From be50810299d004c6e9e7f7f6595a4d9dd5540d8d Mon Sep 17 00:00:00 2001 From: Blake Regalia Date: Sun, 20 Sep 2026 13:16:52 -0700 Subject: [PATCH] Release v0.9.0 --- .github/workflows/audit.yml | 28 + .github/workflows/ci.yml | 111 +- .gitignore | 2 + CBOR.md | 65 +- CLI.md | 523 +- Cargo.lock | 1180 +- Cargo.toml | 37 +- IDS.md | 2 +- INTEROP.md | 17 +- README.md | 54 +- SDK.md | 84 +- crates/sysmlv2-cbor/Cargo.toml | 2 +- crates/sysmlv2-cbor/README.md | 2 +- crates/sysmlv2-cbor/examples/corpus_bench.rs | 5 +- crates/sysmlv2-cbor/src/canonical.rs | 32 +- crates/sysmlv2-cbor/src/cbor.rs | 68 +- crates/sysmlv2-cbor/src/decode.rs | 227 +- crates/sysmlv2-cbor/src/delta.rs | 330 +- crates/sysmlv2-cbor/src/describe.rs | 132 +- crates/sysmlv2-cbor/src/encode.rs | 273 +- crates/sysmlv2-cbor/src/index.rs | 318 +- crates/sysmlv2-cbor/src/lib.rs | 84 +- crates/sysmlv2-cbor/src/resolver.rs | 61 +- crates/sysmlv2-cbor/tests/delta.rs | 115 +- crates/sysmlv2-cbor/tests/describe.rs | 116 +- crates/sysmlv2-cbor/tests/elide.rs | 2 +- crates/sysmlv2-cbor/tests/fuzz.rs | 260 +- crates/sysmlv2-cbor/tests/resolver.rs | 36 + crates/sysmlv2-cbor/tests/roundtrip.rs | 65 +- crates/sysmlv2-cbor/tests/tables.rs | 36 +- crates/sysmlv2-cli/Cargo.toml | 2 +- crates/sysmlv2-cli/src/kpar.rs | 314 +- crates/sysmlv2-cli/src/lib.rs | 5248 + crates/sysmlv2-cli/src/main.rs | 4534 +- crates/sysmlv2-cli/tests/cli.rs | 676 +- .../sysmlv2-cli/tests/fulljson_roundtrip.rs | 2 +- crates/sysmlv2-cli/tests/inprocess.rs | 269 + crates/sysmlv2-cli/tests/prepared_cache.rs | 86 + .../sysmlv2-cli/tests/unit_spelling_switch.rs | 34 + crates/sysmlv2-lint/Cargo.toml | 4 +- crates/sysmlv2-lint/src/json.rs | 444 + crates/sysmlv2-lint/src/lib.rs | 2191 +- crates/sysmlv2-lint/tests/generated.rs | 30 +- crates/sysmlv2-lint/tests/lint.rs | 969 +- crates/sysmlv2-lint/tests/qualified.rs | 62 +- crates/sysmlv2-lsp/Cargo.toml | 1 + crates/sysmlv2-lsp/src/autofix.rs | 38 +- crates/sysmlv2-lsp/src/autoimport.rs | 31 +- crates/sysmlv2-lsp/src/lib.rs | 1298 +- crates/sysmlv2-lsp/src/nav.rs | 810 +- crates/sysmlv2-lsp/src/outline.rs | 37 +- crates/sysmlv2-lsp/src/position.rs | 119 +- crates/sysmlv2-lsp/src/push.rs | 325 +- crates/sysmlv2-lsp/src/tokens.rs | 10 +- crates/sysmlv2-lsp/src/worker.rs | 932 +- crates/sysmlv2-lsp/tests/extras.rs | 149 +- crates/sysmlv2-lsp/tests/lsp.rs | 390 +- crates/sysmlv2-lsp/tests/nav.rs | 100 +- crates/sysmlv2-lsp/tests/outline_corpus.rs | 5 +- crates/sysmlv2-lsp/tests/refactor.rs | 7 +- crates/sysmlv2-lsp/tests/unit_typing.rs | 29 +- crates/sysmlv2-lsp/tests/workspace.rs | 812 +- crates/sysmlv2-model/Cargo.toml | 10 +- crates/sysmlv2-model/build.rs | 2 +- crates/sysmlv2-model/src/ambient.rs | 4 + crates/sysmlv2-model/src/cache_codec.rs | 769 + crates/sysmlv2-model/src/check.rs | 1405 +- crates/sysmlv2-model/src/check/actions.rs | 312 + crates/sysmlv2-model/src/check/chains.rs | 105 + crates/sysmlv2-model/src/check/connectors.rs | 226 + crates/sysmlv2-model/src/check/dimensions.rs | 311 + .../src/check/distinguishability.rs | 617 + crates/sysmlv2-model/src/check/endpoints.rs | 51 + crates/sysmlv2-model/src/check/expressions.rs | 464 + crates/sysmlv2-model/src/check/facts.rs | 457 + .../sysmlv2-model/src/check/facts/id_index.rs | 181 + crates/sysmlv2-model/src/check/invocations.rs | 207 + .../sysmlv2-model/src/check/multiplicities.rs | 84 + .../sysmlv2-model/src/check/relationships.rs | 402 + crates/sysmlv2-model/src/check/scalars.rs | 209 + .../sysmlv2-model/src/check/specialization.rs | 345 + crates/sysmlv2-model/src/check/structural.rs | 668 + crates/sysmlv2-model/src/check/typing.rs | 203 + crates/sysmlv2-model/src/check/values.rs | 172 + crates/sysmlv2-model/src/derived_names.rs | 473 + crates/sysmlv2-model/src/eval.rs | 1485 +- crates/sysmlv2-model/src/flat.rs | 208 + crates/sysmlv2-model/src/flat/rows.rs | 205 + crates/sysmlv2-model/src/full.rs | 1643 +- crates/sysmlv2-model/src/ids.rs | 187 +- crates/sysmlv2-model/src/json.rs | 3980 +- crates/sysmlv2-model/src/json/behavior.rs | 586 + crates/sysmlv2-model/src/json/cases.rs | 133 + crates/sysmlv2-model/src/json/closures.rs | 215 + crates/sysmlv2-model/src/json/derived.rs | 1883 + .../src/json/derived_compositions.rs | 243 + crates/sysmlv2-model/src/json/implied.rs | 258 + crates/sysmlv2-model/src/json/naming.rs | 345 + crates/sysmlv2-model/src/json/scope_table.rs | 260 + crates/sysmlv2-model/src/json/typeops.rs | 417 + .../src/json/unused_imports_tests.rs | 292 + crates/sysmlv2-model/src/layered.rs | 354 + crates/sysmlv2-model/src/lib.rs | 21 + crates/sysmlv2-model/src/libcache.rs | 139 +- crates/sysmlv2-model/src/lift.rs | 1000 +- crates/sysmlv2-model/src/loader.rs | 317 + crates/sysmlv2-model/src/metaclass.rs | 2266 + crates/sysmlv2-model/src/metaclass_tests.rs | 65 + crates/sysmlv2-model/src/model.rs | 282 +- crates/sysmlv2-model/src/prepared.rs | 741 + crates/sysmlv2-model/src/properties.rs | 351 + crates/sysmlv2-model/src/quantity.rs | 239 +- crates/sysmlv2-model/src/rational.rs | 998 + crates/sysmlv2-model/src/render.rs | 21 +- crates/sysmlv2-model/src/semantic_memo.rs | 43 + crates/sysmlv2-model/src/structure.rs | 4 + crates/sysmlv2-parser/Cargo.toml | 4 +- .../examples/derived_correspondence.rs | 129 + crates/sysmlv2-parser/examples/evalstats.rs | 1 + crates/sysmlv2-parser/examples/failstats.rs | 2 +- crates/sysmlv2-parser/examples/fullcheck.rs | 2 +- crates/sysmlv2-parser/examples/liftcheck.rs | 2 +- .../sysmlv2-parser/examples/opensysmlcheck.rs | 55 + crates/sysmlv2-parser/src/lib.rs | 14 +- crates/sysmlv2-parser/tests/apollo.rs | 25 +- crates/sysmlv2-parser/tests/check.rs | 537 +- crates/sysmlv2-parser/tests/closure_policy.rs | 268 + crates/sysmlv2-parser/tests/derived_api.rs | 2299 + .../tests/derived_correspondence.rs | 81 + crates/sysmlv2-parser/tests/derived_parity.rs | 329 + .../tests/distinguishability.rs | 415 + crates/sysmlv2-parser/tests/eval.rs | 579 +- .../tests/eval_unit_spelling_off.rs | 18 + .../tests/fixtures/full-form-baseline.tsv | 10707 ++ .../tests/fixtures/opensysml/LICENSE | 202 + .../tests/fixtures/opensysml/README.md | 38 + .../fixtures/opensysml/baseline-library.json | 5844 + .../tests/fixtures/opensysml/baseline.json | 6327 + .../opensysml/negative-contracts.json | 394 + .../extensions/x01-initial-state-marker.sysml | 8 + .../extensions/x02-choice-pseudostate.sysml | 7 + .../extensions/x03-junction-pseudostate.sysml | 7 + .../extensions/x04-orthogonal-region.sysml | 11 + .../extensions/x05-defer-member.sysml | 8 + .../extensions/x06-history-member.sysml | 7 + .../extensions/x07-transition-to.sysml | 8 + ...x08-require-outside-requirement-body.sysml | 6 + .../grammar/g01-unclosed-package-body.sysml | 3 + .../g02-import-without-visibility.sysml | 7 + .../grammar/g03-alias-without-for.sysml | 5 + .../g04-specialization-without-target.sysml | 4 + .../grammar/g05-typing-without-type.sysml | 4 + .../g06-definition-with-multiplicity.sysml | 4 + .../g07-entry-outside-state-body.sysml | 6 + .../grammar/g08-do-outside-state-body.sysml | 6 + .../g09-value-without-expression.sysml | 4 + .../g10-operator-without-operand.sysml | 4 + .../g11-assignment-without-target.sysml | 6 + .../g12-unterminated-block-comment.sysml | 5 + .../g13-entry-then-without-target.sysml | 6 + .../grammar/g14-connect-without-to.sysml | 8 + .../grammar/g15-keyword-as-name.sysml | 4 + .../grammar/g16-expose-without-name.sysml | 7 + .../grammar/g17-render-without-usage.sysml | 6 + .../g18-require-without-constraint.sysml | 6 + .../grammar/g19-frame-without-concern.sysml | 6 + .../grammar/g20-include-without-target.sysml | 6 + .../g21-filter-without-expression.sysml | 4 + .../grammar/g22-dependency-without-to.sysml | 6 + .../grammar/g23-rep-without-language.sysml | 4 + .../grammar/g24-alias-without-target.sysml | 5 + .../grammar/g25-library-without-package.sysml | 2 + .../grammar/g26-multiplicity-open-range.sysml | 5 + .../grammar/g27-bind-without-right-end.sysml | 8 + .../g28-succession-without-target.sysml | 8 + .../grammar/g29-flow-without-target.sysml | 8 + .../grammar/g30-message-without-target.sysml | 8 + .../grammar/g31-allocate-without-to.sysml | 8 + .../grammar/g32-if-without-condition.sysml | 6 + .../grammar/g33-while-without-condition.sysml | 6 + .../negative/grammar/g34-for-without-in.sysml | 6 + .../grammar/g35-accept-without-payload.sysml | 6 + .../g36-direction-without-feature.sysml | 6 + .../g37-redefines-without-target.sysml | 9 + .../g38-references-without-target.sysml | 7 + ...9-redefinition-symbol-without-target.sysml | 9 + .../grammar/g40-modulo-without-operand.sysml | 4 + .../g41-exponent-without-operand.sysml | 4 + .../grammar/g42-implies-without-operand.sysml | 4 + .../g43-null-coalescing-without-operand.sysml | 4 + .../g44-conditional-without-else.sysml | 4 + ...g45-classification-test-without-type.sysml | 4 + .../grammar/g46-cast-without-type.sysml | 4 + .../g47-prefix-metadata-without-name.sysml | 4 + .../grammar/g48-decision-without-body.sysml | 6 + .../grammar/g49-assign-without-value.sysml | 7 + ...-conjugated-port-typing-without-name.sysml | 7 + .../grammar/g51-real-without-fraction.sysml | 4 + .../grammar/g52-unterminated-string.sysml | 4 + .../g53-range-without-upper-bound.sysml | 4 + .../g54-argument-list-trailing-comma.sysml | 5 + .../g55-feature-chain-trailing-dot.sysml | 6 + ...56-qualified-name-trailing-separator.sysml | 5 + .../g57-unterminated-unrestricted-name.sysml | 4 + .../g58-satisfy-without-reference.sysml | 7 + .../grammar/g59-crosses-without-target.sysml | 7 + .../grammar/g60-alias-keyword-as-name.sysml | 6 + .../g61-actor-outside-requirement-body.sysml | 7 + ...g62-subject-outside-requirement-body.sysml | 7 + .../g63-objective-outside-case-body.sysml | 7 + ...stakeholder-outside-requirement-body.sysml | 7 + .../g65-entry-action-outside-state-body.sysml | 6 + .../g66-render-outside-view-body.sysml | 7 + .../g67-expose-outside-view-body.sysml | 7 + .../g68-definition-in-enumeration-body.sysml | 8 + ...9-calc-body-second-result-expression.sysml | 9 + .../g70-name-before-usage-keyword.sysml | 7 + .../k01-specializes-without-target.kerml | 4 + .../grammar/k02-sysml-keyword-in-kerml.kerml | 4 + .../k03-feature-typing-without-type.kerml | 6 + .../grammar/k04-dangling-visibility.kerml | 4 + .../negative/grammar/k05-unclosed-body.kerml | 3 + .../k06-disjoining-without-target.kerml | 4 + .../k07-conjugation-without-target.kerml | 4 + .../grammar/k08-return-without-feature.kerml | 4 + .../k09-inverting-without-target.kerml | 5 + .../grammar/k10-featuring-without-type.kerml | 3 + ...mespace-prefix-metadata-without-name.kerml | 4 + ...2-multiplicity-subset-without-target.kerml | 4 + .../k13-step-without-declaration.kerml | 4 + .../k14-flow-without-payload-target.kerml | 6 + .../k15-conjugation-without-original.kerml | 3 + .../k16-redefinition-without-target.kerml | 3 + .../grammar/k17-unions-without-target.kerml | 5 + .../k18-connector-end-without-reference.kerml | 8 + .../k19-metadata-typing-without-name.kerml | 6 + ...nction-body-second-result-expression.kerml | 9 + .../k21-name-before-feature-keyword.kerml | 7 + .../semantic/cn01-fork-two-incoming.sysml | 14 + .../semantic/cn02-join-two-outgoing.sysml | 14 + .../semantic/cn03-merge-two-outgoing.sysml | 14 + .../semantic/cn04-decide-two-incoming.sysml | 16 + .../cn05-control-node-outside-action.sysml | 11 + ...06-fork-incoming-target-multiplicity.sysml | 12 + ...07-join-outgoing-source-multiplicity.sysml | 12 + ...8-merge-incoming-source-multiplicity.sysml | 12 + ...-decide-outgoing-target-multiplicity.sysml | 12 + .../k01-two-owned-multiplicities.kerml | 6 + .../semantic/k02-differences-one-type.kerml | 5 + .../semantic/k03-intersects-one-type.kerml | 5 + .../semantic/k04-unions-one-type.kerml | 5 + .../semantic/k05-differences-self.kerml | 5 + .../semantic/k06-intersects-self.kerml | 5 + .../negative/semantic/k07-unions-self.kerml | 5 + .../k08-conjugated-type-specialized.kerml | 6 + .../k09-two-reference-subsettings.kerml | 8 + .../semantic/k10-portion-var-feature.kerml | 6 + .../k11-initial-value-nonvariable.kerml | 6 + .../semantic/k12-chain-through-self.kerml | 7 + .../k13-subsets-inaccessible-feature.kerml | 9 + .../k14-variable-subsets-constant.kerml | 7 + .../semantic/k15-nonend-redefines-end.kerml | 12 + .../semantic/k16-crosses-from-nonend.kerml | 7 + ...k17-crosses-not-through-opposite-end.kerml | 8 + .../k18-cross-feature-type-differs.kerml | 11 + .../k19-cross-feature-not-specializing.kerml | 15 + .../k20-datatype-specializes-class.kerml | 5 + .../k21-class-specializes-datatype.kerml | 5 + .../k22-struct-specializes-behavior.kerml | 5 + .../k23-behavior-specializes-struct.kerml | 5 + .../k24-binary-assoc-three-ends.kerml | 9 + .../negative/semantic/k25-assoc-one-end.kerml | 7 + .../k26-binary-connector-three-ends.kerml | 9 + ...ector-feature-outside-featuring-type.kerml | 9 + .../k28-expr-two-return-parameters.kerml | 8 + ...on-inherits-second-result-expression.kerml | 8 + ...pr-inherits-second-result-expression.kerml | 8 + .../negative/semantic/k31-invoke-class.kerml | 5 + .../semantic/k32-too-many-arguments.kerml | 7 + .../semantic/k33-parameter-bound-twice.kerml | 7 + .../k34-constructor-feature-bound-twice.kerml | 7 + .../k35-metadata-annotates-wrong-kind.kerml | 10 + .../k36-metadata-body-redefines-outside.kerml | 9 + .../k37-multiplicity-bound-not-natural.kerml | 7 + .../k38-flow-end-without-dot-notation.kerml | 9 + .../k39-feature-reference-to-class.kerml | 5 + .../k40-metadata-typed-by-class.kerml | 6 + ...k41-chain-expression-to-nested-class.kerml | 8 + .../semantic/k42-two-cross-subsettings.kerml | 11 + ...tion-states-second-result-expression.kerml | 8 + ...expr-states-second-result-expression.kerml | 8 + .../k45-conjugated-feature-without-type.kerml | 6 + ...6-conjugated-structure-not-an-object.kerml | 7 + ...-chain-through-alias-to-another-type.kerml | 13 + ...-annotating-element-annotates-itself.kerml | 8 + ...49-binding-connector-with-three-ends.kerml | 9 + ...50-inline-cross-feature-also-crosses.kerml | 13 + .../k51-return-parameter-in-classifier.kerml | 7 + .../semantic/k52-two-conjugators.kerml | 6 + ...-boolean-expression-subsets-datatype.kerml | 5 + ...ross-feature-typed-narrower-than-end.kerml | 10 + .../k55-subtype-specific-is-package.kerml | 6 + .../k56-subtype-general-is-package.kerml | 6 + ...bclassifier-subclassifier-is-package.kerml | 6 + ...lassifier-superclassifier-is-feature.kerml | 6 + .../k59-typing-typed-feature-is-package.kerml | 6 + .../k60-typing-typed-feature-is-class.kerml | 6 + .../semantic/k61-typing-type-is-package.kerml | 6 + ...subset-subsetting-feature-is-package.kerml | 6 + ...63-subset-subsetted-feature-is-class.kerml | 6 + ...finition-redefining-feature-is-class.kerml | 6 + ...inition-redefined-feature-is-package.kerml | 6 + ...conjugate-conjugated-type-is-package.kerml | 6 + ...7-conjugate-original-type-is-package.kerml | 6 + ...-inverse-feature-inverted-is-package.kerml | 6 + ...9-inverse-inverting-feature-is-class.kerml | 6 + ...0-disjoint-type-disjoined-is-package.kerml | 6 + ...-disjoint-disjoining-type-is-package.kerml | 6 + ...2-featuring-feature-of-type-is-class.kerml | 6 + ...-featuring-featuring-type-is-package.kerml | 6 + .../s01-action-typed-by-part-def.sysml | 5 + ...2-allocation-typed-by-connection-def.sysml | 11 + .../s03-analysis-typed-by-case-def.sysml | 5 + ...s04-assert-references-non-constraint.sysml | 8 + ...05-assign-to-package-level-attribute.sysml | 7 + .../s06-enum-attribute-two-types.sysml | 6 + .../s07-calc-typed-by-action-def.sysml | 5 + .../s08-case-def-two-objectives.sysml | 8 + .../semantic/s09-case-def-two-subjects.sysml | 8 + .../s10-case-def-subject-not-first.sysml | 8 + .../semantic/s11-case-two-objectives.sysml | 8 + .../semantic/s12-case-two-subjects.sysml | 8 + .../semantic/s13-case-subject-not-first.sysml | 8 + .../s14-case-typed-by-action-def.sysml | 5 + .../s15-connection-typed-by-part-def.sysml | 11 + .../s16-event-references-non-occurrence.sysml | 8 + .../s17-exhibit-references-non-state.sysml | 8 + .../semantic/s18-flow-def-three-ends.sysml | 9 + .../s19-flow-typed-by-connection-def.sysml | 17 + .../s20-include-references-non-use-case.sysml | 8 + .../s21-interface-def-end-not-port.sysml | 10 + ...22-interface-typed-by-connection-def.sysml | 13 + .../s23-metadata-typed-by-part-def.sysml | 7 + .../s24-perform-references-non-action.sysml | 8 + .../s25-port-nested-composite-part.sysml | 10 + .../semantic/s26-port-typed-by-part-def.sysml | 7 + .../s27-rendering-typed-by-part-def.sysml | 5 + ...28-requirement-def-subject-not-first.sysml | 8 + .../s29-requirement-two-subjects.sysml | 8 + .../s30-requirement-subject-not-first.sysml | 8 + ...-requirement-typed-by-constraint-def.sysml | 5 + ...2-satisfy-references-non-requirement.sysml | 7 + ...parallel-state-usage-with-succession.sysml | 8 + .../s34-state-usage-two-entry-actions.sysml | 7 + .../s35-state-typed-by-part-def.sysml | 5 + .../semantic/s36-usage-typed-by-feature.sysml | 4 + ...7-variation-usage-member-not-variant.sysml | 8 + .../s38-use-case-typed-by-case-def.sysml | 5 + .../s39-verification-typed-by-case-def.sysml | 5 + .../s40-view-def-two-renderings.sysml | 8 + .../semantic/s41-view-typed-by-part-def.sysml | 5 + ...2-viewpoint-typed-by-requirement-def.sysml | 5 + .../semantic/s43-assign-to-non-feature.sysml | 7 + .../s44-transition-target-not-action.sysml | 9 + .../s45-snapshot-outside-occurrence.sysml | 5 + .../s46-feature-value-overriding.sysml | 13 + ...-enumeration-specializes-enumeration.sysml | 8 + .../s48-after-trigger-not-duration.sysml | 8 + .../s49-at-trigger-not-time-instant.sysml | 11 + .../s50-when-trigger-not-boolean.sysml | 10 + ...value-body-typed-outside-enumeration.sysml | 6 + .../semantic/s52-variant-port-composite.sysml | 16 + .../s80-constant-attribute-not-variable.sysml | 7 + ...guarded-succession-guard-not-boolean.sysml | 8 + ...tion-states-second-result-expression.sysml | 6 + ...sage-states-second-result-expression.sysml | 11 + ...sage-states-second-result-expression.sysml | 7 + ...nt-inherits-second-result-expression.sysml | 8 + .../semantic/s86-end-with-direction.sysml | 7 + .../s87-end-derived-or-abstract.sysml | 7 + ...ross-feature-typed-narrower-than-end.sysml | 10 + ...s89-case-def-inherits-two-objectives.sysml | 7 + ...equirement-def-inherits-two-subjects.sysml | 6 + ...s91-case-references-second-objective.sysml | 7 + ...equirement-references-second-subject.sysml | 6 + ...t-through-owner-of-unnamed-assertion.sysml | 14 + .../semantic/send-constructor-non-type.sysml | 11 + .../semantic/send-payload-non-behavior.sysml | 9 + .../semantic/send-subaction-no-payload.sysml | 11 + .../xpect/p01-public-root-import.kerml | 5 + .../xpect/p02-association-end-two-types.kerml | 9 + .../xpect/p03-variable-in-datatype.kerml | 6 + .../xpect/p04-nonunique-subsets-unique.kerml | 7 + .../xpect/p05-single-chaining-feature.kerml | 7 + .../xpect/p06-private-member-reference.kerml | 7 + .../xpect/p07-extraneous-closing-brace.kerml | 5 + .../xpect/p08-variant-outside-variation.sysml | 8 + .../p09-variation-member-not-variant.sysml | 7 + .../p10-variation-specializes-variation.sysml | 7 + .../p11-metadata-body-not-evaluable.sysml | 11 + .../xpect/p12-filter-integer-condition.sysml | 4 + .../xpect/p13-state-two-entry-actions.sysml | 7 + .../xpect/p14-requirement-two-subjects.sysml | 8 + .../p15-attribute-typed-by-part-def.sysml | 5 + .../p16-part-typed-by-attribute-def.sysml | 5 + .../p17-calc-two-return-parameters.sysml | 8 + .../negative/xpect/p18-enum-two-types.sysml | 6 + ...enum-value-typed-outside-enumeration.sysml | 8 + .../p19-parallel-state-with-transition.sysml | 8 + .../xpect/p20-connection-with-one-end.sysml | 8 + .../p21-filter-constructor-condition.sysml | 7 + ...p22-filter-not-model-level-evaluable.sysml | 8 + ...metadata-body-feature-not-redefining.sysml | 12 + .../xpect/p24-metadata-abstract-type.sysml | 6 + .../p25-two-individual-definitions.sysml | 8 + .../p26-port-def-nonreferential-usage.sysml | 7 + .../xpect/p27-interface-end-not-port.sysml | 13 + .../p28-package-level-feature-redefined.sysml | 6 + .../xpect/p29-verify-outside-objective.sysml | 8 + .../xpect/p30-two-view-renderings.sysml | 8 + ...-redefinition-incompatible-direction.sysml | 11 + ...p32-redefinition-same-featuring-type.sysml | 11 + .../p33-individual-typed-by-plain-def.sysml | 5 + .../xpect/p34-accepter-source-not-state.sysml | 9 + .../probes/validateActionUsageType.sysml | 3 + .../validateActorMembershipOwningType.sysml | 3 + .../probes/validateAllocationUsageType.sysml | 3 + .../validateAnalysisCaseUsageType.sysml | 3 + ...eAnnotationAnnotatedElementOwnership.kerml | 6 + ...lidateAssertConstraintUsageReference.sysml | 3 + ...alidateAssignmentActionUsageReferent.sysml | 3 + ...mentActionUsageReferentIsTimeVarying.sysml | 3 + ...idateAssociationBinarySpecialization.kerml | 6 + .../probes/validateAssociationEndTypes.kerml | 6 + .../validateAssociationRelatedTypes.kerml | 6 + ...alidateAttributeUsageEnumerationType.sysml | 3 + .../probes/validateAttributeUsageType.sysml | 3 + .../validateBehaviorSpecialization.kerml | 6 + .../validateBindingConnectorIsBinary.kerml | 9 + ...idateBindingConnectorTypeConformance.kerml | 5 + ...ndingConnectorTypeConformance.result.kerml | 7 + ...dingConnectorTypeConformance.satisfy.sysml | 9 + ...dingConnectorTypeConformance.subject.sysml | 6 + .../probes/validateCalculationUsageType.sysml | 3 + ...lidateCaseDefinitionOnlyOneObjective.sysml | 3 + ...validateCaseDefinitionOnlyOneSubject.sysml | 3 + ...seDefinitionSubjectParameterPosition.sysml | 3 + .../validateCaseUsageOnlyOneObjective.sysml | 3 + .../validateCaseUsageOnlyOneSubject.sysml | 3 + ...ateCaseUsageSubjectParameterPosition.sysml | 3 + .../probes/validateCaseUsageType.sysml | 3 + ...lidateClassSpecialization.connection.sysml | 6 + .../probes/validateClassSpecialization.kerml | 6 + .../validateClassSpecialization.subsets.kerml | 7 + .../probes/validateClassSpecialization.sysml | 3 + .../validateClassifierDefaultSupertype.kerml | 6 + .../probes/validateConnectionUsageType.sysml | 3 + ...alidateConnectorBinarySpecialization.kerml | 8 + .../validateConnectorRelatedFeatures.sysml | 9 + .../validateConnectorTypeFeaturing.kerml | 6 + ...essionNoDuplicateFeatureRedefinition.kerml | 3 + ...lidateControlNodeIncomingSuccessions.sysml | 3 + ...lidateControlNodeOutgoingSuccessions.sysml | 3 + .../validateControlNodeOwningType.sysml | 3 + ...alidateCrossSubsettingCrossedFeature.kerml | 7 + ...lidateCrossSubsettingCrossingFeature.kerml | 5 + .../validateDataTypeSpecialization.kerml | 6 + ...lidateDataTypeSpecialization.subsets.kerml | 7 + .../validateDataTypeSpecialization.sysml | 3 + ...idateDecisionNodeIncomingSuccessions.sysml | 6 + ...idateDecisionNodeOutgoingSuccessions.sysml | 3 + ...alidateDefinitionVariationMembership.sysml | 3 + ...ateDefinitionVariationSpecialization.sysml | 3 + ...dateElementFilterMembershipIsBoolean.kerml | 5 + ...ilterMembershipIsModelLevelEvaluable.sysml | 6 + .../probes/validateEnumerationUsageType.sysml | 3 + ...validateEventOccurrenceUsageReferent.sysml | 3 + .../validateExhibitStateUsageReference.sysml | 3 + .../validateExposeOwningNamespace.sysml | 3 + ...ExpressionResultExpressionMembership.kerml | 7 + ...ExpressionResultExpressionMembership.sysml | 12 + ...sionResultExpressionMembership.typed.kerml | 9 + ...eExpressionResultParameterMembership.kerml | 5 + ...ureChainExpressionFeatureConformance.kerml | 9 + ...ateFeatureChainingFeatureConformance.kerml | 10 + ...validateFeatureChainingFeatureNotOne.kerml | 7 + ...lidateFeatureChainingFeaturesNotSelf.kerml | 8 + .../validateFeatureConstantIsVariable.sysml | 6 + ...ateFeatureCrossFeatureSpecialization.kerml | 14 + .../validateFeatureCrossFeatureType.kerml | 8 + ...alidateFeatureEndFeatureMultiplicity.kerml | 6 + .../validateFeatureEndNoDirection.sysml | 6 + ...NotDerivedAbstractCompositeOrPortion.sysml | 6 + .../probes/validateFeatureHasType.kerml | 6 + .../probes/validateFeatureIsVariable.kerml | 5 + .../validateFeatureOwnedCrossSubsetting.kerml | 6 + ...idateFeatureOwnedReferenceSubsetting.kerml | 5 + .../validateFeaturePortionNotVariable.kerml | 5 + ...ReferenceExpressionReferentIsFeature.kerml | 6 + .../validateFeatureValueIsInitial.kerml | 6 + .../validateFeatureValueOverriding.kerml | 11 + .../validateFeatureValueOverriding.sysml | 3 + ...validateFlowDefinitionConnectionEnds.sysml | 3 + .../validateFlowEndImplicitSubsetting.kerml | 9 + .../validateFlowEndImplicitSubsetting.sysml | 9 + .../probes/validateFlowEndSubsetting.kerml | 7 + .../probes/validateFlowUsageType.sysml | 3 + .../validateForkNodeIncomingSuccessions.sysml | 3 + ...teFunctionResultExpressionMembership.kerml | 7 + ...tExpressionMembership.specialization.kerml | 9 + ...teFunctionResultExpressionMembership.sysml | 7 + ...ateFunctionResultParameterMembership.kerml | 5 + .../validateImportTopLevelVisibility.kerml | 4 + ...validateIncludeUseCaseUsageReference.sysml | 3 + ...tantiationExpressionInstantiatedType.kerml | 3 + .../validateInterfaceDefinitionEnd.sysml | 3 + .../probes/validateInterfaceUsageEnd.sysml | 14 + .../probes/validateInterfaceUsageType.sysml | 3 + ...InvocationExpressionInstantiatedType.kerml | 6 + ...sionNoDuplicateParameterRedefinition.kerml | 8 + ...ationExpressionParameterRedefinition.kerml | 6 + .../validateJoinNodeOutgoingSuccessions.sysml | 3 + .../validateLibraryPackageNotStandard.kerml | 5 + ...validateMergeNodeIncomingSuccessions.sysml | 3 + ...validateMergeNodeOutgoingSuccessions.sysml | 3 + ...idateMetadataFeatureAnnotatedElement.kerml | 6 + .../probes/validateMetadataFeatureBody.kerml | 7 + .../validateMetadataFeatureMetadata.kerml | 6 + ...teMetadataFeatureMetadataNotAbstract.kerml | 6 + .../probes/validateMetadataUsageType.sysml | 6 + ...validateMultiplicityRangeResultTypes.kerml | 5 + .../validateNamespaceDistinguishablity.kerml | 6 + ...alidateObjectiveMembershipOwningType.sysml | 3 + ...eOccurrenceUsageIndividualDefinition.sysml | 3 + ...lidateOccurrenceUsageIndividualUsage.sysml | 3 + .../validateOccurrenceUsageIsPortion.sysml | 3 + .../probes/validateOccurrenceUsageType.sysml | 3 + ...ateOperatorExpressionBracketOperator.kerml | 6 + ...ateOperatorExpressionCastConformance.kerml | 6 + .../validateOperatorExpressionQuantity.sysml | 5 + .../validateOwnedDifferencingNotOne.kerml | 6 + .../validateOwnedIntersectingNotOne.kerml | 6 + .../probes/validateOwnedUnioningNotOne.kerml | 6 + .../validatePerformActionUsageReference.sysml | 3 + ...ortDefinitionOwnedUsagesNotComposite.sysml | 3 + .../probes/validatePortUsageIsReference.sysml | 3 + ...atePortUsageNestedUsagesNotComposite.sysml | 3 + .../probes/validatePortUsageType.sysml | 3 + ...dateRedefinitionDirectionConformance.kerml | 6 + .../validateRedefinitionEndConformance.kerml | 7 + .../validateRedefinitionFeaturingTypes.kerml | 6 + ...eRedefinitionMultiplicityConformance.kerml | 6 + .../probes/validateRenderingUsageType.sysml | 3 + ...rementConstraintMembershipOwningType.sysml | 3 + ...eRequirementDefinitionOnlyOneSubject.sysml | 3 + ...ntDefinitionSubjectParameterPosition.sysml | 3 + ...lidateRequirementUsageOnlyOneSubject.sysml | 3 + ...irementUsageSubjectParameterPosition.sysml | 3 + .../probes/validateRequirementUsageType.sysml | 3 + ...mentVerificationMembershipOwningType.sysml | 3 + ...eReturnParameterMembershipOwningType.kerml | 6 + ...dateSatisfyRequirementUsageReference.sysml | 3 + ...lidateSendActionUsagePayloadArgument.sysml | 3 + .../validateSendActionUsageReceiver.sysml | 3 + ...eSpecializationSpecificNotConjugated.kerml | 6 + ...lizationSpecificNotConjugated.subset.kerml | 7 + ...idateStakeholderMembershipOwningType.sysml | 3 + ...ateStateDefinitionParallelSubactions.sysml | 3 + ...validateStateDefinitionSubactionKind.sysml | 3 + ...teStateSubactionMembershioOwningType.sysml | 3 + ...validateStateUsageParallelSubactions.sysml | 3 + .../validateStateUsageSubactionKind.sysml | 3 + .../probes/validateStateUsageType.sysml | 3 + .../validateStructureSpecialization.kerml | 6 + .../validateSubjectMembershipOwningType.sysml | 3 + ...alidateSubsettingConstantConformance.kerml | 8 + .../validateSubsettingFeaturingTypes.kerml | 6 + ...ateSubsettingMultiplicityConformance.kerml | 6 + ...idateSubsettingUniquenessConformance.kerml | 6 + ...tionFeatureMembershipGuardExpression.sysml | 6 + .../validateTransitionUsageSuccession.sysml | 10 + ...alidateTransitionUsageTriggerActions.sysml | 10 + ...TriggerInvocationActionAfterArgument.sysml | 3 + ...ateTriggerInvocationActionAtArgument.sysml | 3 + ...eTriggerInvocationActionWhenArgument.sysml | 3 + .../validateTypeAtMostOneConjugator.kerml | 6 + ...validateTypeDifferencingTypesNotSelf.kerml | 6 + ...validateTypeIntersectingTypesNotSelf.kerml | 6 + .../validateTypeOwnedMultiplicity.kerml | 5 + .../validateTypeUnioningTypesNotSelf.kerml | 6 + .../opensysml/probes/validateUsageType.sysml | 5 + .../validateUsageVariationMembership.sysml | 3 + ...validateUsageVariationSpecialization.sysml | 3 + .../probes/validateUseCaseUsageType.sysml | 3 + ...teVariationMembershipOwningNamespace.sysml | 3 + .../validateVerificationCaseUsageType.sysml | 3 + ...teViewDefinitionOnlyOnvViewRendering.sysml | 3 + ...ateViewRenderingMembershipOwningType.sysml | 3 + .../validateViewUsageOnlyOneRendering.sysml | 3 + .../probes/validateViewUsageType.sysml | 3 + .../probes/validateViewpointUsageType.sysml | 3 + .../tests/fixtures/opensysml/provenance.json | 2316 + .../fixtures/opensysml/static-contracts.json | 1055 + crates/sysmlv2-parser/tests/format.rs | 420 + crates/sysmlv2-parser/tests/full_baseline.rs | 257 + crates/sysmlv2-parser/tests/full_json.rs | 917 +- crates/sysmlv2-parser/tests/fuzz.rs | 163 + crates/sysmlv2-parser/tests/goldens.rs | 7 +- .../goldens/expected/FeatureChaining.json | 2 +- .../goldens/expected/PartDefinition.json | 1 + crates/sysmlv2-parser/tests/grammar_edge.rs | 14 + crates/sysmlv2-parser/tests/ids_derive.rs | 54 + .../sysmlv2-parser/tests/inherited_battery.rs | 341 + crates/sysmlv2-parser/tests/json.rs | 34 + crates/sysmlv2-parser/tests/lexer.rs | 16 + crates/sysmlv2-parser/tests/libcache.rs | 100 +- crates/sysmlv2-parser/tests/model.rs | 691 + crates/sysmlv2-parser/tests/negative.rs | 16 +- .../tests/negative/flow_payloads.kerml | 2 +- crates/sysmlv2-parser/tests/opensysml.rs | 144 + crates/sysmlv2-parser/tests/parser.rs | 439 +- .../sysmlv2-parser/tests/prepared_library.rs | 352 + crates/sysmlv2-parser/tests/query.rs | 35 + crates/sysmlv2-parser/tests/refs.rs | 40 +- crates/sysmlv2-parser/tests/roundtrip.rs | 484 +- crates/sysmlv2-parser/tests/spelling.rs | 149 + crates/sysmlv2-parser/tests/static_rules.rs | 790 + crates/sysmlv2-parser/tests/support/census.rs | 141 + crates/sysmlv2-parser/tests/xmi_audit.rs | 92 +- crates/sysmlv2-py/Cargo.toml | 12 +- crates/sysmlv2-py/README.md | 6 +- crates/sysmlv2-py/src/lib.rs | 477 +- crates/sysmlv2-py/tests/smoke.py | 110 +- crates/sysmlv2-solve/Cargo.toml | 4 +- crates/sysmlv2-solve/examples/solvestats.rs | 8 +- crates/sysmlv2-solve/examples/unknowns.rs | 2 +- crates/sysmlv2-solve/src/ival.rs | 1381 +- crates/sysmlv2-solve/src/lib.rs | 255 +- crates/sysmlv2-solve/src/term.rs | 45 +- crates/sysmlv2-solve/src/translate.rs | 243 +- crates/sysmlv2-solve/src/z3.rs | 114 +- crates/sysmlv2-solve/tests/apollo.rs | 3 + crates/sysmlv2-solve/tests/corpus.rs | 23 +- crates/sysmlv2-solve/tests/prepared.rs | 41 + crates/sysmlv2-solve/tests/propagate.rs | 265 + crates/sysmlv2-solve/tests/solve.rs | 85 +- crates/sysmlv2-syntax/Cargo.toml | 5 + crates/sysmlv2-syntax/src/ast.rs | 244 +- crates/sysmlv2-syntax/src/check.rs | 1 + crates/sysmlv2-syntax/src/diag.rs | 110 +- crates/sysmlv2-syntax/src/lexer.rs | 29 +- crates/sysmlv2-syntax/src/lib.rs | 2 +- crates/sysmlv2-syntax/src/name.rs | 165 +- crates/sysmlv2-syntax/src/parser.rs | 828 +- crates/sysmlv2-syntax/src/print.rs | 345 +- crates/sysmlv2-syntax/src/span.rs | 23 +- crates/sysmlv2-syntax/src/token.rs | 4 + crates/sysmlv2-transform/Cargo.toml | 6 +- .../sysmlv2-transform/examples/importbench.rs | 62 + .../examples/preparedbench.rs | 84 + crates/sysmlv2-transform/src/eligibility.rs | 27 +- crates/sysmlv2-transform/src/lib.rs | 2420 +- crates/sysmlv2-transform/src/projection.rs | 11 +- .../src/unused_imports_tests.rs | 227 + .../sysmlv2-transform/tests/cbor_session.rs | 64 +- crates/sysmlv2-transform/tests/eligibility.rs | 18 + crates/sysmlv2-transform/tests/json_path.rs | 17 +- .../tests/library_subjects.rs | 258 + .../sysmlv2-transform/tests/line_endings.rs | 91 + crates/sysmlv2-transform/tests/minimize.rs | 13 + .../sysmlv2-transform/tests/parsed_sources.rs | 148 + .../sysmlv2-transform/tests/payload_loader.rs | 599 + .../tests/prepared_sources.rs | 35 + .../tests/refusal_message.rs | 24 +- crates/sysmlv2-transform/tests/transform.rs | 942 + .../sysmlv2-transform/tests/unused_imports.rs | 41 + crates/sysmlv2-viz/Cargo.toml | 7 +- crates/sysmlv2-viz/README.md | 22 +- crates/sysmlv2-viz/examples/vizsweep.rs | 5 +- crates/sysmlv2-viz/src/behavior.rs | 160 +- crates/sysmlv2-viz/src/case.rs | 41 +- crates/sysmlv2-viz/src/graph.rs | 204 +- crates/sysmlv2-viz/src/interconnect.rs | 156 +- crates/sysmlv2-viz/src/lib.rs | 352 +- crates/sysmlv2-viz/tests/emitter_walks.rs | 90 + .../sysmlv2-viz/tests/endpoint_semantics.rs | 344 + crates/sysmlv2-viz/tests/escaping.rs | 233 + crates/sysmlv2-viz/tests/options.rs | 144 + crates/sysmlv2-viz/tests/viz.rs | 181 +- crates/sysmlv2-wasm/README.md | 62 +- crates/sysmlv2-wasm/npm/build.mjs | 71 +- crates/sysmlv2-wasm/npm/smoke.mjs | 61 +- .../sysmlv2-wasm/src/bin/gen_stdlib_bundle.rs | 10 +- crates/sysmlv2-wasm/src/lib.rs | 1075 +- crates/sysmlv2-wasm/tests/api.rs | 711 +- crates/sysmlv2-wasm/tests/prepared_library.rs | 178 + crates/sysmlv2-wasm/tests/stack.rs | 214 + editors/vscode/README.md | 5 +- editors/vscode/package.json | 4 +- local-packages/README.md | 32 +- local-packages/Svelte.provenance.json | 4 +- local-packages/SvelteKit.provenance.json | 4 +- local-packages/Template.provenance.json | 4 +- local-packages/Web.provenance.json | 23 +- local-packages/Web.sysml | 25 +- local-packages/WebApp.provenance.json | 4 +- spec-refs/README.md | 11 +- spec-refs/derived-correspondence.json | 136567 +++++++++++++++ spec-refs/derived-properties.json | 10104 ++ spec-refs/derived-properties.md | 304 + tools/derived_census.py | 558 + tools/gen_metaclass_hierarchy.py | 130 + 712 files changed, 241712 insertions(+), 11633 deletions(-) create mode 100644 .github/workflows/audit.yml create mode 100644 crates/sysmlv2-cli/src/lib.rs create mode 100644 crates/sysmlv2-cli/tests/inprocess.rs create mode 100644 crates/sysmlv2-cli/tests/prepared_cache.rs create mode 100644 crates/sysmlv2-cli/tests/unit_spelling_switch.rs create mode 100644 crates/sysmlv2-lint/src/json.rs create mode 100644 crates/sysmlv2-model/src/cache_codec.rs create mode 100644 crates/sysmlv2-model/src/check/actions.rs create mode 100644 crates/sysmlv2-model/src/check/chains.rs create mode 100644 crates/sysmlv2-model/src/check/connectors.rs create mode 100644 crates/sysmlv2-model/src/check/dimensions.rs create mode 100644 crates/sysmlv2-model/src/check/distinguishability.rs create mode 100644 crates/sysmlv2-model/src/check/endpoints.rs create mode 100644 crates/sysmlv2-model/src/check/expressions.rs create mode 100644 crates/sysmlv2-model/src/check/facts.rs create mode 100644 crates/sysmlv2-model/src/check/facts/id_index.rs create mode 100644 crates/sysmlv2-model/src/check/invocations.rs create mode 100644 crates/sysmlv2-model/src/check/multiplicities.rs create mode 100644 crates/sysmlv2-model/src/check/relationships.rs create mode 100644 crates/sysmlv2-model/src/check/scalars.rs create mode 100644 crates/sysmlv2-model/src/check/specialization.rs create mode 100644 crates/sysmlv2-model/src/check/structural.rs create mode 100644 crates/sysmlv2-model/src/check/typing.rs create mode 100644 crates/sysmlv2-model/src/check/values.rs create mode 100644 crates/sysmlv2-model/src/derived_names.rs create mode 100644 crates/sysmlv2-model/src/flat.rs create mode 100644 crates/sysmlv2-model/src/flat/rows.rs create mode 100644 crates/sysmlv2-model/src/json/behavior.rs create mode 100644 crates/sysmlv2-model/src/json/cases.rs create mode 100644 crates/sysmlv2-model/src/json/closures.rs create mode 100644 crates/sysmlv2-model/src/json/derived.rs create mode 100644 crates/sysmlv2-model/src/json/derived_compositions.rs create mode 100644 crates/sysmlv2-model/src/json/implied.rs create mode 100644 crates/sysmlv2-model/src/json/naming.rs create mode 100644 crates/sysmlv2-model/src/json/scope_table.rs create mode 100644 crates/sysmlv2-model/src/json/typeops.rs create mode 100644 crates/sysmlv2-model/src/json/unused_imports_tests.rs create mode 100644 crates/sysmlv2-model/src/layered.rs create mode 100644 crates/sysmlv2-model/src/loader.rs create mode 100644 crates/sysmlv2-model/src/metaclass.rs create mode 100644 crates/sysmlv2-model/src/metaclass_tests.rs create mode 100644 crates/sysmlv2-model/src/prepared.rs create mode 100644 crates/sysmlv2-model/src/properties.rs create mode 100644 crates/sysmlv2-model/src/rational.rs create mode 100644 crates/sysmlv2-model/src/semantic_memo.rs create mode 100644 crates/sysmlv2-parser/examples/derived_correspondence.rs create mode 100644 crates/sysmlv2-parser/examples/opensysmlcheck.rs create mode 100644 crates/sysmlv2-parser/tests/closure_policy.rs create mode 100644 crates/sysmlv2-parser/tests/derived_api.rs create mode 100644 crates/sysmlv2-parser/tests/derived_correspondence.rs create mode 100644 crates/sysmlv2-parser/tests/derived_parity.rs create mode 100644 crates/sysmlv2-parser/tests/distinguishability.rs create mode 100644 crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/LICENSE create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/README.md create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/baseline-library.json create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/baseline.json create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative-contracts.json create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x01-initial-state-marker.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x02-choice-pseudostate.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x03-junction-pseudostate.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x04-orthogonal-region.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x05-defer-member.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x06-history-member.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x07-transition-to.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x08-require-outside-requirement-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g01-unclosed-package-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g02-import-without-visibility.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g03-alias-without-for.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g04-specialization-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g05-typing-without-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g06-definition-with-multiplicity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g07-entry-outside-state-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g08-do-outside-state-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g09-value-without-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g10-operator-without-operand.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g11-assignment-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g12-unterminated-block-comment.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g13-entry-then-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g14-connect-without-to.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g15-keyword-as-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g16-expose-without-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g17-render-without-usage.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g18-require-without-constraint.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g19-frame-without-concern.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g20-include-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g21-filter-without-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g22-dependency-without-to.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g23-rep-without-language.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g24-alias-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g25-library-without-package.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g26-multiplicity-open-range.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g27-bind-without-right-end.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g28-succession-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g29-flow-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g30-message-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g31-allocate-without-to.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g32-if-without-condition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g33-while-without-condition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g34-for-without-in.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g35-accept-without-payload.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g36-direction-without-feature.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g37-redefines-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g38-references-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g39-redefinition-symbol-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g40-modulo-without-operand.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g41-exponent-without-operand.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g42-implies-without-operand.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g43-null-coalescing-without-operand.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g44-conditional-without-else.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g45-classification-test-without-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g46-cast-without-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g47-prefix-metadata-without-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g48-decision-without-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g49-assign-without-value.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g50-conjugated-port-typing-without-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g51-real-without-fraction.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g52-unterminated-string.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g53-range-without-upper-bound.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g54-argument-list-trailing-comma.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g55-feature-chain-trailing-dot.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g56-qualified-name-trailing-separator.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g57-unterminated-unrestricted-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g58-satisfy-without-reference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g59-crosses-without-target.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g60-alias-keyword-as-name.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g61-actor-outside-requirement-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g62-subject-outside-requirement-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g63-objective-outside-case-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g64-stakeholder-outside-requirement-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g65-entry-action-outside-state-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g66-render-outside-view-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g67-expose-outside-view-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g68-definition-in-enumeration-body.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g69-calc-body-second-result-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g70-name-before-usage-keyword.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k01-specializes-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k02-sysml-keyword-in-kerml.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k03-feature-typing-without-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k04-dangling-visibility.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k05-unclosed-body.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k06-disjoining-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k07-conjugation-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k08-return-without-feature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k09-inverting-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k10-featuring-without-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k11-namespace-prefix-metadata-without-name.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k12-multiplicity-subset-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k13-step-without-declaration.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k14-flow-without-payload-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k15-conjugation-without-original.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k16-redefinition-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k17-unions-without-target.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k18-connector-end-without-reference.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k19-metadata-typing-without-name.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k20-function-body-second-result-expression.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k21-name-before-feature-keyword.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn01-fork-two-incoming.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn02-join-two-outgoing.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn03-merge-two-outgoing.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn04-decide-two-incoming.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn05-control-node-outside-action.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn06-fork-incoming-target-multiplicity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn07-join-outgoing-source-multiplicity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn08-merge-incoming-source-multiplicity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k01-two-owned-multiplicities.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k02-differences-one-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k03-intersects-one-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k04-unions-one-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k05-differences-self.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k06-intersects-self.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k07-unions-self.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k08-conjugated-type-specialized.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k09-two-reference-subsettings.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k10-portion-var-feature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k11-initial-value-nonvariable.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k12-chain-through-self.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k13-subsets-inaccessible-feature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k14-variable-subsets-constant.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k15-nonend-redefines-end.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k16-crosses-from-nonend.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k17-crosses-not-through-opposite-end.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k18-cross-feature-type-differs.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k19-cross-feature-not-specializing.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k20-datatype-specializes-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k21-class-specializes-datatype.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k22-struct-specializes-behavior.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k23-behavior-specializes-struct.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k24-binary-assoc-three-ends.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k25-assoc-one-end.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k26-binary-connector-three-ends.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k27-connector-feature-outside-featuring-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k28-expr-two-return-parameters.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k29-function-inherits-second-result-expression.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k30-expr-inherits-second-result-expression.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k31-invoke-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k32-too-many-arguments.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k33-parameter-bound-twice.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k34-constructor-feature-bound-twice.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k35-metadata-annotates-wrong-kind.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k36-metadata-body-redefines-outside.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k37-multiplicity-bound-not-natural.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k38-flow-end-without-dot-notation.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k39-feature-reference-to-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k40-metadata-typed-by-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k41-chain-expression-to-nested-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k42-two-cross-subsettings.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k45-conjugated-feature-without-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k46-conjugated-structure-not-an-object.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k48-annotating-element-annotates-itself.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k49-binding-connector-with-three-ends.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k50-inline-cross-feature-also-crosses.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k51-return-parameter-in-classifier.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k52-two-conjugators.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k53-boolean-expression-subsets-datatype.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k55-subtype-specific-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k56-subtype-general-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k57-subclassifier-subclassifier-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k59-typing-typed-feature-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k60-typing-typed-feature-is-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k61-typing-type-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k62-subset-subsetting-feature-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k63-subset-subsetted-feature-is-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k64-redefinition-redefining-feature-is-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k65-redefinition-redefined-feature-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k66-conjugate-conjugated-type-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k67-conjugate-original-type-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k68-inverse-feature-inverted-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k69-inverse-inverting-feature-is-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k70-disjoint-type-disjoined-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k71-disjoint-disjoining-type-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k72-featuring-feature-of-type-is-class.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k73-featuring-featuring-type-is-package.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s01-action-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s02-allocation-typed-by-connection-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s03-analysis-typed-by-case-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s04-assert-references-non-constraint.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s05-assign-to-package-level-attribute.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s06-enum-attribute-two-types.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s07-calc-typed-by-action-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s08-case-def-two-objectives.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s09-case-def-two-subjects.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s10-case-def-subject-not-first.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s11-case-two-objectives.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s12-case-two-subjects.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s13-case-subject-not-first.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s14-case-typed-by-action-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s15-connection-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s16-event-references-non-occurrence.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s17-exhibit-references-non-state.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s18-flow-def-three-ends.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s19-flow-typed-by-connection-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s20-include-references-non-use-case.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s21-interface-def-end-not-port.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s22-interface-typed-by-connection-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s23-metadata-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s24-perform-references-non-action.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s25-port-nested-composite-part.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s26-port-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s27-rendering-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s28-requirement-def-subject-not-first.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s29-requirement-two-subjects.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s30-requirement-subject-not-first.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s31-requirement-typed-by-constraint-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s32-satisfy-references-non-requirement.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s33-parallel-state-usage-with-succession.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s34-state-usage-two-entry-actions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s35-state-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s36-usage-typed-by-feature.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s37-variation-usage-member-not-variant.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s38-use-case-typed-by-case-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s39-verification-typed-by-case-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s40-view-def-two-renderings.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s41-view-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s43-assign-to-non-feature.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s44-transition-target-not-action.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s45-snapshot-outside-occurrence.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s46-feature-value-overriding.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s47-enumeration-specializes-enumeration.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s48-after-trigger-not-duration.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s49-at-trigger-not-time-instant.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s50-when-trigger-not-boolean.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s52-variant-port-composite.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s80-constant-attribute-not-variable.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s81-guarded-succession-guard-not-boolean.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s86-end-with-direction.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s87-end-derived-or-abstract.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s89-case-def-inherits-two-objectives.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s90-requirement-def-inherits-two-subjects.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s91-case-references-second-objective.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s92-requirement-references-second-subject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-constructor-non-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-payload-non-behavior.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-subaction-no-payload.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p01-public-root-import.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p02-association-end-two-types.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p03-variable-in-datatype.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p04-nonunique-subsets-unique.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p05-single-chaining-feature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p06-private-member-reference.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p07-extraneous-closing-brace.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p08-variant-outside-variation.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p09-variation-member-not-variant.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p10-variation-specializes-variation.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p11-metadata-body-not-evaluable.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p12-filter-integer-condition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p13-state-two-entry-actions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p14-requirement-two-subjects.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p15-attribute-typed-by-part-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p16-part-typed-by-attribute-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p17-calc-two-return-parameters.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-two-types.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-value-typed-outside-enumeration.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p19-parallel-state-with-transition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p20-connection-with-one-end.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p21-filter-constructor-condition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p22-filter-not-model-level-evaluable.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p23-metadata-body-feature-not-redefining.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p24-metadata-abstract-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p25-two-individual-definitions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p26-port-def-nonreferential-usage.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p27-interface-end-not-port.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p28-package-level-feature-redefined.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p29-verify-outside-objective.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p30-two-view-renderings.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p31-redefinition-incompatible-direction.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p32-redefinition-same-featuring-type.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p33-individual-typed-by-plain-def.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p34-accepter-source-not-state.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActionUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActorMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAllocationUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnalysisCaseUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnnotationAnnotatedElementOwnership.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssertConstraintUsageReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferent.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationBinarySpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationEndTypes.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationRelatedTypes.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageEnumerationType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBehaviorSpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorIsBinary.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.result.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.satisfy.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.subject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCalculationUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneObjective.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneSubject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionSubjectParameterPosition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneObjective.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneSubject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageSubjectParameterPosition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.connection.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.subsets.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassifierDefaultSupertype.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectionUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorBinarySpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorRelatedFeatures.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorTypeFeaturing.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeIncomingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOutgoingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossedFeature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossingFeature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.subsets.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeIncomingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeOutgoingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationMembership.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationSpecialization.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsBoolean.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEnumerationUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEventOccurrenceUsageReferent.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExhibitStateUsageReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExposeOwningNamespace.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.typed.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultParameterMembership.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainExpressionFeatureConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureNotOne.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeaturesNotSelf.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureConstantIsVariable.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureSpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureType.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndFeatureMultiplicity.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNoDirection.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureHasType.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureIsVariable.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedCrossSubsetting.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedReferenceSubsetting.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeaturePortionNotVariable.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureReferenceExpressionReferentIsFeature.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueIsInitial.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowDefinitionConnectionEnds.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndSubsetting.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateForkNodeIncomingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.specialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultParameterMembership.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateImportTopLevelVisibility.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateIncludeUseCaseUsageReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInstantiationExpressionInstantiatedType.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceDefinitionEnd.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageEnd.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionInstantiatedType.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionParameterRedefinition.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateJoinNodeOutgoingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateLibraryPackageNotStandard.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeIncomingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeOutgoingSuccessions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureAnnotatedElement.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureBody.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadata.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadataNotAbstract.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMultiplicityRangeResultTypes.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateNamespaceDistinguishablity.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateObjectiveMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualDefinition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualUsage.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIsPortion.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionBracketOperator.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionCastConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionQuantity.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedDifferencingNotOne.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedIntersectingNotOne.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedUnioningNotOne.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePerformActionUsageReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortDefinitionOwnedUsagesNotComposite.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageIsReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageNestedUsagesNotComposite.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionDirectionConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionEndConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionFeaturingTypes.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionMultiplicityConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRenderingUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementConstraintMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionOnlyOneSubject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionSubjectParameterPosition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageOnlyOneSubject.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageSubjectParameterPosition.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementVerificationMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateReturnParameterMembershipOwningType.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSatisfyRequirementUsageReference.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsagePayloadArgument.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsageReceiver.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.subset.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStakeholderMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionParallelSubactions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionSubactionKind.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateSubactionMembershioOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageParallelSubactions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageSubactionKind.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStructureSpecialization.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubjectMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingConstantConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingFeaturingTypes.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingMultiplicityConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingUniquenessConformance.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionFeatureMembershipGuardExpression.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageSuccession.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageTriggerActions.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAfterArgument.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAtArgument.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionWhenArgument.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeAtMostOneConjugator.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeDifferencingTypesNotSelf.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeIntersectingTypesNotSelf.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeOwnedMultiplicity.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeUnioningTypesNotSelf.kerml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationMembership.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationSpecialization.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUseCaseUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVariationMembershipOwningNamespace.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVerificationCaseUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewDefinitionOnlyOnvViewRendering.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewRenderingMembershipOwningType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageOnlyOneRendering.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewpointUsageType.sysml create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/provenance.json create mode 100644 crates/sysmlv2-parser/tests/fixtures/opensysml/static-contracts.json create mode 100644 crates/sysmlv2-parser/tests/full_baseline.rs create mode 100644 crates/sysmlv2-parser/tests/inherited_battery.rs create mode 100644 crates/sysmlv2-parser/tests/opensysml.rs create mode 100644 crates/sysmlv2-parser/tests/prepared_library.rs create mode 100644 crates/sysmlv2-parser/tests/spelling.rs create mode 100644 crates/sysmlv2-parser/tests/static_rules.rs create mode 100644 crates/sysmlv2-parser/tests/support/census.rs create mode 100644 crates/sysmlv2-solve/tests/prepared.rs create mode 100644 crates/sysmlv2-transform/examples/importbench.rs create mode 100644 crates/sysmlv2-transform/examples/preparedbench.rs create mode 100644 crates/sysmlv2-transform/src/unused_imports_tests.rs create mode 100644 crates/sysmlv2-transform/tests/library_subjects.rs create mode 100644 crates/sysmlv2-transform/tests/line_endings.rs create mode 100644 crates/sysmlv2-transform/tests/parsed_sources.rs create mode 100644 crates/sysmlv2-transform/tests/payload_loader.rs create mode 100644 crates/sysmlv2-transform/tests/prepared_sources.rs create mode 100644 crates/sysmlv2-viz/tests/emitter_walks.rs create mode 100644 crates/sysmlv2-viz/tests/endpoint_semantics.rs create mode 100644 crates/sysmlv2-viz/tests/escaping.rs create mode 100644 crates/sysmlv2-viz/tests/options.rs create mode 100644 crates/sysmlv2-wasm/tests/prepared_library.rs create mode 100644 crates/sysmlv2-wasm/tests/stack.rs create mode 100644 spec-refs/derived-correspondence.json create mode 100644 spec-refs/derived-properties.json create mode 100644 spec-refs/derived-properties.md create mode 100644 tools/derived_census.py create mode 100644 tools/gen_metaclass_hierarchy.py diff --git a/.github/workflows/audit.yml b/.github/workflows/audit.yml new file mode 100644 index 0000000..f322ebf --- /dev/null +++ b/.github/workflows/audit.yml @@ -0,0 +1,28 @@ +# Weekly dependency advisory scan of Cargo.lock (also runnable by hand). +# Informational: a new advisory opens a failed scheduled run, it never +# blocks a PR or a release on its own. + +name: audit + +on: + schedule: + - cron: "17 6 * * 1" + workflow_dispatch: + +permissions: + contents: read + +jobs: + audit: + name: advisory scan + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Install the pinned toolchain (rust-toolchain.toml) + run: | + toolchain=$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml) + rustup toolchain install "$toolchain" --profile minimal + - name: Install the advisory scanner + run: cargo install cargo-audit --locked + - name: Scan the lockfile + run: cargo audit diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index bd2f974..14316e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -67,6 +67,13 @@ env: jobs: test: name: test (full corpus gates) + timeout-minutes: 45 + # Release PRs (release/* -> main, opened and admin-merged by + # tools/release.sh in one step) run these gates like any other PR. + # Skipping them costs less than it looks: the tag is pushed by the + # same command that merged, so a skipped release PR makes the tag run + # the first time CI ever sees the tree — and a failure there lands + # after main has already moved, with the version spent. runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 @@ -83,19 +90,24 @@ jobs: run: git submodule update --init spec-refs/apollo-11-sysml-v2 - name: Install z3 run: sudo apt-get update && sudo apt-get install -y z3 - - uses: dtolnay/rust-toolchain@stable - - name: Formatting + - name: Install the pinned toolchain (rust-toolchain.toml) + shell: bash run: | - rustup component add rustfmt - cargo fmt --check + toolchain=$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml) + rustup toolchain install "$toolchain" --profile minimal --component rustfmt --component clippy + rustup show active-toolchain + - name: Formatting + run: cargo fmt --all -- --check - name: Run the full test suite run: cargo test --release - name: Clippy - run: | - rustup component add clippy - cargo clippy --release --all-targets -- -D warnings + run: cargo clippy --release --all-targets -- -D warnings - name: Clippy (slim CLI — no default features) run: cargo clippy --release -p sysmlv2-cli --no-default-features -- -D warnings + - name: Documentation (public docs build warning-free) + env: + RUSTDOCFLAGS: -D warnings + run: cargo doc --no-deps - name: Generated libraries (strict check against the stdlib, canonical formatting) # The committed files are checked as candidates: SYSMLV2_AMBIENT=off # keeps the toolkit's built-in copies out so they cannot collide. @@ -109,8 +121,25 @@ jobs: printf 'package V { part shell : Web::HTML::Elements::Div { :>> id = "app"; } part t : Template::Text; part k : Svelte::KeyBlock; part a : WebApp::Application; part r : SvelteKit::RouteSegment; }\n' > /tmp/ambient.sysml cargo run --release -p sysmlv2-cli -- check --strict --lib spec-refs/SysML-v2-Release/sysml.library /tmp/ambient.sysml + msrv: + name: msrv (declared rust-version still builds) + timeout-minutes: 30 + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v7 + - name: Install the declared minimum toolchain + run: | + msrv=$(sed -n 's/^rust-version = "\(.*\)"$/\1/p' Cargo.toml) + echo "rust-version: $msrv" + rustup toolchain install "$msrv" --profile minimal + echo "MSRV=$msrv" >> "$GITHUB_ENV" + - name: Check every target on the minimum toolchain + # The `+toolchain` override wins over rust-toolchain.toml. + run: cargo +"$MSRV" check --all-targets --locked + wasm: name: wasm (wasm32 gate + npm package + node smoke) + timeout-minutes: 45 runs-on: ubuntu-latest permissions: contents: read @@ -127,15 +156,16 @@ jobs: git sparse-checkout set sysml.library git fetch --filter=blob:none origin "$sha" git checkout "$sha" - - uses: dtolnay/rust-toolchain@stable - with: - # unknown-unknown for the bindgen module, wasip1 for the CLI - # artifact the package ships under cli/. - targets: wasm32-unknown-unknown,wasm32-wasip1 - - name: Clippy (wasm32) + # unknown-unknown for the bindgen module, wasip1 for the CLI + # artifact the package ships under cli/. + - name: Install the pinned toolchain (rust-toolchain.toml) + shell: bash run: | - rustup component add clippy - cargo clippy --release -p sysmlv2-wasm --target wasm32-unknown-unknown -- -D warnings + toolchain=$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml) + rustup toolchain install "$toolchain" --profile minimal --component rustfmt --component clippy --target wasm32-unknown-unknown --target wasm32-wasip1 + rustup show active-toolchain + - name: Clippy (wasm32) + run: cargo clippy --release -p sysmlv2-wasm --target wasm32-unknown-unknown -- -D warnings - name: Install wasm-pack # Pinned release binary. The rustwasm.github.io installer script # is stale (the project moved to drager/wasm-pack) and serves @@ -145,12 +175,39 @@ jobs: curl -sSfL "https://github.com/rustwasm/wasm-pack/releases/download/v${v}/wasm-pack-v${v}-x86_64-unknown-linux-musl.tar.gz" | tar xz mv "wasm-pack-v${v}-x86_64-unknown-linux-musl/wasm-pack" "$HOME/.cargo/bin/" wasm-pack --version + # The runtime the smokes run under is pinned, not inherited. The + # image's own Node 22 on x86_64 faults inside its WASI host on this + # module: measured over 40 runs of the unchanged cli smoke against + # one artifact, 6 died with SIGSEGV, while Node 20 and 24 on the + # same architecture, and Node 22 on arm64, were clean 40/40. The + # rate tracks the module's declared initial memory, which the + # stack reservation the recursion bounds need makes 16 MiB, so the + # trigger is ours even though the fault is the host's. Consumers on + # that combination are told about it in the package README. + - uses: actions/setup-node@v6 + with: + node-version: '24' - name: Build the npm package (wasm module + stdlib bundle/snapshot) - run: node crates/sysmlv2-wasm/npm/build.mjs + run: node --version && node crates/sysmlv2-wasm/npm/build.mjs - name: Node smoke test (module load, stdlib check, snapshot replay) run: node crates/sysmlv2-wasm/npm/smoke.mjs - name: CLI wasi smoke (ambient context, provenance, size budget) run: node crates/sysmlv2-wasm/npm/cli_smoke.mjs + # A failing smoke is only diagnosable from the bytes it ran, and + # those are built here and never uploaded on a red run. Keep them + # when something fails; a green run publishes the tarball below and + # this costs nothing. It is a separate artifact deliberately — the + # release job merges every artifact into one directory and attaches + # the lot, so this must not ride along with the tarball. + - name: Keep the wasm artifacts a failure needs + if: failure() + uses: actions/upload-artifact@v7 + with: + name: sysmlv2-wasm-failed + path: | + crates/sysmlv2-wasm/npm/pkg/cli/sysmlv2-cli.wasm + crates/sysmlv2-wasm/npm/pkg/sysmlv2_bg.wasm + if-no-files-found: warn - name: Upload the package tarball (release artifact) if: startsWith(github.ref, 'refs/tags/') uses: actions/upload-artifact@v7 @@ -219,23 +276,29 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v7 - - uses: dtolnay/rust-toolchain@stable - with: - targets: ${{ matrix.target }} + - name: Install the pinned toolchain (rust-toolchain.toml) + shell: bash + run: | + toolchain=$(sed -n 's/^channel = "\(.*\)"$/\1/p' rust-toolchain.toml) + rustup toolchain install "$toolchain" --profile minimal --component rustfmt --component clippy --target ${{ matrix.target }} + rustup show active-toolchain - name: Install system packages if: matrix.packages != '' run: sudo apt-get update && sudo apt-get install -y ${{ matrix.packages }} + # Shipped binaries build under the whole-program-optimised `dist` + # profile (Cargo.toml); the slim variant uses it too so the size + # comparison stays like for like. - name: Build (slim — size measurement only, not shipped) - run: cargo build --release -p sysmlv2-cli --no-default-features --target ${{ matrix.target }} + run: cargo build --profile dist -p sysmlv2-cli --no-default-features --target ${{ matrix.target }} - name: Stash the slim binary shell: bash run: | bin=sysmlv2 [[ "${{ matrix.target }}" == *windows* ]] && bin=sysmlv2.exe mkdir slim - cp "target/${{ matrix.target }}/release/$bin" slim/ + cp "target/${{ matrix.target }}/dist/$bin" slim/ - name: Build (complete) - run: cargo build --release -p sysmlv2-cli --target ${{ matrix.target }} + run: cargo build --profile dist -p sysmlv2-cli --target ${{ matrix.target }} - name: Package shell: bash run: | @@ -245,7 +308,7 @@ jobs: [[ "$target" == *windows* ]] && bin=sysmlv2.exe name="sysmlv2-${version}-${target}" mkdir "$name" - cp "target/${target}/release/$bin" "$name/" + cp "target/${target}/dist/$bin" "$name/" cp README.md LICENSE "$name/" if [[ "$target" == *windows* ]]; then 7z a "${name}.zip" "$name" @@ -253,7 +316,7 @@ jobs: tar czf "${name}.tar.gz" "$name" fi # One row of the release-wide size table (SIZES.md, release job). - complete=$(wc -c < "target/${target}/release/$bin") + complete=$(wc -c < "target/${target}/dist/$bin") slim=$(wc -c < "slim/$bin") hsize() { awk -v b="$1" 'BEGIN { printf "%.1f MiB", b / 1048576 }'; } printf '| %s | %s (%s) | %s (%s) | %s |\n' \ diff --git a/.gitignore b/.gitignore index 710ec87..fada066 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,6 @@ target/ target-wasm/ +target-msrv/ +/CLAUDE.local.md node_modules/ .DS_Store diff --git a/CBOR.md b/CBOR.md index ece6c70..14e7908 100644 --- a/CBOR.md +++ b/CBOR.md @@ -79,15 +79,19 @@ Where the bytes go, relative to compact JSON: - **tables (u16)** — the generated metamodel tables (type codes, field ordinals, kinds, defaults; currently from the 20250201 normative release). Refused on any decode, since every element record reads through them — but independently of layout, so a tables-only regeneration is diagnosable as exactly that. - **scheme (u8)** — the id-derivation scheme (`IDS.md`; wire scheme 1 is that document's graph-derived derivation). Consulted **only** where derivation is in play (id-elided payloads, snapshot or delta): explicit-id payloads decode regardless of it. Digest failures on matched-scheme payloads therefore come pre-diagnosed: not a scheme skew, so library skew or corruption. +**Flags.** `elideIds` (1), `fullForm` (2), `delta` (4), `deltaPortable` (8), `unitPaths` (16), `impliedOwners` (32), and `explicitIds` (64): a compact snapshot whose ids are not all the graph derivation of `IDS.md` — a session that loaded a document from another producer, or under other unit names, keeps the ids it was given and marks the payload so a receiver never re-derives them; such a session refuses id elision. Informational for decoders, which always read the id table; `describe` reports it as `explicitIds`. + Unknown flag bits are refused, so a decoder never misreads a payload kind it does not know. **Determinism:** byte output is a pure function of the input Value (canonical type/field/table ordering); an exact byte fixture in `crates/sysmlv2-cbor/tests/determinism.rs` pins the wire format. ## Using it - **CLI** — `sysmlv2 convert model.sysml --to compact-cbor -o m.s2c`; a `.s2c` input decodes up front and flows like `.json` (`sysmlv2 convert m.s2c --to text`). Binary stdout when `-o` is omitted. `--flexo` is JSON-only (the change-record envelope wraps JSON; CBOR carries the bare element array). - **Rust** — `sysmlv2_cbor::{to_compact_cbor, from_compact_cbor}` (`Value ↔ bytes`), or `Session::{to_compact_cbor, from_compact_cbor[_with_library]}` in `sysmlv2-transform`. -- **wasm** — `session.toCompactCbor(): Uint8Array`, `Session.fromCompactCbor(bytes, libSources?, libSnapshot?)`. +- **wasm** — `session.toCompactCbor(): Uint8Array`, `Session.fromCompactCbor(bytes, libSources?, libSnapshot?, indent?)`. - **Python** — `session.to_compact_cbor() -> bytes`, `Session.from_compact_cbor(data, lib=None)`. +Every Rust entry point fails with one `sysmlv2_cbor::Error`, whose `Display` explains the refusal and whose `kind()` classifies it for callers that act on the classes differently: `MissingMagic` (not an s2c payload), `UnsupportedVersion` (a wire-layout, table, id-scheme, base-index or resolver-artifact generation this build does not implement), `NeedsResolver` (an id-elided payload at an entry point that carries no name resolver), `WrongForm` (a well-formed payload of another kind — the message names the entry point to use), `BaseDigestMismatch` (the held base is not the one the delta names), `Truncated`, and `Malformed` for everything else. The enum is `#[non_exhaustive]`: later wire generations will distinguish more, so match with a wildcard arm. + ## Compact-form canonicalization The presence-faithful round-trip means the codec never bridges the *default elision split*: a producer that wire-elides schema-default spellings (`isUnique: true`, `isAbstract: false`, `visibility: "public"`, `null`s, empty lists, the `elementId` mirror) and one that spells them explicitly emit different JSON for the same state, and no digest over either spelling can compare them. `sysmlv2_cbor::canonicalize_compact(json) -> json` (wasm free function `canonicalizeCompact`) closes it: every element is materialized through its metaclass field table and re-emitted with each absent property spelled at its metaclass-specific default from the generated tables. Present values and `@id`s are preserved verbatim, element order is untouched, literal-valued fields (no default) stay absent, and the pass is idempotent — both producers land on the same canonical document, so digest comparison becomes sound. Strict like the encoder: unknown `@type`s and non-compact-form keys (derived properties included) are errors. Gate: `crates/sysmlv2-cbor/tests/canonical.rs` (golden corpus under a simulated wire elision) + `sysmlv2-wasm/tests/api.rs`. @@ -96,44 +100,45 @@ The presence-faithful round-trip means the codec never bridges the *default elis ## Measured comparison (real corpora) -Two corpora, measured with `cargo run --release -p sysmlv2-cbor --example corpus_bench` (medians of 5 runs, Apple Silicon; deflate level 8 via the workspace's existing compressor — CBOR needs no compressor to beat compressed JSON, and general-purpose compression composes on top): +Two pinned corpora, measured with toolkit implementation `15a9de5` on Apple Silicon/macOS arm64. Reproduce with `cargo run --release -p sysmlv2-cbor --example corpus_bench` (medians of five runs; deflate level 8). This harness measures each serialization stage; it does not exercise the CLI’s prepared-library cache. Times are descriptive single-machine results, not performance guarantees. -**`library`** — every textual unit of the vendored standard library loaded as user sources (94 units, **91,319 elements**): +The official library pin is `de1070ae8e79c21532b8004fc663d47b35d0e9fa`; Apollo is `6e9c93fe7d80c5ca3534bb14b10ab374a643ef2d`. + +**Library** — 94 textual units loaded as user sources, 91,405 compact elements. | form | bytes | +deflate | |---|---:|---:| -| pretty JSON | 45,392,718 | 4,570,527 | -| minified JSON | 35,401,680 | 4,346,312 | -| compact CBOR | 3,991,107 | 2,314,235 | -| **min-JSON / CBOR** | **8.9×** | **1.9×** | +| pretty JSON | 45432828 | 4575775 | +| minified JSON | 35432925 | 4351340 | +| compact CBOR | 3579835 | 2077326 | +| compact CBOR --elide-ids | 2029539 | 558533 | +| ratio min-JSON / CBOR | 9.90x | 2.09x | -**`model`** — the vendored end-to-end validation model (`spec-refs/apollo-11-sysml-v2`, 28 units, **23,276 elements**), resolved against the standard library: +**Apollo 11** — 28 textual units resolved against the standard library, 23,276 compact elements. | form | bytes | +deflate | |---|---:|---:| -| pretty JSON | 11,915,294 | 1,177,595 | -| minified JSON | 9,273,607 | 1,125,183 | -| compact CBOR | 977,151 | 606,183 | -| **min-JSON / CBOR** | **9.5×** | **1.9×** | - -Pipeline timing, textual notation → serialized form and back (`library` / `model`): +| pretty JSON | 11917868 | 1177849 | +| minified JSON | 9275587 | 1125537 | +| compact CBOR | 886602 | 547650 | +| compact CBOR --elide-ids | 491485 | 160052 | +| ratio min-JSON / CBOR | 10.46x | 2.06x | -| stage | library ms | model ms | +| stage | library ms | Apollo ms | |---|---:|---:| -| text → model (parse) | 12.0 | 16.3 | -| model → element array (lower + resolve + Value) | 245.9 | 214.5 | -| Value → minified JSON | 39.0 | 10.9 | -| Value → CBOR | 104.8 | 26.4 | -| minified JSON → Value | 84.8 | 22.5 | -| CBOR → Value | 80.7 | 22.0 | -| Value → CBOR --elide-ids (derive + verify) | 219.2 | 45.3 | -| CBOR --elide-ids → Value (derive + digest) | 235.1 | 49.0 | -| Value → textual notation (lift + print) | 115.3 | 27.7 | +| text → model (parse) | 10.5 | 17.2 | +| model → element array (lower+resolve+Value) | 252.6 | 234.8 | +| Value → minified JSON | 28.1 | 7.5 | +| Value → CBOR | 127.9 | 30.5 | +| minified JSON → Value | 88.4 | 23.7 | +| CBOR → Value | 116.1 | 30.9 | +| Value → CBOR --elide-ids (derive+verify) | 251.2 | 55.6 | +| CBOR --elide-ids → Value (derive+digest) | 262.2 | 62.3 | +| Value → textual notation (lift+print) | 112.1 | 29.0 | -Reading the numbers: +Compact CBOR is 9.9–10.5× smaller than minified JSON, or about 2.1× after deflate. In this run, encoding takes about 4.1–4.6× JSON serialization time and decoding takes about 1.3× JSON parsing time. Smaller payloads can reduce transfer/storage costs, but this measurement does not establish a faster decoder. Id elision adds graph derivation and digest work. Lowering and resolution remain a substantial part of the complete pipeline. -- **Size.** Real models do better than the golden corpus (~5.8×): ~9× under minified JSON raw, at ~43 B/element. **Raw CBOR is already smaller than deflated minified JSON** — the wire wins without spending CPU on compression — and after both sides deflate, CBOR still halves the payload (the id table's random UUID bytes are the dominant incompressible remainder; eliding them is what id elision, below, does). -- **Time.** Encoding costs ~2.5× JSON serialization (table lookups per field) but is a small slice of the text→bytes pipeline — lowering + resolution dominates at ~200+ ms. Decoding is consistently *faster* than JSON parsing (no string keys to hash, no text numbers to parse), so the read path — the hot one for a web client or a Flexo retrieval — is both ~9× smaller and slightly cheaper to parse. The lift back to textual notation is identical for both forms (they produce the same `Value`). +Full-form CBOR is 10.9–11.6× smaller than minified full JSON (1.78× after deflate). Appending the harness’s small package yields strict deltas of 338 bytes for the library and 316 bytes for Apollo; portable deltas are 345 bytes for both. ## Delta payloads @@ -186,7 +191,7 @@ The id table was the dominant *incompressible* remainder of the un-elided format | corpus | CBOR | elided | CBOR+deflate | elided+deflate | |---|---:|---:|---:|---:| -| library | 3,991,107 | 2,442,273 | 2,314,235 | **797,325** | -| model | 977,151 | 582,034 | 606,183 | **218,243** | +| library | 3,579,835 | 2,029,539 | 2,077,326 | 558,533 | +| Apollo | 886,602 | 491,485 | 547,650 | 160,052 | -Against minified JSON that is **14.5–15.9× raw** and **~5.3× after both sides deflate** (versus 1.9× without elision). Cost: derivation roughly doubles encode (219 ms / 45 ms on the two corpora) and decode (235 ms / 49 ms incl. the digest check) — still the same order as JSON parsing, and far under lowering/resolution. +Against minified JSON, elision gives **17.5–18.9× raw** and **7.0–7.8× after both sides deflate** in the benchmark above. Derivation and digest verification roughly double ordinary CBOR encode/decode time; see the stage table for the measured costs. diff --git a/CLI.md b/CLI.md index af6e28c..868e309 100644 --- a/CLI.md +++ b/CLI.md @@ -25,7 +25,7 @@ $ $sysmlv2 parse "$vehicle" spec-refs/SysML-v2-Release/sysml/src/examples/Vehicle Example/SysML v2 Spec Annex A SimpleVehicleModel.sysml: 1 top-level member(s), 0 diagnostic(s) ``` -Exit code 0 on a clean parse, 1 if there are diagnostics. Both dialects are supported; the dialect is chosen by extension (`.kerml` → KerML): +Exit code 0 on a clean parse, 1 if there are diagnostics. Both dialects are supported; the dialect is chosen by extension (`.kerml` → KerML), and extensions are matched whatever case they are spelled in (`Model.SysML` is a model source, `Lib.KerML` is KerML): ```console $ $sysmlv2 parse "$corpus/sysml.library/Kernel Libraries/Kernel Data Type Library/ScalarValues.kerml" @@ -57,14 +57,15 @@ SourceUnit { --- -## 2. `check` — parse + body-context validation +## 2. `check` — static validation -`check` runs two stages: parse diagnostics, then post-parse validation of the rules the (deliberately permissive) parser does not enforce — member legality per body context, duplicate member names, `variant` ownership, and the mandatory import visibility. +`check` reports parse diagnostics, validates body contexts on cleanly parsed files, then resolves those files together and runs referential and semantic checks. These local checks run even without `--lib`; supply the library to resolve standard types and enable unused-private-import warnings. Structural checks include member legality, duplicate names, `variant` ownership, and import visibility. `--strict` fails on warnings as well as errors. -The whole vehicle example directory is clean: +A self-contained model is clean without a library: ```console -$ $sysmlv2 check "$corpus/sysml/src/examples/Vehicle Example"/*.sysml +$ printf 'package Demo { part def Vehicle; part car : Vehicle; }\n' > clean.sysml +$ $sysmlv2 check clean.sysml $ echo $? 0 ``` @@ -97,7 +98,7 @@ error: a transition usage is not allowed in a definition or usage body | | transition first parked then driving; -error: a `subject` member is not allowed in a definition or usage body +error: validateSubjectMembershipOwningType: a `subject` member is not allowed in a definition or usage body --> broken.sysml:6:9 | | subject v; @@ -107,6 +108,22 @@ error: a `variant` member is only allowed in the body of a `variation` definitio | | variant part manual; +warning: unresolved reference `Definitions` + --> broken.sysml:2:12 + | + | import Definitions::*; + +warning: unresolved reference `parked` + --> broken.sysml:5:26 + | + | transition first parked then driving; + +warning: unresolved reference `driving` + --> broken.sysml:5:38 + | + | transition first parked then driving; + +3 warning(s) 4 error(s) $ echo $? 1 @@ -116,7 +133,7 @@ The legality matrix is transcribed from the normative Xtext grammars' `*BodyItem ### Referential checks (`--lib`) -With `--lib`, all input files form one model resolved against the standard library, and referential findings are reported as **warnings** (exit code unaffected — the resolver covers 99.9% of the corpus, and a warning must not fail a conforming model): +With `--lib`, all input files form one model resolved against the standard library, and unresolved references, missing alias targets and import cycles are **warnings**; ambiguous references are **errors**. Without `--lib`, local references are still checked and missing standard-library dependencies may produce warnings. Warnings affect the exit code only with `--strict`: ```sysml package Demo { @@ -167,9 +184,37 @@ $ echo $? (Run against the corpus, the only import cycles found are the deliberate `CircularImport.sysml` test fixture — gated by `tests/check.rs::corpus_referential_ratchet`.) +A root package (or any other root declaration) named like a standard-library root package is reported at its declaration: the diagnostic states whether references resolve to the library or the name is ambiguous. In the following package collision, the library wins qualified lookup. + +```sysml +package Requirements { + requirement def Speed; +} +package Uses { + requirement s : Requirements::Speed; +} +``` + +```console +$ $sysmlv2 check shadow.sysml --lib "$corpus/sysml.library" +warning: root package `Requirements` shadows the standard library package `Requirements`; references resolve to the library + --> shadow.sysml:1:9 + | + | package Requirements { + +warning: unresolved reference `Requirements::Speed` + --> shadow.sysml:5:21 + | + | requirement s : Requirements::Speed; + +2 warning(s) +``` + +Nesting the package under a differently named root, or renaming it, clears both warnings. + ### Semantic constraints (`--lib`) -The same `--lib` run also applies the semantic checks: multiplicity bounds (evaluated with the expression evaluator, so a bound can be an expression), self/circular specialization (errors), and duplicate specialization targets (warnings). Errors are raised only for what is *provably* wrong — a symbolic bound the evaluator cannot compute stays silent: +Semantic checks run with or without a library; `--lib` supplies additional type and relationship information. The example below exercises multiplicity bounds (evaluated with the expression evaluator, so a bound can be an expression), self/circular specialization (errors), and duplicate specialization targets (warnings). Errors are raised only for what is *provably* wrong — a symbolic bound the evaluator cannot compute stays silent: ```sysml package Demo { @@ -220,7 +265,328 @@ error: multiplicity upper bound is negative 5 error(s) ``` -Note the last finding: `[spares]` is provably negative only because the evaluator computed `2 - 3`. These checks are corpus-gated at zero findings (`tests/check.rs`, `examples/semstats`). +Note the last finding: `[spares]` is provably negative only because the evaluator computed `2 - 3`. The official semantic gate pins two dimensional findings in Turbojet Stage Analysis and VehicleGeometryAndCoordinateFrames (`tests/check.rs`, `examples/semstats`). Additional checks cover usage typing, redefinitions, metadata, valuation, invocation binding, dimensions, connector ends, and static action/state contracts. Unknown values stay conservative; behavioral execution is outside this checker. + +With `--lib`, the CLI also reports unused private imports. The analysis combines resolution provenance with enclosing-owner and source-text evidence, so uncertain usage is retained conservatively. Public imports are not candidates because they can re-export names for other models. This is a warning, promoted to failure by `--strict`. + +### `--format json` — one report document + +`--format json` writes the findings as one JSON document on stdout instead of the text above on stderr; the exit code is unchanged and the count lines are not printed. Every item carries the same keys whichever verb produced it — `lint --format json` ([2a](#2a-lint--project-policy-rules)) emits the same shape: `stage` (`parse`, `context`, `referential` or `semantic`), `severity` in the lint config spelling (`error` / `warn` / `info` / `hint`), the `message`, the input's index and name (`unit`, `unitName`), byte offsets (`start`, `end`), 1-based positions (`line`, `col`, `endLine`, `endCol`), and the lint-only fields (`rule`, `element`, `suggest`, `fix`, `alternatives`) as null or empty: + +```console +$ printf 'package Q { part x : ; }\n' > broken.sysml +$ $sysmlv2 check --format json broken.sysml +{ + "findings": [ + { + "alternatives": [], + "col": 22, + "element": null, + "end": 22, + "endCol": 23, + "endLine": 1, + "fix": null, + "line": 1, + "message": "expected a name, found `;`", + "rule": null, + "severity": "error", + "stage": "parse", + "start": 21, + "suggest": null, + "unit": 0, + "unitName": "broken.sysml" + } + ], + "summary": { + "errors": 1, + "hints": 0, + "infos": 0, + "warnings": 0 + } +} +$ echo $? +1 +``` + +A clean run is an empty `findings` array with a zeroed summary. Over several inputs `unit` indexes the files as given, so a consumer attributes each finding without parsing paths: + +```console +$ $sysmlv2 check --format json clean.sysml +{ + "findings": [], + "summary": { + "errors": 0, + "hints": 0, + "infos": 0, + "warnings": 0 + } +} +$ $sysmlv2 check --format json clean.sysml broken.sysml | jq -c '.findings[] | {stage, severity, unit, unitName, line, col}' +{"stage":"parse","severity":"error","unit":1,"unitName":"broken.sysml","line":1,"col":22} +``` + +Operational failures — an unreadable input, a library that fails to load — still go to stderr with exit 1 and no document. + +--- + +## 2a. `lint` — project-policy rules + +`lint` reports what `check` deliberately does not: style, hygiene and dead-model findings that are project policy rather than language law. It runs beside `check` and never changes its verdicts, sees only the user units (library elements are never linted, even with `--lib`), and sorts findings by unit, position and rule. Given `rig.sysml`: + +```sysml +package Rig { + part def Wheel; + part def spare_wheel; + part axle : Wheel; + calc def Torque { + in force : Real; + in radius : Real; + return t : Real = force * 2; + } +} +``` + +Without configuration, only the rules with a non-off default speak — here the casing nudge: + +```console +$ $sysmlv2 lint rig.sysml +warning: definition name `spare_wheel` should be PascalCase [naming-convention] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +1 warning(s) +$ echo $? +0 +``` + +Every finding names its rule in brackets. The text report has two severities — `info` and `hint` findings print as `warning:` and count as warnings — while the JSON report below keeps the exact severity. `--rule ID=LEVEL` switches a rule on for one run (repeatable; it wins over the config file): + +```console +$ $sysmlv2 lint --rule unused-parameter=warn --rule unused-definition=warn rig.sysml +warning: definition name `spare_wheel` should be PascalCase [naming-convention] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: `Torque` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:5:14 + | + | calc def Torque { + +warning: input parameter `radius` of `Torque` is never used [unused-parameter] + --> rig.sysml:7:12 + | + | in radius : Real; + +4 warning(s) +``` + +### Configuration — `sysmlint.json` + +Project policy lives in a JSON file: `{"rules": {"": | {"severity": , "scopes": {"": …}, …options}}}` where a level is `off`, `hint`, `info`, `warn` or `error`. Every rule accepts `scopes`, the same knob at stereotype granularity — a metaclass name maps to a level or to an object with rule-specific keys (naming's `style` / `regex`, undocumented's `depth`); an element's effective severity is its scope's, else the rule's base. `--config` names the file; without it, a `sysmlint.json` beside the first input is picked up automatically: + +```console +$ cat > sysmlint.json <<'EOF' +{ + "rules": { + "naming-convention": "off", + "unused-parameter": "warn", + "unused-definition": { "severity": "warn", "scopes": { "CalculationDefinition": "off" } } + } +} +EOF +$ $sysmlv2 lint rig.sysml +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: input parameter `radius` of `Torque` is never used [unused-parameter] + --> rig.sysml:7:12 + | + | in radius : Real; + +2 warning(s) +``` + +The scope silenced the unused `calc def` while the `part def` still reports. A typo'd rule id or option is a finding (`lint-config`, without a location), never a silent ignore: + +```console +$ $sysmlv2 lint --rule no-such=warn rig.sysml +warning: unknown lint rule `no-such` [lint-config] +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +2 warning(s) +``` + +Warnings exit 0; `error`-level findings exit 1, and `--strict` fails on any finding at all (infos and hints included): + +```console +$ $sysmlv2 lint --strict rig.sysml +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: input parameter `radius` of `Torque` is never used [unused-parameter] + --> rig.sysml:7:12 + | + | in radius : Real; + +2 warning(s) +--strict: warnings are failures +$ echo $? +1 +``` + +### `--fix` — applying the fixes + +Findings that carry a fix are applied in place by `--fix`, except the two guarded kinds: fixes that *delete* model text (an unused parameter's fix removes its declaration) additionally need `--fix-deletes`, and fixes that change what a declaration *means* (a usage keyword, a member's visibility) need `--fix-semantic`. Refused fixes are counted on stderr; every rewritten file must reparse cleanly before it is written back: + +```console +$ $sysmlv2 lint --fix rig.sysml +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: input parameter `radius` of `Torque` is never used [unused-parameter] + --> rig.sysml:7:12 + | + | in radius : Real; + +1 deletion fix(es) available but not applied — deleting model text needs --fix --fix-deletes +2 warning(s) +$ $sysmlv2 lint --fix --fix-deletes rig.sysml +warning: `spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint) [unused-definition] + --> rig.sysml:3:14 + | + | part def spare_wheel; + +warning: input parameter `radius` of `Torque` is never used [unused-parameter] + --> rig.sysml:7:12 + | + | in radius : Real; + +fixed: rig.sysml +2 warning(s) +$ cat rig.sysml +package Rig { + part def Wheel; + part def spare_wheel; + part axle : Wheel; + calc def Torque { + in force : Real; + return t : Real = force * 2; + } +} +``` + +The report still lists the findings the fixes addressed — it describes the input as read; the deleted line is gone from the file. Stdin (`-`) and archive members are linted but never written. + +### `--format json` — one report document + +`--format json` writes one JSON document on stdout — the same shape as `check --format json` above — and prints nothing else: each finding carries its `rule`, the exact `severity`, `element` (the engine's edit-target spelling, a `::`-qualified name or `@` for anonymous elements), `suggest` (a naming finding's re-spelled name) and `fix` / `alternatives` with byte-offset `edits` over the unit's text, so a host can apply or offer them itself. The exit status stays the text mode's (`--strict`, refused fixes), which the summary's per-severity counts do not encode. Before the fix above: + +```console +$ $sysmlv2 lint --format json rig.sysml +{ + "findings": [ + { + "alternatives": [], + "col": 14, + "element": "Rig::spare_wheel", + "end": 58, + "endCol": 25, + "endLine": 3, + "fix": null, + "line": 3, + "message": "`spare_wheel` is never referenced in these units (closed world: outside consumers are not visible to lint)", + "rule": "unused-definition", + "severity": "warn", + "stage": "lint", + "start": 47, + "suggest": null, + "unit": 0, + "unitName": "rig.sysml" + }, + { + "alternatives": [], + "col": 12, + "element": "Rig::Torque::radius", + "end": 147, + "endCol": 18, + "endLine": 7, + "fix": { + "deletes": true, + "edits": [ + { + "end": 155, + "replacement": "", + "start": 138, + "unit": 0, + "unitName": "rig.sysml" + } + ], + "label": "delete unused parameter `radius`", + "semantic": false + }, + "line": 7, + "message": "input parameter `radius` of `Torque` is never used", + "rule": "unused-parameter", + "severity": "warn", + "stage": "lint", + "start": 141, + "suggest": null, + "unit": 0, + "unitName": "rig.sysml" + } + ], + "summary": { + "errors": 0, + "hints": 0, + "infos": 0, + "warnings": 2 + } +} +$ $sysmlv2 lint --format json rig.sysml | jq -r '.findings[] | "\(.unitName):\(.line):\(.col) \(.severity) \(.rule)"' +rig.sysml:3:14 warn unused-definition +rig.sysml:7:12 warn unused-parameter +``` + +### The rules + +| Rule | Default | Flags | Fix | +|---|---|---|---| +| `naming-convention` | info | a declared name off the project's casing — definitions PascalCase, usages and features camelCase; per-family and per-scope presets (`camelCase`, `PascalCase`, `snake_case`, `UPPER_SNAKE_CASE`, `kebab-case`) or a `regex` | `suggest` carries the re-spelled name | +| `undocumented-element` | off | a definition without its own `doc` body or a comment `about` it; `depth` reaches below the top level | — | +| `untyped-usage` | off | a named usage with no typing, subsetting or redefinition clause (enumeration literals and transitions off by default) | — | +| `unused-definition` | off | a user definition nothing in the user model references (closed world) | — | +| `unused-parameter` | off | an input parameter of a calc / constraint / action definition never used in its body | deletes the parameter (`--fix-deletes`) | +| `import-visibility` | info | an import without a visibility keyword — the syntax check reports the error, this finding carries the fix | declares the visibility its dependents need; the other keywords as alternatives | +| `visibility-blocked-reference` | warn | an unresolved reference that names a member reachable only by ignoring visibility | widens the member to `public` (`--fix-semantic`) | +| `usage-kind-mismatch` | info | a usage typed by a definition of another kind — the semantic check reports the error, this finding carries the fix | rewrites the usage keyword (`--fix-semantic`) | +| `port-member-referential` | info | a composite non-port usage inside a port body | inserts `ref` | +| `unqualified-enum-literal` | warn | an unresolved simple name matching exactly one enumeration literal | qualifies it | +| `unit-spelling` | off | one unit spelled two ways across the model; the `style` option (`quoted-product` / `expression`) enforces a form | re-spells | +| `dimensional-consistency` | warn | a quantity attribute whose declared type and value unit disagree; the `untyped` scope covers an untyped attribute whose value determines its type (needs the standard library) | re-types, or writes the inferred type | +| `qualified-names` | off | one target spelled differently across reference sites; the `style` option (`qualified` / `minimal` / `imported`) enforces a policy | re-spells (adding an import under `imported`) | +| `multiline-conditions` | off | a condition chain of `min` or more operands on one line (the formatter's threshold) | — | +| `indentation` | off | leading whitespace off the project's `style` (tabs or spaces) and `size`; verbatim bodies keep their layout | re-indents | +| `generated-provenance-invalid` | error | corrupted transformer ownership: markers without records, wrong or duplicate claims, malformed baselines | — | +| `generated-provenance-baseline-outdated` | info | a provenance record predating the baseline fields (legacy, not tamper) | — | +| `generated-element-modified` | warn | a generated member drifting from its provenance baseline (format-only drift, baseline drift, or a semantic edit) | — | + +`--lib` supplies resolution context only (`dimensional-consistency` stays silent without the standard library's quantity types); library elements are never linted. --- @@ -337,6 +703,8 @@ $ $sysmlv2 convert m.sysml --to compact-json --lib "$lib" | grep -A1 '"type"' Library elements participate in resolution but are not serialized — the output stays scoped to your model. +Native directory loading saves a build- and content-identified `.prepared` snapshot and shares a live prepared library across SDK sessions. Warm loads reuse the resolved graph and static facts; source trees reconstruct on demand. Set `SYSMLV2_CACHE_DIR` to choose the cache directory or `SYSMLV2_LIB_CACHE=off` to disable library caching. A fresh process with a populated disk cache is warm; a retained SDK session also avoids disk decoding. Neither means the operating-system file cache is cold. In-memory/WASM bundles use the separate resolution-only snapshot API. + ### Ambient libraries Whenever a library loads, the toolkit's generated libraries load with it: `Web` (`Web::DOM`, `Web::HTML`, `Web::HTML::Elements` — the Web platform from the standards' WebIDL), `Template` and `Svelte` (the template metamodel and its engine overlay), `WebApp` and `SvelteKit` (the application and route/SSR layers) and `TransformMeta`. A model can reference them without naming their files: @@ -348,13 +716,13 @@ $ $sysmlv2 query --lib "$lib" v.sysml 'V::shell.localName' "div" ``` -Their sources are `local-packages/*.sysml` in the repository; see `local-packages/README.md` for what they contain and how to regenerate them from the pinned corpus and compiler declarations. +Their sources are `local-packages/*.sysml` in the repository; see `local-packages/README.md` for their contents, provenance, and local validation commands. --- ## 6. `convert --to full-json` — the schema-valid full form -The full form adds every derived property and the implied relationships the published `SysML.json` schema requires (44,656/44,656 corpus elements validate; `tests/full_json.rs`): +The full form adds every derived property and the implied relationships the published `SysML.json` schema requires (52,048/52,048 corpus elements validate; `tests/full_json.rs`): ```console $ printf 'part def Vehicle { attribute mass : Real; }\n' | $sysmlv2 convert - --to full-json > full.json @@ -367,6 +735,8 @@ print('name:', pd['name'], '| qualifiedName:', pd['qualifiedName'])" name: Vehicle | qualifiedName: Vehicle ``` +A JSON input (a stored compact or full payload) is converted by loading it into a session and emitting from the model — every element keeps the id it carried, foreign ids included, and lift problems print as warnings — so `convert` and the session API cannot disagree; text inputs emit from the parsed model as before. Without `--lib`, references into the standard library stay the library ids the payload carried. + Compare: the compact form carries ~12 properties per element; the full form carries the complete metaclass property set (`name`, `qualifiedName`, `ownedFeature`, `documentation`, `isLibraryElement`, …). If a work-in-progress model contains unresolved textual references, full JSON and full CBOR preserve their exact spelling by default using schema-valid `TextualRepresentation` annotations. This behavior does not depend on `--flexo`; Flexo changes only the outer payload envelope. @@ -502,7 +872,7 @@ This invariant is gated over all 345 corpus files (`tests/roundtrip.rs`). ## 10. `eval` — compute feature values -The expression evaluator computes bound feature values against the resolved model: operators, sequences, feature references (following values, redefinition-aware), and Kernel Function Library intrinsics including lambda-bodied control functions. +The expression evaluator computes bound feature values against the resolved model: operators, sequences, feature references (following values, redefinition-aware), and Kernel Function Library intrinsics including lambda-bodied control functions. Numbers are exact: decimal literals are rationals, arithmetic never rounds (`0.1 + 0.2` is `0.3`, `100 * 1.1` is `110`), integers grow past the machine word instead of wrapping, and unit conversion factors are exact. A result whose decimal expansion terminates prints as that decimal; any other rational prints as a reduced fraction (`1/3`), which is itself a valid expression. Only transcendental functions (`sqrt` of a non-square, `ln`, `exp`, trigonometry) and non-exact powers produce approximate doubles, and any operation over such a value stays approximate. ```sysml package Demo { @@ -548,7 +918,7 @@ wheelbase = 2700 [mm] overhangs = 900 [mm] length = 3600 [mm] isLong = true -peakPower = 157.08451146716934 +peakPower = 500000/3183 ``` Quantities (`2700 [mm]`) carry their units: same-unit values add and compare on the numbers, scalars scale them, and *different* units never mix silently — `1 [kg] + 1 [mm]` is a type error, not a wrong number. User-defined calculations invoke with positional or named arguments (`Power(rpm = 6000, torque = 250)`), and may recurse (bounded). @@ -561,7 +931,7 @@ Demo::carTotal = 1294 Demo::Vehicle::totalMass = 1094.5 ``` -Across the corpus (with `--lib`), 81.3% of all ~4,000 feature values evaluate; the rest fail with clean errors (`tests/eval.rs` gates this). +The `examples/evalstats` run computes 3,306/3,993 feature values (82.8%); 614 are indeterminate over unbound inputs and 73 return errors. Seventeen errors explicitly reject calculations requiring statement execution. These categories distinguish a computed value from a successful indeterminate result; `tests/eval.rs` gates evaluation without panics. ## 11. `query` — ask the model questions @@ -619,7 +989,7 @@ $ $sysmlv2 query "$vehicle" "size(ownedFeature($vb))" ## 11a. `render` — evaluate a view's component template -A component template imported in semantic mode (the `websysml` generator, `import --semantic`) becomes a `rendering def` plus a `view def`. A `view` usage of that definition exposes a model slice, and `render` evaluates the template over it — each blocks iterate the exposed elements, expression tags evaluate their translated KerML — printing the rendered node tree as JSON, or HTML with `--html`. The model is not modified. +A component template represented as a `rendering def` plus a `view def` can be evaluated over a model. A `view` usage of that definition exposes a model slice, and `render` evaluates the template over it — each blocks iterate the exposed elements, expression tags evaluate their translated KerML — printing the rendered node tree as JSON, or HTML with `--html`. The model is not modified. ```console $ $sysmlv2 render --lib "$lib" --html PackagesView.sysml fleet.sysml Site::packagesView @@ -656,7 +1026,7 @@ $ echo $? 1 ``` -Verdicts are deliberately cautious: a comparison involving an *unbound* feature is undecided, never a false `false` — which keeps the corpus at **0 violated** (ratcheted by `tests/check.rs`). The same discipline covers cardinality: `size(xs)` over an unbound feature answers only what the declared multiplicity proves (an exact `[3]` answers 3, `[1..*]` settles `notEmpty`, anything else stays undecided). +Verdicts are deliberately cautious: a comparison involving an *unbound* feature is undecided, never a false `false` — which keeps the corpus at **0 violated** (ratcheted by `tests/check.rs`). A type default read through an unbound parameter or featured reference — a requirement's `subject` or `ref part`, an actor, a calculation input — is undecided because the instance bound later may override it. A fixed literal still decides; a fixed formula decides only when its inputs are known. This uncertainty survives aliases, conditionals, nested members and calculation calls, while concrete receivers still read their defaults. The same discipline covers cardinality: `size(xs)` over an unbound feature answers only what the declared multiplicity proves (an exact `[3]` answers 3, `[1..*]` settles `notEmpty`, anything else stays undecided). Propagation keeps unknown receiver members free; nested unknown receiver paths stay outside the supported fragment rather than conflating distinct instances. ### Satisfaction claims — subject-bound verdicts @@ -701,8 +1071,8 @@ package Freight { ```console $ $sysmlv2 verify freight.sysml --lib sysml.library -freight.sysml:21:30 (ConstraintUsage): undecided (type error: cannot compare and ) -freight.sysml:26:29 (ConstraintUsage): undecided (type error: cannot compare a quantity with a plain value) +freight.sysml:21:30 (ConstraintUsage): undecided (result is indeterminate over unbound features) +freight.sysml:26:29 (ConstraintUsage): undecided (result is indeterminate over unbound features) freight.sysml:21:30 (ConstraintUsage, satisfies Freight::wagonSpec): satisfied freight.sysml:21:30 (ConstraintUsage, satisfies Freight::wagonSpec): VIOLATED freight.sysml:26:29 (ConstraintUsage, satisfies Freight::wagonSpec): satisfied @@ -764,7 +1134,7 @@ package Tank { ```console $ $sysmlv2 verify tank.sysml --solve -tank.sysml:7:30 fits (AssertConstraintUsage): undecided (type error: numeric operands required) — z3: satisfiable, e.g. radius = 1.5 +tank.sysml:7:30 fits (AssertConstraintUsage): undecided (result is indeterminate over unbound features) — z3: satisfiable, e.g. radius = 1.5 0 satisfied, 0 violated, 1 undecided ``` @@ -772,7 +1142,7 @@ What stays undecided is honestly undecided — a contingent constraint reports a ## 13. `viz` — PlantUML diagrams -`viz` renders one view of a model as PlantUML text (`--view`, default `tree`). Feed the output to any PlantUML build for SVG/PNG; the toolkit itself has no rendering stage. +`viz` renders one view of a model as PlantUML text (`--view tree|interconnection|state|action|sequence|case|mixed`, default `tree`; `ic` and `seq` are accepted short spellings). Feed the output to any PlantUML build for SVG/PNG; the toolkit itself has no rendering stage. The **tree** view is the structure diagram: packages, definitions, and usages with attribute compartments, plus composition (`*--`), typing (`..>`), and specialization (`--|>`) edges. @@ -939,8 +1309,11 @@ package M { $ git show HEAD:model.sysml | $sysmlv2 check - # check a past revision $ curl -s https://example.org/model.json | $sysmlv2 convert - --to text +$ $sysmlv2 lint --format json src/*.sysml | jq '.summary' # machine-readable findings (check too) ``` +A reader that stops early — `$sysmlv2 convert model.json --to text | head` — ends the run quietly: the closed pipe means no more output is wanted, so nothing is printed and the exit status is 0. + --- ## 15. `convert --to compact-cbor` — the binary `.s2c` form @@ -1093,7 +1466,7 @@ $ jq '{magic, versions, flags}' s2c-tables.json { "magic": "d9d9f7da24533243", "versions": { "layout": 1, "scheme": 1, "tables": 1 }, - "flags": { "delta": 4, "deltaPortable": 8, "elideIds": 1, "fullForm": 2, "impliedOwners": 32, "unitPaths": 16 } + "flags": { "delta": 4, "deltaPortable": 8, "elideIds": 1, "explicitIds": 64, "fullForm": 2, "impliedOwners": 32, "unitPaths": 16 } } $ jq '.metaclasses[] | select(.name == "AcceptActionUsage") | .fields[15]' s2c-tables.json { @@ -1108,16 +1481,17 @@ The document carries both ordinal spaces (`metaclasses` for compact payloads, `f ### 15.4 Exporting the standard library — `convert --library` -A normal conversion emits just the user units' elements; its references into the standard library are bare `@id`s that dangle by design (section 9's note). `convert --library` emits the other half — the resolved library itself, every element of the `--lib` units under its normative KerML 9.1 id — so a store can materialize the library once and have every user payload's library references land exactly on its element ids: +A normal conversion emits just the user units' elements; its references into the standard library are bare `@id`s that dangle by design (section 5's note). `convert --library` emits the other half — the resolved library itself, every element of the `--lib` units under its normative KerML 9.1 id — so a store can materialize the library once and have every user payload's library references land exactly on its element ids: ```console -$ $sysmlv2 convert --library --lib "$SYSML_LIBRARY" --to compact-json -o stdlib.json -$ $sysmlv2 convert --library --lib "$SYSML_LIBRARY" --to compact-cbor -o stdlib.s2c +$ export SYSMLV2_AMBIENT=off # measure the 94-unit official library alone +$ $sysmlv2 convert --library --lib "$lib" --to compact-json -o stdlib.json +$ $sysmlv2 convert --library --lib "$lib" --to compact-cbor -o stdlib.s2c $ jq length stdlib.json 91405 $ ls -l stdlib.json stdlib.s2c | awk '{print $5, $9}' -45430871 stdlib.json -3586863 stdlib.s2c +45432383 stdlib.json +3586617 stdlib.s2c ``` (The binary form also benefits from implied ownership backpointers — `CBOR.md`, flag 0x20: backpointers that match their derivation from the forward ownership lists never reach the wire, ~10% of this payload.) @@ -1126,12 +1500,14 @@ The export is deterministic, internally complete (no dangling references; its on ```console $ $sysmlv2 payload stdlib.json | jq .stateDigest -"2480be9a-0642-5b47-8dcf-04fdf030755e" +"c64e4daa-4a49-5052-8adb-d038c3ac6202" $ $sysmlv2 payload stdlib.s2c | jq .stateDigest -"2480be9a-0642-5b47-8dcf-04fdf030755e" +"c64e4daa-4a49-5052-8adb-d038c3ac6202" ``` -Named library elements carry ids derived from their qualified names (KerML 9.1 — identical across conforming implementations, stable across releases while the name is stable). Truly unnamed elements keep this toolkit's deterministic path-based ids: the norm's positional ids count an implementation's implied-relationship closure, so no portable spelling exists for them — and being unnamed, they are never the target of a cross-model reference. `--library` takes no inputs (the `--lib` directory is the input) and targets `compact-json` and `compact-cbor`. +Named library elements carry ids derived from their qualified names (KerML 9.1 — identical across conforming implementations, stable across releases while the name is stable). Truly unnamed elements keep this toolkit's deterministic path-based ids: the norm's positional ids count an implementation's implied-relationship closure, so no portable spelling exists for them — and being unnamed, they are never the target of a cross-model reference. Unset `SYSMLV2_AMBIENT` after reproducing these official-library-only numbers to restore ambient libraries. Byte counts and digests above use the pinned library. `--library` takes no inputs (the `--lib` directory is the input) and targets `compact-json` and `compact-cbor`. + +## 16. Ambient model and library directories Every section above named its input files explicitly. When `SYSMLV2_MODEL_DIR` names a directory, its `.sysml`/`.kerml` files (collected depth-first with siblings in name order; hidden entries skipped) stand in for omitted inputs. Explicit files always win — the variable only fills an absence — and a stderr note records when it did, so output never silently depends on ambient state: @@ -1222,9 +1598,9 @@ mass AttributeUsage `position` counts owned members only (import memberships are not members of the importing namespace); an unresolved name exits 1 with `error: cannot resolve \`…\``. -## 18. `refactor` — extract / inline definitions +## 18. `refactor` — extract / split / inline -The refactoring pair moves a model between the usage-oriented and definition-oriented styles. Both directions run the transformation engine's verified commit: every carried reference is checked at its new home, and a refusal names its reason and leaves every file untouched. Given `model.sysml`: +`extract` and `inline` move a model between the usage-oriented and definition-oriented styles. Both directions run the transformation engine's verified commit: every carried reference is checked at its new home, and a refusal names its reason and leaves every file untouched. Given `model.sysml`: ```sysml package Rig { @@ -1281,6 +1657,83 @@ error: extract refused: not an extractable usage (metaclass PartDefinition) Inline reports imports its deletion leaves unused as `note:` lines on stderr and never removes them itself (that is the LSP quick fix's job). With `SYSMLV2_MODEL_DIR` set, bare invocations read the ambient model for `--dry-run` only — in-place rewriting always requires explicit file paths, the same discipline as `fmt`. +### `split` — one file per nested package + +`refactor split` takes a package apart: every nested package moves to its own file under a directory named after the root file (`--dir` overrides it; `--slug` restricts file names to letters, digits, `.`, `_` and `-`), dedented, with every reference to something outside it spelled in full, and the root package re-exports each one with a `public import` (or a public alias when a package had to be renamed to avoid a root-level collision), so every qualified reference through the root keeps resolving. Given `model.sysml`: + +```sysml +package Root { + part def Frame; + package Chassis { + part def Axle; + part body : Frame; + } + package Drive { + part axle : Chassis::Axle; + } +} +``` + +`--dry-run` prints the plan, the new files and the root's hunk, and writes nothing: + +```console +$ $sysmlv2 refactor split model.sysml Root --dry-run +model/Chassis.sysml: `Root::Chassis` (73 bytes) +model/Drive.sysml: `Root::Drive` (56 bytes) +--- model/Chassis.sysml (new) +package Chassis { + part def Axle; + part body : Root::Frame; +} + +--- model/Drive.sysml (new) +package Drive { + part axle : Root::Chassis::Axle; +} + +--- model.sysml +@@ -3,7 +3,2 @@ +- package Chassis { +- part def Axle; +- part body : Frame; +- } +- package Drive { +- part axle : Chassis::Axle; +- } ++ public import Chassis; ++ public import Drive; +``` + +Without it the files are written and the root is rewritten in place; the pieces check clean together, and running `split` again on a moved file splits deeper: + +```console +$ $sysmlv2 refactor split model.sysml Root +model/Chassis.sysml: `Root::Chassis` (73 bytes) +model/Drive.sysml: `Root::Drive` (56 bytes) +created model/Chassis.sysml +created model/Drive.sysml +split `Root` — rewrote model.sysml +$ cat model.sysml +package Root { + part def Frame; + public import Chassis; + public import Drive; +} +$ $sysmlv2 check model.sysml model/*.sysml && echo clean +clean +``` + +--- + +## 19. `lsp` — the language server + +`sysmlv2 lsp` speaks the Language Server Protocol over stdio until the client ends the session — an editor runs it, not a terminal. It serves parse and body-context diagnostics on every change, whole-document formatting, outline, semantic tokens, navigation, completion, hover, inlay hints, code lenses and refactorings; `--lib` (or `SYSMLV2_LIB_DIR`) adds the standard library so hover, definition, references and rename resolve library names too, and lint findings surface as diagnostics with their fixes as quick fixes. The dialect follows the file extension (`.kerml` is KerML, everything else SysML). Client configuration for VS Code, Neovim and Helix is in [editors/vscode/README.md](editors/vscode/README.md). + +```console +$ $sysmlv2 lsp --help | head -1 +Run the Language Server Protocol server over stdio +``` + --- ## Exit codes @@ -1288,17 +1741,21 @@ Inline reports imports its deletion leaves unused as `note:` lines on stderr and | Command | 0 | 1 | |---|---|---| | `parse` | no diagnostics | any diagnostic | -| `check` | all files parse and validate | any parse or context error | +| `check` | all files parse and validate | any parse or context error (`--strict`: any finding) | +| `lint` | no error-severity finding | an error finding, a parse error, or a `--fix` that would break a file or cannot be written (`--strict`: any finding) | | `fmt` | formatted / already canonical | I/O or parse failure | | `fmt --check` | all files canonical | some file would be reformatted | | `convert` | conversion written | read/parse/convert failure | | `eval` | all named features evaluate | parse failure, unresolved name, or evaluation error | | `query` | the expression evaluates | expression/parse failure, unresolved reference, or evaluation error | | `verify` | no violated constraint | any violation (incl. Z3-proved unsatisfiable) | -| `viz` | diagram written | read/parse failure, unknown --element, --view, or --line-style | +| `viz` | diagram written | read/parse failure or unknown --element | | `describe` | element described | read/parse failure or unresolved name | | `members` | members listed | read/parse failure or unresolved name | | `refactor extract` | extracted (or `--dry-run` diff printed) | refusal (named reason), unresolved name, read/parse/write failure | | `refactor inline` | inlined (or `--dry-run` diff printed) | refusal (named reason), unresolved name, read/parse/write failure | +| `refactor split` | new files written (or `--dry-run` plan printed) | refusal (named reason), unresolved name, read/parse/write failure | + +A value an enumerated option does not accept — `--to`, `--format`, `--view`, `--line-style` — is a usage error: the message lists the possible values and the status is 2, the same as a missing argument or an unknown flag. Every subcommand's `--help` carries worked examples (enforced by `tests/cli.rs`). diff --git a/Cargo.lock b/Cargo.lock index 1673879..a2a1834 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,13 +24,19 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" dependencies = [ "memchr", ] +[[package]] +name = "allocator-api2" +version = "0.2.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "683d7910e743518b0e34f1186f92494becacb047c7b6bf616c96772180fef923" + [[package]] name = "anstream" version = "1.0.0" @@ -67,7 +73,7 @@ version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "40c48f72fd53cd289104fc64099abca73db4166ad86ea0b4341abe65af83dadc" dependencies = [ - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -78,7 +84,7 @@ checksum = "291e6a250ff86cd4a820112fb8898808a366d8f9f58ce16d1f538353ad55747d" dependencies = [ "anstyle", "once_cell_polyfill", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -93,12 +99,41 @@ version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53" +[[package]] +name = "aws-lc-rs" +version = "1.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b281d307588d634de920874890732659e2e7672f72b5e10e81badc1a8a83621e" +dependencies = [ + "aws-lc-sys", + "zeroize", +] + +[[package]] +name = "aws-lc-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9bff6c3b54fad79a2e60b8102caf565819711497c1f5f092f49508e2f5c31b27" +dependencies = [ + "cc", + "cmake", + "dunce", + "fs_extra", + "pkg-config", +] + [[package]] name = "base64" version = "0.22.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" +[[package]] +name = "base64" +version = "0.23.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac07cdecf99051d9a5238b80f35af32cdeba5b336e55d957b318b50137e18da5" + [[package]] name = "bit-set" version = "0.8.0" @@ -122,9 +157,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" [[package]] name = "bitflags" -version = "2.13.0" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4388bee8683e3d04af747c73422af53102d2bd24d9eadb6cbc100baef4b43f8" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "borrow-or-share" @@ -150,17 +185,29 @@ version = "1.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" +[[package]] +name = "cc" +version = "1.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a3eb0f42d6c360dc3f8a821f6bf2fdea7f72bfd36b3076eb0e6d1e9e0752fff4" +dependencies = [ + "find-msvc-tools", + "jobserver", + "libc", + "shlex", +] + [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "clap" -version = "4.6.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ddb117e43bbf7dacf0a4190fef4d345b9bad68dfc649cb349e7d17d28428e51" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", "clap_derive", @@ -168,9 +215,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.6.0" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "714a53001bf66416adb0e2ef5ac857140e7dc3a0c48fb28b2f10762fc4b5069f" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstream", "anstyle", @@ -181,21 +228,30 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.6.1" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ce8604710f6733aa641a2b3731eaa1e8b3d9973d5e3565da11800813f997a9" +checksum = "f9c751b79415d4e559e3d1fcf128e09e720eb673a06d26cf6f392d37d75b66e0" dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] [[package]] name = "clap_lex" -version = "1.1.0" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" + +[[package]] +name = "cmake" +version = "0.1.58" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +checksum = "c0f78a02292a74a88ac736019ab962ece0bc380e3f977bf72e376c5d78ff0678" +dependencies = [ + "cc", +] [[package]] name = "colorchoice" @@ -203,32 +259,70 @@ version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1d07550c9036bf2ae0c684c4297d503f838287c83c53686d05370d0e139ae570" +[[package]] +name = "combine" +version = "4.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfc320937d09e6de266b31b9afb480f197d7a861be86be7cb2ea7e5d1bfffc5e" +dependencies = [ + "bytes", + "memchr", +] + +[[package]] +name = "core-foundation" +version = "0.10.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2a6cd9ae233e7f62ba4e9353e81a88df7fc8a5987b8d445b4d90c879bd156f6" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "core-foundation-sys" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" + [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" + +[[package]] +name = "data-encoding" +version = "2.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "4583a4551df46e2792f82ceeac45e850d2e2d5debba0b91f102385cda5b11f06" [[package]] name = "displaydoc" -version = "0.2.6" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ac70aa55017e108007fbaf5aa0f54b021c98f92ff8af59d42eda9da96e3dd4f" +checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] +[[package]] +name = "dunce" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813" + [[package]] name = "email_address" version = "0.2.9" @@ -238,6 +332,12 @@ dependencies = [ "serde", ] +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + [[package]] name = "errno" version = "0.3.14" @@ -245,20 +345,26 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] name = "fancy-regex" -version = "0.14.0" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e24cb5a94bcae1e5408b0effca5cd7172ea3c5755049c5f3af4cd283a165298" +checksum = "d301f5bf187b3c295fce6468d3875037a0bccc5f6b151c63cac2f85babf21912" dependencies = [ "bit-set", "regex-automata", "regex-syntax", ] +[[package]] +name = "find-msvc-tools" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3e0f1c7c3a72c66fd80abe965175f7523475c0489a87d3ff9d6e8c87d87a9d2d" + [[package]] name = "fluent-uri" version = "0.1.4" @@ -270,15 +376,27 @@ dependencies = [ [[package]] name = "fluent-uri" -version = "0.3.2" +version = "0.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1918b65d96df47d3591bed19c5cca17e3fa5d0707318e4b5ef2eae01764df7e5" +checksum = "bc74ac4d8359ae70623506d512209619e5cf8f347124910440dbc221714b328e" dependencies = [ "borrow-or-share", "ref-cast", "serde", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ce24cb58228fbb8aa041425bb1050850ac19177686ea6e0f41a70416f56fdb" + [[package]] name = "form_urlencoded" version = "1.2.2" @@ -290,19 +408,25 @@ dependencies = [ [[package]] name = "fraction" -version = "0.15.4" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e076045bb43dac435333ed5f04caf35c7463631d0dae2deb2638d94dd0a5b872" +checksum = "e246562084dde8ebbcc943b261c406ce4f68e5032ec28029a251a47d6a295500" dependencies = [ - "lazy_static", "num", + "num-bigint", ] +[[package]] +name = "fs_extra" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42703706b716c37f96a77aea830392ad231f44c9e9a67872fa5548707e11b11c" + [[package]] name = "futures-channel" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "07bbe89c50d7a535e539b8c17bc0b49bdb77747034daa8087407d655f3f7cc1d" +checksum = "b1f9e3d69d39e4862ffed03ed071a76f9a13ba1d9109d355b0f0aa6b15e393c4" dependencies = [ "futures-core", "futures-sink", @@ -310,33 +434,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7e3450815272ef58cec6d564423f6e755e25379b217b0bc688e295ba24df6b1d" +checksum = "92d699e522242e69e3003b94ecc1f960f3a5e015aa7c5d7486e65ad01dd94f5e" [[package]] name = "futures-io" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cecba35d7ad927e23624b22ad55235f2239cfa44fd10428eecbeba6d6a717718" +checksum = "53c0fa8157de1303bfffdaa1cc2a673bfffb60102f76b0ef4441659124373fed" [[package]] name = "futures-sink" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c39754e157331b013978ec91992bde1ac089843443c49cbc7f46150b0fad0893" +checksum = "1944426bf7d03f1d14f708785e4b33efd750b36d48a157b836b3efc15ede8e1d" [[package]] name = "futures-task" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037711b3d59c33004d3856fbdc83b99d4ff37a24768fa1be9ce3538a1cde4393" +checksum = "cd417de3d1d015fc3bfd2b1ea46dfc7bab72ef86f1cc7cc9c78e728b34a6d1fd" [[package]] name = "futures-util" -version = "0.3.32" +version = "0.3.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "389ca41296e6190b48053de0321d02a77f32f8a5d2461dd38762c0593805c6d6" +checksum = "0d50a92467f8ba5dd6e3ee5d4bd04d73ab2e4e1c44474a0674821dfce14b79bc" dependencies = [ "futures-core", "futures-io", @@ -347,6 +471,17 @@ dependencies = [ "slab", ] +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + [[package]] name = "getrandom" version = "0.3.4" @@ -354,9 +489,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "899def5c37c4fd7b2664648c28120ecec138e4d395b459e5ca34f9cce2dd77fd" dependencies = [ "cfg-if", + "js-sys", "libc", "r-efi 5.3.0", "wasip2", + "wasm-bindgen", ] [[package]] @@ -370,6 +507,36 @@ dependencies = [ "r-efi 6.0.0", ] +[[package]] +name = "h2" +version = "0.4.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8e5e5a340588f4452631496976cf8636d4a7ecf600239fdc27615d2530bc16" +dependencies = [ + "atomic-waker", + "bytes", + "fnv", + "futures-core", + "futures-sink", + "http", + "indexmap", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +dependencies = [ + "allocator-api2", + "equivalent", + "foldhash", +] + [[package]] name = "heck" version = "0.5.0" @@ -378,9 +545,9 @@ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" [[package]] name = "http" -version = "1.4.2" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6970f50e31d6fc17d3fa27329444bfa74e196cf62e95052a3f6fee181dba6425" +checksum = "918d3568bebf352712bc2ef3d46a8bcf1a75b373be6539de198e9105cbbf9ce0" dependencies = [ "bytes", "itoa", @@ -388,9 +555,9 @@ dependencies = [ [[package]] name = "http-body" -version = "1.0.1" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" +checksum = "ca2a8f2913ee65f60facd6a5905613afaa448497a0230cc41ce022d93290bc2c" dependencies = [ "bytes", "http", @@ -398,9 +565,9 @@ dependencies = [ [[package]] name = "http-body-util" -version = "0.1.3" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" +checksum = "23169fe34a5fbcdd3f3862e78fb9b6fccd5f02a6dc6f732547005d45631ce71c" dependencies = [ "bytes", "futures-core", @@ -417,14 +584,15 @@ checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" [[package]] name = "hyper" -version = "1.10.1" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55281c53a1894c864990125767da440a4e630446785086f52523b20033b74498" +checksum = "27b501faa50e7a26c3d3560ca625132f4078a17771f4810baf70475ae48cbe43" dependencies = [ "atomic-waker", "bytes", "futures-channel", "futures-core", + "h2", "http", "http-body", "httparse", @@ -435,13 +603,28 @@ dependencies = [ "want", ] +[[package]] +name = "hyper-rustls" +version = "0.27.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ca68d021ef39cf6463ab54c1d0f5daf03377b70561305bb89a8f83aab66e0f" +dependencies = [ + "http", + "hyper", + "hyper-util", + "rustls", + "tokio", + "tokio-rustls", + "tower-service", +] + [[package]] name = "hyper-util" version = "0.1.20" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96547c2556ec9d12fb1578c4eaf448b04993e7fb79cbaad930a656880a6bdfa0" dependencies = [ - "base64", + "base64 0.22.1", "bytes", "futures-channel", "futures-util", @@ -460,9 +643,9 @@ dependencies = [ [[package]] name = "icu_collections" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2984d1cd16c883d7935b9e07e44071dca8d917fd52ecc02c04d5fa0b5a3f191c" +checksum = "fa68d21081c4a05d5a901a1c62add574c77048b6a1c67be3b50ce0b60d4ca513" dependencies = [ "displaydoc", "potential_utf", @@ -474,9 +657,9 @@ dependencies = [ [[package]] name = "icu_locale_core" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92219b62b3e2b4d88ac5119f8904c10f8f61bf7e95b640d25ba3075e6cac2c29" +checksum = "d56e28588da92eee5c3201a6eff33fabdd49b62269c8938d4ff050ce4d900deb" dependencies = [ "displaydoc", "litemap", @@ -487,9 +670,9 @@ dependencies = [ [[package]] name = "icu_normalizer" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c56e5ee99d6e3d33bd91c5d85458b6005a22140021cc324cea84dd0e72cff3b4" +checksum = "12f9cf5f235641ed274641dd81c3f28d870e276763d0797aeeab72317b1c646f" dependencies = [ "icu_collections", "icu_normalizer_data", @@ -501,16 +684,17 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da3be0ae77ea334f4da67c12f149704f19f81d1adf7c51cf482943e84a2bad38" +checksum = "1563da1ed3e0b3bf3d74c9b85917ac9c56464d2f57242270c09c9e752f8021a0" [[package]] name = "icu_properties" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bee3b67d0ea5c2cca5003417989af8996f8604e34fb9ddf96208a033901e70de" +checksum = "7e7ca276ad3145661a65914e6daf131ca5120cd3dcee8f8f3214b8875184a148" dependencies = [ + "displaydoc", "icu_collections", "icu_locale_core", "icu_properties_data", @@ -521,15 +705,15 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e2bbb201e0c04f7b4b3e14382af113e17ba4f63e2c9d2ee626b720cbce54a14" +checksum = "e590f038c1464a96894fd6d10127e90a8be4509f56ff7ecef851b15cee0b7caa" [[package]] name = "icu_provider" -version = "2.2.0" +version = "2.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "139c4cf31c8b5f33d7e199446eff9c1e02decfc2f0eec2c8d71f65befa45b421" +checksum = "d27bbb9d3abbefac45d55f647c9de1d44aafcd1186eb91879afef17c396c3e73" dependencies = [ "displaydoc", "icu_locale_core", @@ -562,19 +746,20 @@ dependencies = [ ] [[package]] -name = "indoc" -version = "2.0.7" +name = "indexmap" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ - "rustversion", + "equivalent", + "hashbrown", ] [[package]] name = "ipnet" -version = "2.12.0" +version = "2.12.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d98f6fed1fde3f8c21bc40a1abb88dd75e67924f9cffc3ef95607bad8017f8e2" +checksum = "791930b43c0d5973160d90a8f3894509f2b273430f5c5c73b668636d0287c5c0" [[package]] name = "is_terminal_polyfill" @@ -588,11 +773,70 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" +[[package]] +name = "jni" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5efd9a482cf3a427f00d6b35f14332adc7902ce91efb778580e180ff90fa3498" +dependencies = [ + "cfg-if", + "combine", + "jni-macros", + "jni-sys", + "log", + "simd_cesu8", + "thiserror", + "walkdir", + "windows-link", +] + +[[package]] +name = "jni-macros" +version = "0.22.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a00109accc170f0bdb141fed3e393c565b6f5e072365c3bd58f5b062591560a3" +dependencies = [ + "proc-macro2", + "quote", + "rustc_version", + "simd_cesu8", + "syn 2.0.119", +] + +[[package]] +name = "jni-sys" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c6377a88cb3910bee9b0fa88d4f42e1d2da8e79915598f65fb0c7ee14c878af2" +dependencies = [ + "jni-sys-macros", +] + +[[package]] +name = "jni-sys-macros" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c0b942f458fe50cdac086d2f946512305e5631e720728f2a61aabcd47a6264" +dependencies = [ + "quote", + "syn 2.0.119", +] + +[[package]] +name = "jobserver" +version = "0.1.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1c00acbd29eabad4a2392fa0e921c874934dbbf4194312ad20f04a0ed67a3cb3" +dependencies = [ + "getrandom 0.4.3", + "libc", +] + [[package]] name = "js-sys" -version = "0.3.103" +version = "0.3.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53b44bfcdb3f8d5837a46dae1ca9660a837176eee74a28b229bc626816589102" +checksum = "ce57d20d1ea864ce2ac172ab472d409214f4fd359f0b2a2775abdf522e2af99e" dependencies = [ "cfg-if", "futures-util", @@ -601,40 +845,65 @@ dependencies = [ [[package]] name = "jsonschema" -version = "0.26.2" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26a960f0c34d5423581d858ce94815cc11f0171b09939409097969ed269ede1b" +checksum = "b6a806f80c1f5560431009ce5ec29b59d38f950e0cd7db5f1b8925e6d8104e21" dependencies = [ "ahash", - "base64", "bytecount", + "data-encoding", "email_address", "fancy-regex", "fraction", + "getrandom 0.3.4", "idna", "itoa", + "jsonschema-regex", + "jsonschema-value", "num-cmp", - "once_cell", + "num-traits", "percent-encoding", "referencing", - "regex-syntax", + "regex", "reqwest", + "rustls", "serde", "serde_json", + "strum", + "unicode-general-category", "uuid-simd", ] [[package]] -name = "lazy_static" -version = "1.5.0" +name = "jsonschema-regex" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "cb862addfa7782108933abcf842fe25334523a9df5b89ea4d9620e3dd7b42181" +dependencies = [ + "regex-syntax", +] + +[[package]] +name = "jsonschema-value" +version = "0.56.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a05cd404c5ff6e2731dbbf7e290a27417750acfb59e329560a1d0af384c93fb0" +dependencies = [ + "ahash", + "bytecount", + "fraction", + "getrandom 0.3.4", + "num-cmp", + "num-traits", + "serde_json", + "zmij", +] [[package]] name = "libc" -version = "0.2.186" +version = "0.2.189" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "linux-raw-sys" @@ -644,21 +913,30 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "litemap" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +checksum = "47d9d19d1d6efa0109d2f65ff4c85cddd50bd572e5a00127ab10987290bcefae" + +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] [[package]] name = "log" -version = "0.4.33" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "lsp-server" -version = "0.7.9" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7d6ada348dbc2703cbe7637b2dda05cff84d3da2819c24abcb305dd613e0ba2e" +checksum = "3ee25a31f2e571e426eef2896179450cafc7e2f5be00d8a93b1c2d21c0ff7656" dependencies = [ "crossbeam-channel", "log", @@ -687,32 +965,29 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf8baf1c55e62ffcace7a9f06f4bd9cd3f0c4beb022d3b367256b91b87513d98" [[package]] -name = "memoffset" -version = "0.9.1" +name = "micromap" +version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a" -dependencies = [ - "autocfg", -] +checksum = "c2a86d3146ed3995b5913c414f6664344b9617457320782e64f0bb44afd49d74" [[package]] name = "miniz_oxide" -version = "0.8.9" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1fa76a2c86f704bdb222d66965fb3d63269ce38518b83cb0575fca855ebb6316" +checksum = "b63fbc4a50860e98e7b2aa7804ded1db5cbc3aff9193adaff57a6931bf7c4b4c" dependencies = [ "adler2", ] [[package]] name = "mio" -version = "1.2.1" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02bd0af71c67b473010cbbc60715ee815645a4dc942899111f494b4b737d6fda" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -756,9 +1031,9 @@ dependencies = [ [[package]] name = "num-integer" -version = "0.1.46" +version = "0.1.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +checksum = "7ce2d95d4b3734dc35aa2f45e1aa22cd416814592a4f9d9205e11affd5b8e10b" dependencies = [ "num-traits", ] @@ -805,12 +1080,41 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "openssl-probe" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" + [[package]] name = "outref" version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a80800c0488c3a21695ea981a54918fbb37abf04f4d0720c453632255e2ff0e" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -823,63 +1127,64 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" +[[package]] +name = "pkg-config" +version = "0.3.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6b464fbc74e149a392436b17d523f769e057cb6877f6a5c4618bc6f11800548" + [[package]] name = "portable-atomic" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3d20d5497ef88037a52ff98267d066e7f11fcc5e99bbfbd58a42336193aacec3" +checksum = "05c8b63e8d9609db387f0324918f81d68fe27748f084ef092fb35954d0539a85" [[package]] name = "potential_utf" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0103b1cef7ec0cf76490e969665504990193874ea05c85ff9bab8b911d0a0564" +checksum = "d83eb9bc6d8e5cf568e7a1101d60ee05e81ed50ea106026f3d18deeb046d7661" dependencies = [ "zerovec", ] [[package]] name = "proc-macro2" -version = "1.0.106" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" dependencies = [ "unicode-ident", ] [[package]] name = "pyo3" -version = "0.23.5" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7778bffd85cf38175ac1f545509665d0b9b92a198ca7941f131f85f7a4f9a872" +checksum = "4688ddedf473e32662b9b067670129a8afb8c18e351482c70d62ba4a88171e8b" dependencies = [ - "cfg-if", - "indoc", "libc", - "memoffset", "once_cell", "portable-atomic", "pyo3-build-config", "pyo3-ffi", "pyo3-macros", - "unindent", ] [[package]] name = "pyo3-build-config" -version = "0.23.5" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "94f6cbe86ef3bf18998d9df6e0f3fc1050a8c5efa409bf712e661a4366e010fb" +checksum = "f41027e41b4bd03f6e60f9f417fe24a6341a6bb744edd62b6f709f2a52ea30e9" dependencies = [ - "once_cell", "target-lexicon", ] [[package]] name = "pyo3-ffi" -version = "0.23.5" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e9f1b4c431c0bb1c8fb0a338709859eed0d030ff6daa34368d3b152a63dfdd8d" +checksum = "e591a95526fead067432c3b3a33fc74770b87b1e04e73671090d9c2055a2b327" dependencies = [ "libc", "pyo3-build-config", @@ -887,34 +1192,33 @@ dependencies = [ [[package]] name = "pyo3-macros" -version = "0.23.5" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbc2201328f63c4710f68abdf653c89d8dbc2858b88c5d88b0ff38a75288a9da" +checksum = "73225868fc1cd84eef2c3c230ddb91273bf1de46aeb8a4248da76d32a0924a1c" dependencies = [ "proc-macro2", "pyo3-macros-backend", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "pyo3-macros-backend" -version = "0.23.5" +version = "0.29.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fca6726ad0f3da9c9de093d6f116a93c1a38e417ed73bf138472cf4064f72028" +checksum = "571575aa3749fa6216757dd47d2a3e7ef360f329a40f0666a9fbd14889024952" dependencies = [ "heck", "proc-macro2", - "pyo3-build-config", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] name = "quote" -version = "1.0.46" +version = "1.0.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" dependencies = [ "proc-macro2", ] @@ -931,44 +1235,69 @@ version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.13.2", +] + [[package]] name = "ref-cast" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f354300ae66f76f1c85c5f84693f0ce81d747e2c3f21a45fef496d89c960bf7d" +checksum = "7e440fb4e4b4147295338efb76001ab9e4efc0e5839df2c47fc5ac2381d365c3" dependencies = [ "ref-cast-impl", ] [[package]] name = "ref-cast-impl" -version = "1.0.25" +version = "1.0.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7186006dcb21920990093f30e3dea63b7d6e977bf1256be20c3563a5db070da" +checksum = "92ecd8964f8453721699a1ed72037b0db49ce2f5a5138486ee89bed6f67cdf3a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] [[package]] name = "referencing" -version = "0.26.2" +version = "0.56.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb8e15af8558cb157432dd3d88c1d1e982d0a5755cf80ce593b6499260aebc49" +checksum = "a3b4a92fac7e28c27de3ad26df2ecb9e652f227b258e845af034052e5b22c96c" dependencies = [ "ahash", - "fluent-uri 0.3.2", - "once_cell", + "fluent-uri 0.4.1", + "getrandom 0.3.4", + "hashbrown", + "itoa", + "micromap", + "parking_lot", "percent-encoding", "serde_json", ] +[[package]] +name = "regex" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f020237b6c8eed93db2e2cb53c00c60a8e1bc73da7d073199a1180401450218d" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + [[package]] name = "regex-automata" -version = "0.4.15" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f388202e4b80542a0921078cc23b6333bcf1409c1e3f86404cae4766a6131db" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ "aho-corasick", "memchr", @@ -989,29 +1318,34 @@ checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" [[package]] name = "reqwest" -version = "0.12.28" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "eddd3ca559203180a307f12d114c268abf583f59b03cb906fd0b3ff8646c1147" +checksum = "16a1cfa75cc186dd73d5818e510e042e40927bccc9c236b061cea97e1eb08029" dependencies = [ - "base64", + "base64 0.23.1", "bytes", "futures-channel", "futures-core", "futures-util", + "h2", "http", "http-body", "http-body-util", "hyper", + "hyper-rustls", "hyper-util", "js-sys", "log", "percent-encoding", "pin-project-lite", + "rustls", + "rustls-pki-types", + "rustls-platform-verifier", "serde", "serde_json", - "serde_urlencoded", "sync_wrapper", "tokio", + "tokio-rustls", "tower", "tower-http", "tower-service", @@ -1021,17 +1355,114 @@ dependencies = [ "web-sys", ] +[[package]] +name = "ring" +version = "0.17.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4689e6c2294d81e88dc6261c768b63bc4fcdb852be6d1352498b114f61383b7" +dependencies = [ + "cc", + "cfg-if", + "getrandom 0.2.17", + "libc", + "untrusted", + "windows-sys 0.52.0", +] + +[[package]] +name = "rustc_version" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfcb3a22ef46e85b45de6ee7e79d063319ebb6594faafcf1c225ea92ab6e9b92" +dependencies = [ + "semver", +] + [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.2", "errno", "libc", "linux-raw-sys", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls" +version = "0.23.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d41d731c7d2f962d1ccc364cec258de3c0e93b38c2fb3ba97ac74513048d634" +dependencies = [ + "aws-lc-rs", + "once_cell", + "rustls-pki-types", + "rustls-webpki", + "subtle", + "zeroize", +] + +[[package]] +name = "rustls-native-certs" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dab5152771c58876a2146916e53e35057e1a4dfa2b9df0f0305b07f611fdea4d" +dependencies = [ + "openssl-probe", + "rustls-pki-types", + "schannel", + "security-framework", +] + +[[package]] +name = "rustls-pki-types" +version = "1.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f4925028c7eb5d1fcdaf196971378ed9d2c1c4efc7dc5d011256f76c99c0a96" +dependencies = [ + "zeroize", +] + +[[package]] +name = "rustls-platform-verifier" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d1e2536ce4f35f4846aa13bff16bd0ff40157cdb14cc056c7b14ba41233ba0" +dependencies = [ + "core-foundation", + "core-foundation-sys", + "jni", + "log", + "once_cell", + "rustls", + "rustls-native-certs", + "rustls-platform-verifier-android", + "rustls-webpki", + "security-framework", + "security-framework-sys", + "webpki-root-certs", + "windows-sys 0.61.2", +] + +[[package]] +name = "rustls-platform-verifier-android" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f87165f0995f63a9fbeea62b64d10b4d9d8e78ec6d7d51fb2125fda7bb36788f" + +[[package]] +name = "rustls-webpki" +version = "0.103.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3c3cf1d8b1e7d4927e2d154c3fcb02979afb9939629c62cd9048d4f07b60ac2" +dependencies = [ + "aws-lc-rs", + "ring", + "rustls-pki-types", + "untrusted", ] [[package]] @@ -1041,16 +1472,63 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf54715a573b99ac80df0bc206da022bcd442c974952c7b9720069370852e21f" [[package]] -name = "ryu" -version = "1.0.23" +name = "same-file" +version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9774ba4a74de5f7b1c1451ed6cd5285a32eddb5cccb8cc655a4e50009e06477f" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "schannel" +version = "0.1.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91c1b7e4904c873ef0710c1f407dde2e6287de2bebc1bbbf7d430bb7cbffd939" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + +[[package]] +name = "security-framework" +version = "3.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b7f4bc775c73d9a02cde8bf7b2ec4c9d12743edf609006c7facc23998404cd1d" +dependencies = [ + "bitflags 2.13.2", + "core-foundation", + "core-foundation-sys", + "libc", + "security-framework-sys", +] + +[[package]] +name = "security-framework-sys" +version = "2.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6ce2691df843ecc5d231c0b14ece2acc3efb62c0a398c7e1d875f3983ce020e3" +dependencies = [ + "core-foundation-sys", + "libc", +] + +[[package]] +name = "semver" +version = "1.0.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a7852d02fc848982e0c167ef163aaff9cd91dc640ba85e263cb1ce46fae51cd" [[package]] name = "serde" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +checksum = "4148590afebada386688f18773da617792bf2ef03ffc1e4cbd2b1d45b023e0ba" dependencies = [ "serde_core", "serde_derive", @@ -1058,29 +1536,29 @@ dependencies = [ [[package]] name = "serde_core" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.228" +version = "1.0.229" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] [[package]] name = "serde_json" -version = "1.0.150" +version = "1.0.151" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +checksum = "c841b55ecdae098c80dcae9cf767f6f8a0c2cdb3416bbef72181df4d0fe73f14" dependencies = [ "itoa", "memchr", @@ -1097,26 +1575,36 @@ checksum = "8d3b1629de253c70a0508c3899572da79ca359fdab27c7920ff00406df418906" dependencies = [ "proc-macro2", "quote", - "syn 3.0.2", + "syn 3.0.6", ] [[package]] -name = "serde_urlencoded" -version = "0.7.1" +name = "sha1_smol" +version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" +checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" + +[[package]] +name = "shlex" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" + +[[package]] +name = "simd_cesu8" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11031e251abf8611c80f460e19dbdeb54a66db918e49c65a7065b46ac7aec520" dependencies = [ - "form_urlencoded", - "itoa", - "ryu", - "serde", + "rustc_version", + "simdutf8", ] [[package]] -name = "sha1_smol" -version = "1.0.1" +name = "simdutf8" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbfa15b3dddfee50a0fff136974b3e1bde555604ba463834a7eb7deb6417705d" +checksum = "e3a9fe34e3e7a50316060351f37187a3f546bce95496156754b601a5fa71b76e" [[package]] name = "slab" @@ -1126,18 +1614,18 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "ba467056f1b547ed52077911161fc86985becbc60e8e1857c8a144dab0def891" [[package]] name = "socket2" -version = "0.6.4" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "52d1cfed4120b4d927bf7c0f86d2087a4a7d6027c906d9f9d525a80573b9be51" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", - "windows-sys", + "windows-sys 0.61.2", ] [[package]] @@ -1152,11 +1640,38 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "strum" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9628de9b8791db39ceda2b119bbe13134770b56c138ec1d3af810d045c04f9bd" +dependencies = [ + "strum_macros", +] + +[[package]] +name = "strum_macros" +version = "0.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab85eea0270ee17587ed4156089e10b9e6880ee688791d45a905f5b1ca36f664" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn 2.0.119", +] + +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "syn" -version = "2.0.118" +version = "2.0.119" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" dependencies = [ "proc-macro2", "quote", @@ -1165,9 +1680,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.2" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a207d6d6a2b7fc470b80443726053f18a2481b7e1eee970597051596567987a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -1185,18 +1700,18 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] [[package]] name = "sysmlv2-cbor" -version = "0.6.0" +version = "0.9.0" dependencies = [ "miniz_oxide", "serde_json", @@ -1208,7 +1723,7 @@ dependencies = [ [[package]] name = "sysmlv2-cli" -version = "0.6.0" +version = "0.9.0" dependencies = [ "clap", "miniz_oxide", @@ -1228,7 +1743,7 @@ dependencies = [ [[package]] name = "sysmlv2-lint" -version = "0.6.0" +version = "0.9.0" dependencies = [ "regex-lite", "serde_json", @@ -1240,11 +1755,12 @@ dependencies = [ [[package]] name = "sysmlv2-lsp" -version = "0.6.0" +version = "0.9.0" dependencies = [ "crossbeam-channel", "lsp-server", "lsp-types", + "serde", "serde_json", "sysmlv2-lint", "sysmlv2-parser", @@ -1255,8 +1771,12 @@ dependencies = [ [[package]] name = "sysmlv2-model" -version = "0.6.0" +version = "0.9.0" dependencies = [ + "num-bigint", + "num-integer", + "num-rational", + "num-traits", "serde", "serde_json", "sysmlv2-syntax", @@ -1265,7 +1785,7 @@ dependencies = [ [[package]] name = "sysmlv2-parser" -version = "0.6.0" +version = "0.9.0" dependencies = [ "jsonschema", "serde_json", @@ -1277,7 +1797,7 @@ dependencies = [ [[package]] name = "sysmlv2-py" -version = "0.6.0" +version = "0.9.0" dependencies = [ "pyo3", "serde_json", @@ -1290,7 +1810,7 @@ dependencies = [ [[package]] name = "sysmlv2-solve" -version = "0.6.0" +version = "0.9.0" dependencies = [ "sysmlv2-model", "sysmlv2-syntax", @@ -1299,15 +1819,18 @@ dependencies = [ [[package]] name = "sysmlv2-syntax" -version = "0.6.0" +version = "0.9.0" +dependencies = [ + "serde", +] [[package]] name = "sysmlv2-testkit" -version = "0.6.0" +version = "0.9.0" [[package]] name = "sysmlv2-transform" -version = "0.6.0" +version = "0.9.0" dependencies = [ "serde_json", "sysmlv2-cbor", @@ -1320,8 +1843,9 @@ dependencies = [ [[package]] name = "sysmlv2-viz" -version = "0.6.0" +version = "0.9.0" dependencies = [ + "serde", "serde_json", "sysmlv2-model", "sysmlv2-syntax", @@ -1330,7 +1854,7 @@ dependencies = [ [[package]] name = "sysmlv2-wasm" -version = "0.6.0" +version = "0.9.0" dependencies = [ "miniz_oxide", "serde", @@ -1348,9 +1872,9 @@ dependencies = [ [[package]] name = "target-lexicon" -version = "0.12.16" +version = "0.13.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1" +checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca" [[package]] name = "terminal_size" @@ -1359,14 +1883,34 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "230a1b821ccbd75b185820a1f1ff7b14d21da1e442e22c0863ea5f08771a8874" dependencies = [ "rustix", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "thiserror" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "2.0.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +dependencies = [ + "proc-macro2", + "quote", + "syn 3.0.6", ] [[package]] name = "tinystr" -version = "0.8.3" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d" +checksum = "b1e27c91459209c2986af3dcf603a5a74a4368754ce37414f59acc971167f643" dependencies = [ "displaydoc", "zerovec", @@ -1374,15 +1918,40 @@ dependencies = [ [[package]] name = "tokio" -version = "1.52.3" +version = "1.53.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fc7f01b389ac15039e4dc9531aa973a135d7a4135281b12d7c1bc79fd57fffe" +checksum = "202caea871b69668250d242070849eb495be178ed697a3e98aebce5bc81a0bed" dependencies = [ + "bytes", "libc", "mio", "pin-project-lite", "socket2", - "windows-sys", + "windows-sys 0.61.2", +] + +[[package]] +name = "tokio-rustls" +version = "0.26.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0c85f2c3ef0b1cd58b36682f4b17aaa995f0e5db534d85692b4903abce21f67" +dependencies = [ + "rustls", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "494815d09bf52b5548659851081238f0ca39ff638363907596da739561c62c52" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "libc", + "pin-project-lite", + "tokio", ] [[package]] @@ -1406,7 +1975,7 @@ version = "0.6.11" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4cfcf7e2740e6fc6d4d688b4ef00650406bb94adf4731e43c096c3a19fe40840" dependencies = [ - "bitflags 2.13.0", + "bitflags 2.13.2", "bytes", "futures-util", "http", @@ -1455,17 +2024,23 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "unicode-general-category" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b993bddc193ae5bd0d623b49ec06ac3e9312875fdae725a975c51db1cc1677f" + [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "ab72a15cf68d77cb0987d3684aa8a45c5ef827e8cb49ee2f30bfd7ba2feb519f" [[package]] -name = "unindent" -version = "0.2.4" +name = "untrusted" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3" +checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1" [[package]] name = "url" @@ -1493,12 +2068,13 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" [[package]] name = "uuid" -version = "1.23.4" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf80a72845275afea99e7f2b434723d3bc7e38470fcd1c7ed39a599c73319a53" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" dependencies = [ "getrandom 0.4.3", "js-sys", + "serde_core", "sha1_smol", "wasm-bindgen", ] @@ -1510,7 +2086,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23b082222b4f6619906941c17eb2297fff4c2fb96cb60164170522942a200bd8" dependencies = [ "outref", - "uuid", "vsimd", ] @@ -1526,6 +2101,16 @@ version = "0.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c3082ca00d5a5ef149bb8b555a72ae84c9c59f7250f013ac822ac2e49b19c64" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -1552,9 +2137,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.126" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b067c0c11094aef6b7a801c1e34a26affafdf3d051dba08456b868789aaf9a4" +checksum = "aecb87a33d3b0c5e3b7aa46336eaf486cffafbd281b195e4c8b80d50df2351bf" dependencies = [ "cfg-if", "once_cell", @@ -1565,9 +2150,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-futures" -version = "0.4.76" +version = "0.4.78" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c62df1340f32221cb9c54d6a27b030e3dba64361d4a95bed55f9aacb44da291d" +checksum = "6ef4c5d3d2cdf5c54f4231181768f5510842e350db025faf1f7163b1030ed928" dependencies = [ "js-sys", "wasm-bindgen", @@ -1575,9 +2160,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.126" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "167ce5e579f6bcf889c4f7175a8a5a585de84e8ff93976ce393efa5f2837aab1" +checksum = "a690d511e3c1a8b3a55e33511e3c2c00c78415cd23650f32b808627f5696b9ed" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1585,42 +2170,69 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.126" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3997c7839262f4ef12cf90b818d6340c18e80f263f1a94bf157d0ec4420380e" +checksum = "411e4887f0071ef2d2164a9d5fdf2d20efbef78fccd3a78b0c10a1dc5295e48a" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.126" +version = "0.2.128" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc1b4cb0cc549fcf58d7dfc081778139b3d283a081644e833e84682ad71cea24" +checksum = "81941cd78d0c92026c33e5e01312845a4cb1e9af3407f9134b100dd03144103e" dependencies = [ "unicode-ident", ] [[package]] name = "web-sys" -version = "0.3.103" +version = "0.3.105" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8622dcb61c0bcc9fffa6938bed81210af2da9a7e4a1a834b2e37a59b6dfb6141" +checksum = "9fbddc4a036f00ec4f18c83445bd3115cb306a91da554919a099d9222fe4a7f8" dependencies = [ "js-sys", "wasm-bindgen", ] +[[package]] +name = "webpki-root-certs" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b96554aa2acc8ccdb7e1c9a58a7a68dd5d13bccc69cd124cb09406db612a1c9b" +dependencies = [ + "rustls-pki-types", +] + +[[package]] +name = "winapi-util" +version = "0.1.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "windows-link" version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-sys" +version = "0.52.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" +dependencies = [ + "windows-targets", +] + [[package]] name = "windows-sys" version = "0.61.2" @@ -1630,6 +2242,70 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "wit-bindgen" version = "0.57.1" @@ -1638,9 +2314,9 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "writeable" -version = "0.6.3" +version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1ffae5123b2d3fc086436f8834ae3ab053a283cfac8fe0a0b8eaae044768a4c4" +checksum = "3ad82d2a33cdc9674dc7465672f271e096168fcdbe0f799d9e6db8c5892679dc" [[package]] name = "xattr" @@ -1665,34 +2341,34 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.2" +version = "0.8.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +checksum = "33811428bee40dbceb6d545e95754741d17a6aef9a4849f0fd62e2ba4f412a78" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.54" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b7cbbc0a705a0fd05cc3676525980d2bf5a9bc4adac6d6475209a7887cf59d19" +checksum = "d35102a9f36d089ccae9e4c6802bc118be4487b80aaffc0ab4e0cf5ce92d2873" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.54" +version = "0.8.57" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e2e817b7b52d0c7358d3246da9d69935ebb18116b2b102b4230dac079b4862f5" +checksum = "146c01f5ab44258da43cf276c74a2763db2ff3969c9c652c3f2de07041d0b2bc" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 2.0.119", ] [[package]] @@ -1706,21 +2382,27 @@ dependencies = [ [[package]] name = "zerofrom-derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", "synstructure", ] +[[package]] +name = "zeroize" +version = "1.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e" + [[package]] name = "zerotrie" -version = "0.2.4" +version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f9152d31db0792fa83f70fb2f83148effb5c1f5b8c7686c3459e361d9bc20bf" +checksum = "4ea269c3bd32f0a32c321907a2ae912ba6f4649bb0fc764a15627e99a7095a3f" dependencies = [ "displaydoc", "yoke", @@ -1729,9 +2411,9 @@ dependencies = [ [[package]] name = "zerovec" -version = "0.11.6" +version = "0.11.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239" +checksum = "bb0464e17806c1d976d5cba29399c7f08e516e279e2ba493f63123b5fca67dd8" dependencies = [ "yoke", "zerofrom", @@ -1740,17 +2422,17 @@ dependencies = [ [[package]] name = "zerovec-derive" -version = "0.11.3" +version = "0.11.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "625dc425cab0dca6dc3c3319506e6593dcb08a9f387ea3b284dbd52a92c40555" +checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 2.0.118", + "syn 3.0.6", ] [[package]] name = "zmij" -version = "1.0.21" +version = "1.0.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" +checksum = "29666d0abbfad1e3dc4dcf6144730dd3a3ab225bbbdac83319345b1b44ccfc1b" diff --git a/Cargo.toml b/Cargo.toml index 3748de1..7d467e3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -44,22 +44,22 @@ default-members = [ ] [workspace.package] -version = "0.6.0" +version = "0.9.0" edition = "2021" -rust-version = "1.86" +rust-version = "1.97" license = "Apache-2.0" repository = "https://github.com/Open-MBEE/sysml-toolkit" [workspace.dependencies] -sysmlv2-parser = { path = "crates/sysmlv2-parser", version = "0.6.0" } -sysmlv2-cbor = { path = "crates/sysmlv2-cbor", version = "0.6.0" } -sysmlv2-solve = { path = "crates/sysmlv2-solve", version = "0.6.0" } -sysmlv2-lint = { path = "crates/sysmlv2-lint", version = "0.6.0" } +sysmlv2-parser = { path = "crates/sysmlv2-parser", version = "0.9.0" } +sysmlv2-cbor = { path = "crates/sysmlv2-cbor", version = "0.9.0" } +sysmlv2-solve = { path = "crates/sysmlv2-solve", version = "0.9.0" } +sysmlv2-lint = { path = "crates/sysmlv2-lint", version = "0.9.0" } sysmlv2-testkit = { path = "crates/sysmlv2-testkit" } -sysmlv2-transform = { path = "crates/sysmlv2-transform", version = "0.6.0" } -sysmlv2-viz = { path = "crates/sysmlv2-viz", version = "0.6.0" } -sysmlv2-lsp = { path = "crates/sysmlv2-lsp", version = "0.6.0" } -lsp-server = "0.7" +sysmlv2-transform = { path = "crates/sysmlv2-transform", version = "0.9.0" } +sysmlv2-viz = { path = "crates/sysmlv2-viz", version = "0.9.0" } +sysmlv2-lsp = { path = "crates/sysmlv2-lsp", version = "0.9.0" } +lsp-server = "0.10" lsp-types = "0.97" crossbeam-channel = "0.5" serde = { version = "1", features = ["derive"] } @@ -70,9 +70,13 @@ serde = { version = "1", features = ["derive"] } serde_json = { version = "1", features = ["float_roundtrip"] } uuid = { version = "1", features = ["v4", "v5", "js"] } clap = { version = "4", features = ["derive", "wrap_help", "env"] } -jsonschema = "0.26" -miniz_oxide = "0.8" +jsonschema = "0.56" +miniz_oxide = "0.9" regex-lite = "0.1" +num-bigint = "0.4" +num-integer = "0.1" +num-rational = "0.4" +num-traits = "0.2" # The wasi CLI artifact is size-sensitive: it ships in # the npm package and browsers fetch it lazily. Opt-in profile — native @@ -84,3 +88,12 @@ lto = true codegen-units = 1 strip = true panic = "abort" + +# Shipped native binaries (the release build matrix) — whole-program +# optimisation is worth the build time there and nowhere else: the +# test job keeps the stock release profile so its many test binaries +# link quickly. +[profile.dist] +inherits = "release" +lto = "fat" +codegen-units = 1 diff --git a/IDS.md b/IDS.md index 83e9e74..8928f8f 100644 --- a/IDS.md +++ b/IDS.md @@ -4,7 +4,7 @@ How this toolkit assigns `@id`s to **user-model** elements. The scheme makes eve On the wire, this derivation is stamped as **id-scheme 1** in the payload header of the binary interchange form (`CBOR.md`): id-elided payloads (snapshot or delta) refuse a scheme they don't carry, while explicit-id payloads ignore the stamp entirely. -Standard-library elements are unaffected: named library elements keep their normative KerML 9.1 name-based UUIDs, positional library elements keep their sealed-snapshot ids. +Standard-library elements are unaffected: named library elements keep their normative KerML 9.1 name-based UUIDs, unnamed library elements keep their deterministic toolkit-local path ids. ## The derivation diff --git a/INTEROP.md b/INTEROP.md index 260f92a..2a5096f 100644 --- a/INTEROP.md +++ b/INTEROP.md @@ -1,15 +1,16 @@ # Interchange conformance notes -How this toolkit's interchange JSON relates to the normative sources — the OMG pilot implementation (its Xtext grammars vendored in `spec-refs/`, the published 20250201 JSON schemas and XMI metamodel) — and what to expect when exchanging payloads with other SysML v2 implementations. Representation choices below were adjudicated against the pilot implementation as the normative reference (2026-07-16); where other tools serialize differently, this toolkit follows the pilot. +How this toolkit's interchange JSON relates to the normative sources — the OMG pilot implementation (its Xtext grammars vendored in `spec-refs/`, the published 20250201 JSON schemas and XMI metamodel) — and what to expect when exchanging payloads with other SysML v2 implementations. Representation choices below were adjudicated against the pilot implementation as the normative reference; where other tools serialize differently, this toolkit follows the pilot. ## Conformance level of the full form -Both compact (KerML 10.4) and full-form (Systems Modeling API element list) output validate against the published 20250201 JSON schemas. The full form computes derived properties where the derivation is structural and emits the inheritance/import closures as type-correct empty values — the API's "passthrough" level — so payload size stays proportional to the model. Implementations that materialize the inherited/implied closures per element will produce much larger payloads for the same model; both are schema-valid, and this toolkit reads either. +Full-form output validates against the published 20250201 JSON schemas, with one documented departure: the value of a numeric literal that no JSON number denotes exactly is emitted as the literal's own text, where the schema declares `LiteralInteger.value` an integer or null and `LiteralRational.value` a number or null (see *Numeric literal values* below for why, and `crates/sysmlv2-parser/tests/full_json.rs`, where the schema check's expectations live, for the exception itself). Compact output contains owned properties and deliberately omits derived properties required by those schemas; it is checked separately against the XMI property inventory. The full form computes every derived property the derivation layer answers (API.md §7) and, by default, emits the inheritance/import closures as type-correct empty values and the inheritance-aware properties over the owned side — the API's "passthrough" level — so payload size stays proportional to the model. Under the closure policy (`EmissionPolicy::closures`, `sysmlv2 convert --to full-json` keeps the passthrough level) the four closure names — `inheritedMembership`, `inheritedFeature`, `importedMembership`, `featuringType` — are written and the inheritance-aware properties carry their specification values over the inherited and imported memberships, with or without the implied library heritage. Measured on the standard corpus (251 files, library loaded): the closure form over the written heritage is 1.25× the passthrough payload, and 2.31× with the implied heritage (every part listing the members of `Parts::Part` and its bases). Both forms are schema-valid and this toolkit reads either; a model whose heritage is deeper than the resolver's depth budget (24 levels) is refused under the closure policy rather than written with a truncated closure. ## Representation rules (per the pilot) - **Operator-expression operands** are wrapped: each operand becomes the `FeatureValue` of an owned `in` parameter Feature under a **private** ParameterMembership (pilot `OperandEList` / `TypeUtil.addOwnedParameterTo`; the 20250201 metamodel removed the old `operand` containment). Explicit argument lists (`f(a, b)`) wrap the same way with default visibility (KerML.xtext `ArgumentMember`). - **Effective names**: `Membership.memberName` and full-form `name` derive from an unnamed feature's naming feature — the first redefined feature (`attribute :>> uid = 4;` is member-named `uid`), a referenced feature, or a chain's last link (pilot `Element::name → effectiveName()` → `Feature::namingFeature`). Binary connector/succession ends take their computed positional names (`source`/`target`, `earlierOccurrence`/`laterOccurrence`), payloads `payload`, return parameters `result`, subjects `subj`, objectives `obj`. +- **Qualified names** follow the `escapedName` derivation literally (KerML 8.3.2.1): only a name without the form of a basic name is quoted, so a reserved word used as a name stays bare — `ControlFunctions::if`, `ViewDefinition::view` — which is the spelling the normative library ids (below) hash and the pilot implementation's XMI carries. `qualifiedName` is therefore a model property, not guaranteed to parse as a reference; textual emission quotes such names (`'part'::'view'`). - **`isComposite`/`isReference`**: SysML usages are composite by default, except the inherently referential metaclasses (attribute, reference, enumeration, binding/succession-as-usage, event, exhibit, include, perform — pilot `*Impl` constructors), `ref`/directed/`end` declarations, usages with no featuring type, and non-subport ports. `isReference` derives as the negation; the `ref` keyword round-trips exactly. - **Membership-implied directions**: subjects/actors/stakeholders are `in`, return parameters `out` (pilot `ParameterMembershipAdapter`). - **Metadata usages** are AnnotatingElements owned via **OwningMembership** even in type bodies (unfeatured, referential); a bare about-less `@M;` member canonicalizes to the `#M` prefix shape. @@ -17,6 +18,7 @@ Both compact (KerML 10.4) and full-form (Systems Modeling API element list) outp - **Classification/cast/extent expressions**: type references are owned parameter Features with a `FeatureTyping`; casts use a ReturnParameterMembership; the implicit subject spells as a self-reference; the `meta`/`@@` left side as a MetadataAccessExpression. - **Connector ends** are ReferenceUsages (pilot `ConnectorEnd` rule), succession ends included; interface ends are PortUsages (pilot InterfaceEnd/DefaultInterfaceEnd). Flow ends follow the pilot's `FlowEnd` rule (prefix ReferenceSubsetting when spelled, plus an owned ReferenceUsage whose FlowRedefinition targets the last step). - **Multiplicity bounds**: the pilot's `MultiplicityBounds` rule owns the bound literals directly under the MultiplicityRange (no operator wrapping). +- **Numeric literal values** carry a JSON number whenever one denotes the written literal exactly, and the literal's own text otherwise. A JSON number is a 64-bit integer or a double, so it holds neither an integer past 64 bits, nor more significant digits than a double's precision, nor an exponent outside its range; evaluation reads literals exactly, so emitting a rounded number there would make a model's JSON form and its textual form disagree. `LiteralInteger.value` is thus `12` but `"170141183460469231731687303715884105727"`, and `LiteralRational.value` is `3.5` or `0.1` but `"1.234567890123456789012345678901"` and `"1e400"`. Readers accept either spelling for both metaclasses; a string value is parsed as the literal text it is. The published schema declares both properties numeric, so the text spelling is the one departure from it noted above. - Variations (and enum definitions) are implicitly abstract; exposes force `isImportAll`; chain/index/collect/select expressions carry their fixed `operator`; multi-step chain expressions flatten to a single FeatureChainExpression + OwnedFeatureChain member. - Every SysML port definition owns its implicit `~P` ConjugatedPortDefinition (OwningMembership, declaredName `~P`) with the PortConjugation pointing back at the original. - Satisfy `by` targets bind per the pilot's `SatisfactionFeatureValue`; named invocation/constructor arguments own the pilot's `ParameterRedefinition` of the callee's parameter; positional arguments take the callee's `in` parameter names (in-document callees); binding connector ends take the `Links::SelfLink` positional names `thisThing`/`sameThing`. @@ -28,10 +30,11 @@ Top-level standard-library packages get `uuid5(NameSpace_URL, prefix + escapedNa ## Known gaps +The complete derived-property census — every `isDerived` name with its class (structural, inheritance-aware, closure) and whether the emitter derives it — is generated into [`spec-refs/derived-properties.md`](spec-refs/derived-properties.md) by `tools/derived_census.py`; the bullets below are the hand-maintained notes that the census does not express. + - Implied end-**Redefinition elements** for binary connector ends are not emitted (the positional *names* are derived, the relationships are not). -- `mayTimeVary`/SysML `isVariable` stay passthrough-null (their derivation needs library conformance walks). -- Named invocation arguments keep the `memberName` spelling in some paths; the pilot additionally owns a `ParameterRedefinition` inside the argument Feature (no corpus coverage to gate a fix). -- The implicit `~P` `conjugatedPortDefinition` owner-side property is tracked in `tests/xmi_audit.rs`. +- `mayTimeVary`/SysML `isVariable` are set for variation/enum cases recognized structurally; complete derivation through library conformance remains limited. +- The compact owner-side `conjugatedPortDefinition` property remains an explicit XMI-audit omission. The implicit `~P` element and full-form property are emitted; this is a property-coverage gap, not absence of the conjugated element. ## Diagnostics philosophy: errors vs. warnings @@ -44,3 +47,7 @@ The binary form (`CBOR.md`) is a byte-level re-encoding of the compact interchan ## Element ids (scheme 1) User-element `@id`s are graph-derived (see `IDS.md`): chained UUIDv5 from the document root through ownership, with name-based segments for membership-owned named elements — chained past the membership's ordinal, so a named member and its membership derive from the owner and the member's name alone — and positional segments otherwise. Consequence for interchange consumers: every non-root id of a compact payload is recomputable from structure + names (`ids::derive_ids`), and re-emitting a model from text is id-stable under edits that do not move or rename the element's own ancestry — including inserting members before it. Payloads that carry explicit ids lift verbatim. Library element ids are unchanged (normative KerML 9.1 where named). + +## Anonymous redefinition targets + +Sibling anonymous redefinitions such as `ref :>> items = a;` and `ref :>> items = b;` resolve their target against the inherited feature, including an inherited override. Their inferred local names cannot resolve each other's `redefinedFeature`. Each occurrence remains a distinct feature; compact JSON and navigation reference sites point at the same intended base target. Declared local targets remain available, and missing or genuinely ambiguous inherited targets still produce findings. diff --git a/README.md b/README.md index 573fd87..f716e3d 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,9 @@ A Rust toolchain for [OMG SysML v2](https://www.omg.org/sysml/sysmlv2/) and KerM - **Resolve** names across files and against the vendored standard library (normative KerML 9.1 element IDs, verified against the published XMI). - **Interchange JSON in both directions** — emit the compact (KerML 10.4) and full (derived properties + implied relationships) forms, and read JSON back to text. - **Binary interchange (s2c)** — a deterministic CBOR encoding of the compact form (`.s2c`, RFC 9277 file magic): ~10× under minified JSON, optional id elision (~15–19× with an integrity digest), full-form emit, and digest-verified delta payloads for commit-sized changes. -- **Validate** — body-context legality, duplicate names, referential checks, and semantic constraints (multiplicity bounds, specialization cycles, redefinition compatibility, invocation arity). -- **Lint** — configurable project-policy rules (style, hygiene, dead model) with optional auto-fixes, additive beside `check`. -- **Evaluate** expressions: KerML Function Library intrinsics, lambdas, quantities with unit conversion, user-defined calculations, featuring-context rollups. +- **Validate** — body-context legality, duplicate names, referential checks, and semantic constraints (usage typing, multiplicity bounds, specialization cycles, redefinition compatibility, argument binding, and quantity dimensions). +- **Lint** — configurable project-policy rules (style, hygiene, dead model) with optional auto-fixes, additive beside `check`; both verbs report as rustc-style text or as one JSON document. +- **Evaluate** expressions exactly: rational arithmetic with no rounding (`0.1 + 0.2 == 0.3`), KerML Function Library intrinsics, lambdas, quantities with exact unit conversion, user-defined calculations, featuring-context rollups. - **Verify constraints** to satisfied / violated / undecided verdicts, and **solve** the undecided ones with Z3 (witnesses, unsatisfiability and validity proofs) or the built-in interval propagator. - **Transform** — rename, set value, insert, remove, retarget, extract and inline definitions as span-anchored text splices that preserve formatting and notes byte-for-byte, with commits that reparse, re-resolve, and verify untouched references kept their targets. - **Visualize** as PlantUML — seven views (structure tree, interconnection, state, action, sequence, use case, mixed) with comment notes, metadata stereotypes, inherited members, color palettes, and clickable source hyperlinks carried into rendered SVG. @@ -44,11 +44,12 @@ sysmlv2 fmt --check src/*.sysml # canonical formatter (notes preserved) sysmlv2 check model.sysml --lib sysml.library/ # validation + referential/semantic checks sysmlv2 check --strict --lib sysml.library/ *.sysml # warnings fail too (gate a commit) sysmlv2 lint model.sysml --fix # project-policy rules, auto-fixable ones applied +sysmlv2 lint --format json model.sysml # findings as one JSON document on stdout (check too) sysmlv2 eval model.sysml --lib sysml.library/ # evaluate feature values sysmlv2 verify model.sysml --solve # constraint verdicts; Z3 for the undecided sysmlv2 query model.sysml 'ownedFeature(Demo::Vehicle)->select { in p; p istype Demo::Wheel }' -sysmlv2 refactor extract model.sysml Demo::car # usage↔definition refactorings (extract / inline) -sysmlv2 payload diff before.s2c after.s2c # inspect, diff, and apply interchange payloads +sysmlv2 refactor extract model.sysml Demo::car # usage↔definition refactorings (extract / split / inline) +sysmlv2 payload after.s2c --delta-from before.s2c -o commit.s2c # inspect, diff, and apply interchange payloads sysmlv2 describe model.sysml Demo::car # one element: metaclass, owner, typing, position sysmlv2 viz model.sysml --view mixed --color | java -jar plantuml.jar -tsvg -p > model.svg sysmlv2 lsp # the language server over stdio @@ -59,7 +60,7 @@ Every subcommand's `--help` carries a description and worked examples (enforced ### Standard-library cache -Loading a standard library with `--lib` is cached automatically — no flags involved. The first run against a given library builds it cold and records a *sealed snapshot* (reference resolutions plus final element ids) at `~/.cache/sysmlv2/stdlib-.libcache`; later runs replay it, cutting a warm `check --lib` to well under 0.1 s for typical models. The cache is keyed by toolkit version and library content and carries its own integrity checks, so an edited library, a toolkit upgrade, or a corrupted file just triggers a cold rebuild that rewrites the snapshot — it can never change a result (cold and warm builds are gated byte-identical in `tests/libcache.rs`). +Loading a standard library with `--lib` is cached automatically. The first run prepares its parsed units, resolved graph and static-analysis indexes, then saves a build- and content-identified snapshot at `~/.cache/sysmlv2/stdlib-.prepared`. A resolution recording (`stdlib-.libcache`) is saved beside it for the rare builds that must resolve jointly. Later processes load the snapshot without parsing or resolving library sources. Directory-backed SDK sessions can also share a live prepared library across edits. Library snapshots store property and relationship rows in contiguous tables, share decoded property strings, and omit redundant headers from fixed-layout records. Library source text is retained and syntax trees are reconstructed only when requested or needed for joint resolution. Scope names and identity indexes load as checked sorted tables; expression metadata remains available for calculations. Typed graph properties, direct ownership indexes and cached unit/dimension results reduce repeated work. Connector checks reuse the same ownership and binary target indexes as other validators. Static-fact adjacency tables read checked offsets and contiguous values directly; only edited library rows and new model rows need private storage. Each model adds private elements, scopes and index entries over the immutable library prefix; user resolution, semantic checks and import analysis still run. Rust callers use `prepared::load_library_with_cache` for this path; `Model::load_library_dir` parses directly. `Model::units()` requests every syntax tree; `unit_count()` and `is_library_unit(index)` avoid reconstruction, and `unit(index)` requests one tree. `ModelUnit.unit` is `Arc`. Root declarations or root-level imports that supply a name the library looked up and missed select a joint build, which replays the recording for every outcome those names cannot reach. Edited libraries, toolkit changes and damaged snapshots trigger rebuilding; an unwritable cache does not prevent analysis. Initial preparation costs more than a warm load. The existing resolution-only snapshot APIs remain available for in-memory library bundles. Two environment variables control it: @@ -72,6 +73,12 @@ Two environment variables control it: Every model that loads a library also sees the generated Web platform libraries under [local-packages/](local-packages/) (`Web::DOM`, `Web::HTML::Elements`, `Template`, `Svelte`, `WebApp`, `SvelteKit`, `TransformMeta`) without naming their files; `SYSMLV2_AMBIENT=off` switches them off. `SYSMLV2_MODEL_DIR` and `SYSMLV2_LIB_DIR` supply inputs and the library for verbs invoked without file arguments. +### Calculation and static-analysis boundaries + +Calculations with expression results, local feature values, and positional or named inputs can be evaluated. Duplicate bindings and missing required inputs fail explicitly; omitted inputs use their own defaults without capturing same-named caller parameters. Bodies requiring assignments, loops, or action execution return `Unsupported`, including direct reads of their output initializers, and are not inlined by the solver. Behavioral execution belongs to a separate layer. Lambda bodies with unmodelled local declarations also fail explicitly. + +Dimensional arithmetic is checked from declared quantity types even when parameter values are unbound. Unknown dimensions remain undecided. This check is conservative: it does not yet infer dimensions through arbitrary invocations or lambda bodies. The pinned [OpenSysML negative fixtures](crates/sysmlv2-parser/tests/fixtures/opensysml/) record both diagnostic baselines and remaining gaps; accepting a negative fixture is not counted as validation success. + ### Partial models Work-in-progress models with unresolved references are first-class: `check` reports them as warnings (promote with `--strict`), and full-form JSON and CBOR carry schema-valid recovery annotations by default (standard `TextualRepresentation` elements) so the exact source references are restored on conversion back to text — a partial model committed to a repository round-trips losslessly. @@ -91,17 +98,17 @@ The repository is a Cargo workspace. Everything is licensed under Apache-2.0; th | [`sysmlv2-viz`](crates/sysmlv2-viz) | PlantUML emission, seven views | | [`sysmlv2-lsp`](crates/sysmlv2-lsp) | The Language Server Protocol server (stdio and an embeddable push-driven core) | | [`sysmlv2-parser`](crates/sysmlv2-parser) | Compatibility facade re-exporting `sysmlv2-syntax` and `sysmlv2-model` under one crate; hosts the corpus test suites and triage examples | -| [`sysmlv2-cli`](crates/sysmlv2-cli) | The `sysmlv2` binary — every capability above as subcommands, plus `.kpar` project archives, Flexo change-record payloads, and a wasi build for browsers | +| [`sysmlv2-cli`](crates/sysmlv2-cli) | The `sysmlv2` binary — every capability above as subcommands, plus `.kpar` project archives, Flexo change-record payloads, and a wasi build for browsers; the verbs are also a library (`run(args)` and one function per verb) so a host drives them in process | | [`sysmlv2-py`](crates/sysmlv2-py) | Python binding (module `sysmlv2`): the whole session surface — `Session.from_files(...)`, queries, find-usages, batch edits with verified commits — as abi3 wheels via maturin | | [`sysmlv2-wasm`](crates/sysmlv2-wasm) | WebAssembly/JavaScript binding (`@sysml/wasm`): sessions, checking, interchange, diagrams, and the language server, with the standard library bundled | | [`sysmlv2-testkit`](crates/sysmlv2-testkit) | Dev-only corpus helpers shared by the workspace's tests and examples (not published) | Alongside the crates: -- [`editors/vscode`](editors/vscode) — the VS Code extension: dialect-aware TextMate highlighting plus the language-server client. -- [`local-packages/`](local-packages) — the generated ambient libraries and their provenance sidecars, produced by the separate `websysml` generator (not yet published). +- [`editors/vscode`](editors/vscode) — the VS Code extension: semantic highlighting with a TextMate fallback, plus the language-server client. +- [`local-packages/`](local-packages) — the generated ambient libraries and their provenance sidecars; checked-in sources work without a generator. - [`spec-refs/`](spec-refs) — the pinned normative grammars, JSON schemas, and metamodel XMI, plus the official corpus and an external validation corpus as submodules (see [spec-refs/README.md](spec-refs/README.md)). -- [`tools/`](tools) — the release script, the generators for the spec-derived tables (`gen_cbor_tables.py`, `xmi_props.py`), and the `SDK.md` doctest runner. +- [`tools/`](tools) — the generators for the spec-derived tables (`gen_cbor_tables.py`, `gen_metaclass_hierarchy.py`, `xmi_props.py`), the `SDK.md` doctest runner, and the release and public-export scripts. ## Status @@ -113,18 +120,18 @@ Alongside the crates: | Expression grammar (KerML Expressions) | ✅ complete, exact precedence ladder | | Corpus gate (`cargo test`) | ✅ **345/345** official files parse clean **and** emit JSON | | Compact JSON (KerML 10.4) | ✅ flat element array, memberships, relationships, expressions | -| Multi-file models + standard-library resolution | ✅ `model::Model`; 99.93% of corpus references resolve | +| Multi-file models + standard-library resolution | ✅ `model::Model`; 99.92% of corpus references resolve | | Normative library element IDs (KerML 9.1) | ✅ verified against published OMG XMI | | Textual printer + formatter (`sysmlv2 fmt`) | ✅ idempotency/semantic/note gates over the corpus | | `sysmlv2` CLI with example-rich `--help` | ✅ convert / payload / fmt / check / lint / verify / eval / query / render / describe / members / parse / viz / refactor / lsp | | JSON reader (`lift`) + conversion matrix: text ⇄ compact JSON, full-JSON input normalized | ✅ corpus round-trip gate (`emit∘parse∘print∘lift = id`) | -| Full JSON form (derived props + implied relationships, `--to full-json`) | ✅ 44,656 corpus elements validate against the published schema | +| Full JSON form (derived props + implied relationships, `--to full-json`) | ✅ 52,048 corpus elements validate against the published schema | | Binary interchange (`--to compact-cbor` / `full-cbor`, `.s2c`) | ✅ deterministic, byte-for-byte reconstructable; elided ids; digest-verified deltas | | `.kpar` project archives | ✅ read and write (KerML 10.3) | -| Post-parse validation + referential checks (`sysmlv2 check [--lib]`) | ⚠️ body-context matrix, visibility/ambiguity-aware resolution, and a growing normative-rule registry; 14/180 pinned XMI `validate…` rules are explicitly mapped today | -| Semantic constraints (`check --lib`): multiplicity bounds, circular specialization | ✅ corpus-gated, zero findings | -| Configurable lint rules (`sysmlv2 lint`) | ✅ project-policy rules with auto-fixes, configured per project | -| Expression evaluation (`sysmlv2 eval`) | ✅ operators (rational Int division per KFL), sequences, feature refs, featuring contexts, KFL intrinsics + lambdas, quantities (`10 [mm]`), user-defined calc invocation (incl. `return x = expr;`), `new` constructors — 81.3% of corpus feature values compute | +| Post-parse validation + referential checks (`sysmlv2 check [--lib]`) | ⚠️ body-context matrix, visibility/ambiguity-aware resolution, and a growing normative-rule registry; 85/180 unique pinned XMI `validate…` names are registered across structural and semantic checks; this is an inventory, not a complete conformance claim | +| Semantic constraints (`check --lib`) | Usage-kind typing, multiplicity types/ranges, specialization cycles, redefinition compatibility, invocation binding, metadata/variation, connector ends and bindings, static action/state contracts, and conservative dimensional arithmetic; official-corpus gate pins two confirmed dimensional defects | +| Configurable lint rules (`sysmlv2 lint`) | ✅ project-policy rules with auto-fixes, configured per project; text or JSON report (`--format json`, shared with `check`) | +| Expression evaluation (`sysmlv2 eval`) | ✅ operators (rational Int division per KFL), sequences, feature refs, featuring contexts, KFL intrinsics + lambdas, quantities (`10 [mm]`), user-defined calc invocation (incl. `return x = expr;`), `new` constructors — 82.8% of corpus feature values compute | | Constraint verdicts (`sysmlv2 verify`) | ✅ satisfied / violated / undecided per constraint/requirement/invariant body | | Constraint solving (`sysmlv2 verify --solve`, Z3) | ✅ witnesses for unbound features, unsatisfiability/validity proofs — the `sysmlv2-solve` crate drives the `z3` binary as a subprocess (no libz3 link); interval propagation answers without a solver where it can | | Ad-hoc model queries (`sysmlv2 query`) | ✅ KerML expressions evaluated at the root namespace, plus query-only extensions: closed-world `istype` on model elements and the reflection functions `ownedMember(x)` / `ownedFeature(x)` — find parts by usage type in one line | @@ -134,7 +141,7 @@ Alongside the crates: | Python binding (`sysmlv2-py`, module `sysmlv2`) | ✅ the whole session surface from Python — abi3 wheels via maturin, generation-guarded handles (stale ones raise instead of mis-resolving) | | WebAssembly binding (`sysmlv2-wasm`) | ✅ the same session surface plus the language server for browsers and Node, standard library bundled with a sealed resolution snapshot | -All suites are green under `cargo test` and `clippy` is clean with `-D warnings`. +The latest implementation gate passed the full default-member release test suite and workspace/all-target Clippy with `-D warnings`. Corpus counts above use the pinned submodules; initialize them to run those gates. ## Architecture and design choices @@ -169,22 +176,27 @@ source text ──lexer──▶ tokens ──parser──▶ syntax AST ──b ## Validation - **Spec grounding.** The grammars implemented are the normative machine-readable Xtext files of the 2025 formal specifications (KerML 1.0, SysML 2.0, metamodel `20250201`), vendored in [spec-refs/](spec-refs/) together with provenance notes. The JSON mapping follows KerML clause 10.4; owned-vs-derived property decisions come from the published XMI; implied relationships follow KerML 8.4.2 / SysML Tables 31–33. -- **Corpus gate.** Every `cargo test` run parses all **345** official files — the complete OMG standard library (Systems, Domain, and Kernel libraries), all 42 training topics, all examples, and all validation suites — asserting zero diagnostics *and* successful compact-JSON emission for each (~119k elements corpus-wide). +- **Corpus gate.** Every `cargo test` run parses all **345** official files — the complete OMG standard library (Systems, Domain, and Kernel libraries), all 42 training topics, all examples, and all validation suites — asserting zero diagnostics *and* successful compact-JSON emission for each (139,656 compact elements when files are emitted independently; `examples/jsoncheck` run). +- **External rule fixtures.** [462 pinned OpenSysML fixtures](crates/sysmlv2-parser/tests/fixtures/opensysml/README.md) have per-stage baselines, with 147 paired rejection contracts and one adjudicated acceptance. An unrelated diagnostic does not establish intended-rule coverage. - **External corpus.** Airbus Central R&T's Apollo 11 mission model — the first substantial model independent of the OMG pilot lineage — is a pinned submodule with its own ratcheted gates (parse, checks, formatter, round-trip, evaluation, constraint verdicts, SMT solving). -- **Resolution coverage.** Emitting the 251 non-library corpus files against the vendored library yields 137,080 resolved `{"@id"}` references with 102 (0.07%) remaining symbolic `{"@ref"}`s (a heterogeneous long tail). Feature chains (`a.b.c`) serialize per the normative grammar — an owned `Feature` with one `FeatureChaining` per link — with each link resolved in the previous link's scope (owned + inherited-via-typing members). -- **Full-form schema validation.** `--to full-json` output — implied relationships (normative library targets, anti-redundancy) plus the complete per-metaclass property set generated from the published `SysML.json` — validates for **all 44,656 corpus elements** against the schema's exact-type definitions (`tests/full_json.rs`, `examples/fullcheck`). The representation rules, including the approximations at the API's passthrough level (expression `result`, `inheritedMembership`), are documented in [INTEROP.md](INTEROP.md). +- **Resolution coverage.** The `examples/modelcheck` run over 251 non-library corpus files yields 48,251 compact elements, 112,245 resolved `{"@id"}` references and 90 symbolic `{"@ref"}`s (99.92% resolved). `examples/modelcheck` counts 160,496 `@id` occurrences; subtract the 48,251 element declarations to count references only. Feature chains (`a.b.c`) serialize per the normative grammar — an owned `Feature` with one `FeatureChaining` per link — with each link resolved in the previous link's scope (owned + inherited-via-typing members). +- **Full-form schema validation.** `--to full-json` output — implied relationships (normative library targets, anti-redundancy) plus the complete per-metaclass property set generated from the published `SysML.json` — validates for **all 52,048 corpus elements** against the schema's exact-type definitions (`tests/full_json.rs`, `examples/fullcheck`). The representation rules, including the approximations at the API's passthrough level (expression `result`, `inheritedMembership`), are documented in [INTEROP.md](INTEROP.md). - **Normative-ID test vectors.** Library IDs are verified in [tests/model.rs](crates/sysmlv2-parser/tests/model.rs) against elementIds extracted from the published OMG XMI serializations: `ScalarValues` → `40bb440c-5036-58e1-8675-5afccb8b8f1d`, `ScalarValues::Real` → `14c0aa22-5489-59b5-b438-ded26e83ba31`, `Parts::Part` → `0774a545-39e3-5bc1-9607-63beabc6bf65`. The algorithm (UUIDv5/SHA-1, the RFC 4122 `NameSpace_URL` namespace, escaped qualified names) was confirmed against both the spec text and the pilot implementation's Java source. - **Round-trip gates.** Text → JSON → text, JSON → CBOR → JSON, and transformation inverses (rename and back, extract then inline) are gated over the corpus so every representation stays faithful to every other. ### Known limitations - The compact form deliberately does not satisfy the published JSON schemas' `required` lists — those describe the *full* (derived) form, which `--to full-json` produces. -- Body contexts parse as a superset; `sysmlv2 check` closes the gap post-parse (body-context legality, duplicate names, variant ownership, import visibility). A few fidelity long-tails remain (metadata-body redefinition semantics, effect-only transition shorthands, positional rules like result-expression-last). +- Body contexts parse as a superset; `sysmlv2 check` closes the gap post-parse (body-context legality, duplicate names, variant ownership, import visibility). Remaining syntax fidelity limits include effect-only transition shorthands and result-expression-last positioning. Metadata-body implicit redefinitions and their static value checks are implemented. - Unnamed library elements keep deterministic local IDs instead of the normative positional `path()` IDs (never referenced from user text). +- The [generated Web library](local-packages/README.md) has nine invalid attribute typings when checked as user input; its generator mappings need correction. Library-mode loading suppresses those library diagnostics. +- Behavioral execution is not implemented. Calculations that require statement execution return an explicit unsupported error; unbound inputs may yield an indeterminate value. Static action/state checks do not execute behaviors. - Only the decidable fragment of constraint expressions reaches the SMT translator; the rest stay `undecided` with a stated reason. ## Development +Rust 1.97 or newer is required. Development and CI use the toolchain pinned in `rust-toolchain.toml`. + ```sh git submodule update --init --filter=blob:none # the corpus (sparse checkout is enough; see spec-refs/README.md) cargo test # all suites incl. the 345-file corpus gate diff --git a/SDK.md b/SDK.md index d4a3e60..2b52ec8 100644 --- a/SDK.md +++ b/SDK.md @@ -34,6 +34,53 @@ The running example is a small two-package model: --- +## Exceptions + +Everything this module raises derives from `sysmlv2.Error`, so `except sysmlv2.Error` separates the toolkit's failures from the interpreter's own. A refusal — an argument the toolkit cannot use, a handle minted against a superseded session state, an edit whose commit would change what an untouched reference denotes — is `sysmlv2.RefusedError`, which derives from `sysmlv2.Error` and from `ValueError`, so `except ValueError` keeps catching every refusal it caught before. Anything else the toolkit could not carry out, such as an unreadable library directory, is a plain `sysmlv2.Error`. + +Model problems are not exceptions at all: `check` reports them as findings, and a broken parse is a finding rather than a raise. + +## Deeply nested sources + +Every call parses on the thread that makes it. The parser bounds how deeply a source may nest — 128 levels of braces — and that bound assumes a stack large enough to descend that far; a thread that has less overflows on input the parser accepts, and a stack overflow ends the interpreter rather than raising anything catchable. The toolkit's own command line and language server reserve that stack for themselves, but a thread the interpreter made is the caller's to size. + +Sources from an editor never come close (the published example and library models nest ten levels). Machine-generated ones can. To be safe with those, ask for the stack before the thread that will parse, and hand back what the work returned — or raised, since an exception on a thread is otherwise printed there and lost: + +```pycon +>>> import threading +>>> def on_a_parsing_stack(work): +... threading.stack_size(16 * 1024 * 1024) # what the parser's bound assumes +... outcome = [] +... def run(): +... try: +... outcome.append((work(), None)) +... except BaseException as raised: +... outcome.append((None, raised)) +... thread = threading.Thread(target=run) +... thread.start() +... thread.join() +... value, raised = outcome[0] +... if raised is not None: +... raise raised +... return value +... +>>> on_a_parsing_stack(lambda: 1 / 0) +Traceback (most recent call last): + ... +ZeroDivisionError: division by zero +``` + +A session lives on the thread that opened it, and so does every handle into it, so the work that *uses* the deep sources runs on that thread too — what comes back is its answer, not the session: + +```pycon +>>> def unresolved_in(sources): +... session = sysmlv2.Session.from_sources(sources) +... return session.unresolved_count() +... +>>> on_a_parsing_stack(lambda: unresolved_in([("deep.sysml", MODEL)])) +0 +``` + ## 1. Sessions A `Session` owns the parsed, resolved model and every handle into it. Open one from files on disk, from in-memory sources, or from interchange JSON (section 6): @@ -44,7 +91,7 @@ A `Session` owns the parsed, resolved model and every handle into it. Open one f 0 ``` -`from_files([...])` does the same for paths (dialect by extension, `.kerml` → KerML). To resolve names from the OMG standard library, call `load_library(dir)` with a checkout of its `sysml.library/` directory — resolution outcomes come from the same warm cache the CLI uses, and quantity values (`10 [mm]`) then evaluate to `(magnitude, unit)` tuples. +`from_files([...])` does the same for paths (dialect by extension, `.kerml` → KerML). To resolve names from the OMG standard library, call `load_library(dir)` with a checkout of its `sysml.library/` directory — native directory loading shares the CLI’s prepared graph and static-analysis cache, with library source trees reconstructed on demand, and quantity values (`10 [mm]`) then evaluate to `(magnitude, unit)` tuples. `units()` lists the model's units as `(index, name, source)`; `source(i)` returns one unit's current text: @@ -86,7 +133,7 @@ False False ``` -`element_id(e)` returns the element's interchange id — the same UUID the JSON emitters use. +`element_id(e)` returns the element's interchange id — the same UUID the JSON emitters use. Every derived property of the abstract syntax is reachable by its specification name through `s.derived(e, "ownedFeature")`, `s.derived(e, "owningNamespace")`, `s.derived(e, "name")`, …; `Session.derives(metaclass, name)` says in advance whether a name is computed (`"exact"`, `"passthrough"`, `"not-computed"`) or not a derived property there (`"not-declared"`), and `s.set_closure_policy("closure")` switches the inheritance-aware properties to their definition over the inherited and imported memberships (API.md §3.2a). ## 3. Find usages @@ -104,7 +151,7 @@ type (226, 231) ## 4. Queries and evaluation -`query(expr)` evaluates a KerML expression at the root namespace with the CLI's query-mode semantics — closed-world `istype` on model elements plus the reflection functions `ownedMember(x)` / `ownedFeature(x)`. Elements come back as handles, scalars as native Python values: +`query(expr)` evaluates a KerML expression at the root namespace with the CLI's query-mode semantics — closed-world `istype` on model elements plus the reflection functions `ownedMember(x)` / `ownedFeature(x)`. Elements come back as handles, scalars as native Python values — integers as `int` (arbitrary size), exact non-integral rationals as `fractions.Fraction`, approximate results of transcendental functions as `float`: (Exact numbers arrived with toolkit 0.7; before that every non-integer was a `float`.) ```pycon >>> hits = s.query("ownedFeature(Rig::Vehicle)->select { in p; p istype Defs::Wheel }") @@ -121,7 +168,7 @@ type (226, 231) 660 ``` -Malformed expressions raise `ValueError` with the parser's diagnostics. +Malformed expressions raise `sysmlv2.RefusedError` with the parser's diagnostics. ## 5. Batch edits with verified commits @@ -165,7 +212,7 @@ The report's `id_map` lists `(old id, new id)` for every element whose interchan 2 ``` -Renames only respell sites written with the element's own name — alias and effective-name spellings stay untouched. New text is validated at plan time: unparsable member text, renames to reserved words, and overlapping splices raise `ValueError` before anything is applied. +Renames only respell sites written with the element's own name — alias and effective-name spellings stay untouched. New text is validated at plan time: unparsable member text, renames to reserved words, and overlapping splices raise `sysmlv2.RefusedError` before anything is applied. A successful commit is a new model state: handles minted before it — including the consumed batch itself — are **stale** and raise rather than silently denoting the wrong element: @@ -173,11 +220,11 @@ A successful commit is a new model state: handles minted before it — including >>> s.name(wheel) Traceback (most recent call last): ... -ValueError: stale handle: the session was edited since it was minted (re-resolve after commit) +sysmlv2.RefusedError: stale handle: the session was edited since it was minted (re-resolve after commit) >>> s.commit(edit) Traceback (most recent call last): ... -ValueError: stale handle: the session was edited since it was minted (re-resolve after commit) +sysmlv2.RefusedError: stale handle: the session was edited since it was minted (re-resolve after commit) ``` `remove(e)` deletes a member's whole extent, but the commit pre-fails (nothing applied) if other sites still reference the removed element: @@ -189,10 +236,10 @@ ValueError: stale handle: the session was edited since it was minted (re-resolve >>> s.commit(bad) Traceback (most recent call last): ... -RuntimeError: removing `Defs::RoadWheel` breaks 4 reference(s) +sysmlv2.RefusedError: removing `Defs::RoadWheel` breaks 4 reference(s) ``` -And commit-time semantic breakage — here a rename that would let an inner declaration shadow-capture an outer reference — rolls back bit-exact and raises `RuntimeError`: +And commit-time semantic breakage — here a rename that would let an inner declaration shadow-capture an outer reference — rolls back bit-exact and raises `sysmlv2.RefusedError`: ```pycon >>> t = sysmlv2.Session.from_sources( @@ -202,7 +249,7 @@ And commit-time semantic breakage — here a rename that would let an inner decl >>> t.commit(shadow) Traceback (most recent call last): ... -RuntimeError: edit refused: 1 reference would break: `T` at u.sysml:1:58 (bytes 57..58) would resolve to `P::Q::T` instead of `P::T` +sysmlv2.RefusedError: edit refused: 1 reference would break: `T` at u.sysml:1:58 (bytes 57..58) would resolve to `P::Q::T` instead of `P::T` >>> t.resolve("P::Q::U") is not None True ``` @@ -259,7 +306,7 @@ package Rig { ``` -Refusals are named `ValueError`s — an ineligible kind or header, a taken definition name, outside references through the definition — and the session is left untouched. +Refusals are named `sysmlv2.RefusedError`s — an ineligible kind or header, a taken definition name, outside references through the definition — and the session is left untouched. ## 6. Interchange JSON sessions @@ -342,14 +389,16 @@ True Id-elided payloads (`Session::to_compact_cbor_elided` in Rust, CLI `--elide-ids`) and digest-named delta payloads (`delta_cbor_from`, CLI `--delta-base`) are covered in `CBOR.md`. +**Explicit ids.** A loaded document keeps the ids it carried: the session pairs the document's elements with the rebuilt model's by ownership path (roots in document order, then relationship and element positions, trusted only between elements of the same metaclass) and overlays every id the derivation would have replaced — foreign producers' ids, or a toolkit payload loaded under different unit names — on the resolved model and on every emission. Elements that could not be paired keep derived ids and are counted in `warnings()`. Such a session's compact CBOR carries the `explicitIds` header flag, and the Rust `to_compact_cbor_elided` / `delta_cbor_elided_from` return `Err(SessionError::ExplicitIds)`: every given id would ride the exception map anyway, and the elided form cannot carry the flag (the Python binding does not expose the elided forms or `has_explicit_ids()`; the JS binding's `toCompactCborElided` reports the refusal as an error). References to elements the text cannot name — unnamed targets, or library elements when no library is loaded — bind by id on load instead of degrading to a spelling. After an edit, an element keeps its given id only while it still derives the key it was loaded under with the same metaclass; a renamed, moved or deleted element's entry retires, and elements created after the load derive from their parents' *given* ids, so under the flag no id in a payload is guaranteed graph-derivable. + ## 8. Checking models -`sysmlv2.check(sources, lib=None)` runs the `sysmlv2 check` pipeline as a library call: per-unit parse and body-context validation always, plus referential and semantic checks against the standard library when `lib` is given (loaded through the same sealed-snapshot cache as sessions). It returns `Finding`s — severity, message, unit name, and a 1-based line/column — and never raises for model problems, so a broken parse is data, not an exception: +`sysmlv2.check(sources, lib=None)` exposes the checking stages as a library call: per-unit parse and body-context validation always, plus referential and semantic checks against the standard library when `lib` is given (loaded through the same native prepared-library cache as sessions). Unlike CLI `check`, this API currently runs model-level checks only when `lib` is supplied and does not include unused-private-import analysis. It returns `Finding`s — severity, stage (`parse`, `context`, `referential` or `semantic`; only `parse` findings keep a unit out of a session), message, unit name, and a 1-based line/column — and never raises for model problems, so a broken parse is data, not an exception: ```pycon >>> bad = sysmlv2.check([("bad.sysml", "package Bad {\n part p : ;\n}")]) ->>> (bad[0].severity, bad[0].unit, bad[0].line, bad[0].col) -('error', 'bad.sysml', 2, 12) +>>> (bad[0].severity, bad[0].stage, bad[0].unit, bad[0].line, bad[0].col) +('error', 'parse', 'bad.sysml', 2, 12) >>> sysmlv2.check([("ok.sysml", "package Ok { part def A; part a : A; }")]) [] ``` @@ -440,17 +489,14 @@ n1 ->> n2 : ping usecase "Drive" as n1 <> actor "driver : Driver" as n2 n2 -- n1 -note as o1 -«objective» -arrive -end note +note "«objective»\narrive " as o1 o1 .. n1 @enduml ``` Every view takes the same keyword options: comment/doc bodies attach as notes (`show_notes=False` omits), prefix metadata joins the stereotype list (`show_metadata=False` hides metadata), `show_inherited=True` adds `^`-marked inherited compartment lines, `show_lib=True` gives referenced library types marked nodes, `show_imported=True` draws `«import»` edges, `line_style="polyline"|"ortho"` picks edge routing, `std_color=True` colors nodes by metaclass family, and `link_template="vscode://file/{file}:{line}"` embeds `[[hyperlinks]]` (placeholders `{file}`/`{line}`/`{col}`/`{qname}`/`{id}`) that PlantUML carries into rendered SVG — diagram nodes click through to source. -`element="V::A"` roots the diagram at one element (unknown names raise `ValueError`, as do an unknown `view` or `line_style`); sessions lifted from interchange JSON diagram the same way — fetch a Flexo element list, `from_interchange_json`, `to_plantuml`. +`element="V::A"` roots the diagram at one element (unknown names raise `sysmlv2.RefusedError`, as do an unknown `view` or `line_style`); sessions lifted from interchange JSON diagram the same way — fetch a Flexo element list, `from_interchange_json`, `to_plantuml`. --- diff --git a/crates/sysmlv2-cbor/Cargo.toml b/crates/sysmlv2-cbor/Cargo.toml index 3b72f79..934c97c 100644 --- a/crates/sysmlv2-cbor/Cargo.toml +++ b/crates/sysmlv2-cbor/Cargo.toml @@ -12,7 +12,7 @@ repository.workspace = true include = ["src/**", "Cargo.toml", "README.md"] [dependencies] -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } serde_json.workspace = true uuid.workspace = true diff --git a/crates/sysmlv2-cbor/README.md b/crates/sysmlv2-cbor/README.md index 08bbf34..75f71a2 100644 --- a/crates/sysmlv2-cbor/README.md +++ b/crates/sysmlv2-cbor/README.md @@ -24,7 +24,7 @@ assert_eq!(from_compact_cbor(&bytes)?, compact_value); ## Measured (real corpora) -Against minified compact JSON: **~9–10×** raw and **~1.9×** after both sides deflate; with `--elide-ids` **~15–19×** raw and **~5×** after deflate (the interned UUID table is the only incompressible part, and elision removes it). Full form lands ~11×. An edit-sized delta commit is a few hundred bytes against megabyte snapshots. Decoding is faster than JSON parsing. Numbers, methodology, and the wire specification: [`CBOR.md`](../../CBOR.md) (reproduce with `cargo run --release -p sysmlv2-cbor --example corpus_bench`). +Against minified compact JSON: **9.9–10.5×** raw and **~2.1×** after both sides deflate; with `--elide-ids` **17.5–18.9×** raw and **7.0–7.8×** after deflate (the interned UUID table is the only incompressible part, and elision removes it). Full form lands ~11×. An edit-sized delta commit is a few hundred bytes against megabyte snapshots. In the corpus benchmark, decoding takes about 1.3× JSON parsing time; the size advantage does not imply a faster decoder. Numbers, methodology, and the wire specification: [`CBOR.md`](../../CBOR.md) (reproduce with `cargo run --release -p sysmlv2-cbor --example corpus_bench`). ## Layered use diff --git a/crates/sysmlv2-cbor/examples/corpus_bench.rs b/crates/sysmlv2-cbor/examples/corpus_bench.rs index 2444611..9297f28 100644 --- a/crates/sysmlv2-cbor/examples/corpus_bench.rs +++ b/crates/sysmlv2-cbor/examples/corpus_bench.rs @@ -177,10 +177,7 @@ fn bench(c: &Corpus) { let portable = sysmlv2_cbor::delta_compact_cbor( &value, &target, - &sysmlv2_cbor::DeltaOptions { - portable: true, - ..Default::default() - }, + &sysmlv2_cbor::DeltaOptions::new().with_portable(true), ) .unwrap(); let snapshot = to_compact_cbor(&target).unwrap(); diff --git a/crates/sysmlv2-cbor/src/canonical.rs b/crates/sysmlv2-cbor/src/canonical.rs index daae078..2d4a865 100644 --- a/crates/sysmlv2-cbor/src/canonical.rs +++ b/crates/sysmlv2-cbor/src/canonical.rs @@ -20,11 +20,8 @@ use std::collections::HashMap; use serde_json::{Map, Value}; -use crate::encode::{ctx, default_value}; -use crate::tables::{ - CborField, ENUM_TABLES, FULL_METACLASS_FIELDS, K_BOOL, K_ELEMENT_ID, K_ENUM, K_REF_LIST, - K_STR_LIST, METACLASS_FIELDS, -}; +use crate::encode::{ctx, default_value, is_default_value}; +use crate::tables::{CborField, FULL_METACLASS_FIELDS, K_ELEMENT_ID, K_LITERAL, METACLASS_FIELDS}; use crate::{Error, ordinal}; /// Canonicalize a compact interchange document (the flat element array @@ -241,23 +238,16 @@ fn normalize_element(e: &Value) -> Result { } /// Is `value` the metaclass default the graph-normal spelling elides? +/// The metaclass defaults themselves are the encoder's rule; this +/// spelling parts from it exactly twice, and says so. fn is_wire_default(field: &CborField, value: &Value) -> bool { - let (_, kind, etbl, dflt) = *field; - match kind { - K_BOOL => value.as_bool() == Some(dflt == 1), - K_ENUM => match dflt { - 255 => value.is_null(), - d => { - value.as_str().is_some() - && value.as_str() - == ENUM_TABLES - .get(etbl as usize) - .and_then(|t| t.get(d as usize)) - .copied() - } - }, - K_REF_LIST | K_STR_LIST => value.as_array().is_some_and(Vec::is_empty), + match field.1 { + // A store derives `elementId` from the element identity, so + // the stored form always carries it. K_ELEMENT_ID => false, - _ => value.is_null(), + // A literal-valued field has no metaclass default, but the + // stored form still elides a null one. + K_LITERAL => value.is_null(), + _ => is_default_value(field, "", value), } } diff --git a/crates/sysmlv2-cbor/src/cbor.rs b/crates/sysmlv2-cbor/src/cbor.rs index ed66efc..6dea4d4 100644 --- a/crates/sysmlv2-cbor/src/cbor.rs +++ b/crates/sysmlv2-cbor/src/cbor.rs @@ -4,7 +4,7 @@ //! exists so the codec carries no external dependency and stays //! wasm-clean by construction. -use crate::Error; +use crate::{Error, ErrorKind}; const MAJOR_UINT: u8 = 0; const MAJOR_NINT: u8 = 1; @@ -24,9 +24,15 @@ impl Writer { /// A writer opened with the RFC 9277 payload magic already /// emitted: tag 55799 wrapping application tag `0x24533243` /// ("$S2C"); the body written next is the tags' content, so the - /// whole payload stays one valid CBOR item. - pub fn with_magic() -> Self { - let mut w = Self::default(); + /// whole payload stays one valid CBOR item. Room for roughly + /// `elements` element records is reserved up front — an id-table + /// entry is 17 bytes and a record's frame about as much again — so + /// a whole model never starts from nothing and walks the doubling + /// sequence. + pub fn with_magic_for(elements: usize) -> Self { + let mut w = Self { + buf: Vec::with_capacity(crate::MAGIC.len() + elements.saturating_mul(48)), + }; w.buf.extend_from_slice(crate::MAGIC); w } @@ -41,6 +47,9 @@ impl Writer { self.buf.extend_from_slice(bytes); } + // Each arm narrows `arg` to the width its own range bound already + // proves exact — that is what picking the shortest head means. + #[allow(clippy::cast_possible_truncation)] fn head(&mut self, major: u8, arg: u64) { let m = major << 5; match arg { @@ -150,7 +159,7 @@ impl<'a> Reader<'a> { let b = *self .buf .get(self.pos) - .ok_or_else(|| Error::new("truncated payload"))?; + .ok_or_else(|| Error::of(ErrorKind::Truncated, "truncated payload"))?; self.pos += 1; Ok(b) } @@ -160,7 +169,7 @@ impl<'a> Reader<'a> { .pos .checked_add(n) .filter(|&e| e <= self.buf.len()) - .ok_or_else(|| Error::new("truncated payload"))?; + .ok_or_else(|| Error::of(ErrorKind::Truncated, "truncated payload"))?; let s = &self.buf[self.pos..end]; self.pos = end; Ok(s) @@ -181,6 +190,20 @@ impl<'a> Reader<'a> { usize::try_from(arg).map_err(|_| Error::new("length overflow")) } + /// Narrow an already-read wire integer to an in-memory index or + /// position. Wire integers are 64-bit and `usize` is 32 bits on + /// the wasm targets, so a value that cannot address memory here is + /// a malformed payload rather than a silently wrapped index. + pub fn index_of(arg: u64) -> Result { + usize::try_from(arg).map_err(|_| Error::new(format!("wire index {arg} out of range"))) + } + + /// Read an unsigned wire integer as an index or position + /// ([`Self::index_of`]). + pub fn index(&mut self) -> Result { + Self::index_of(self.uint()?) + } + pub fn head(&mut self) -> Result { let b = self.byte()?; let (major, ai) = (b >> 5, b & 0x1F); @@ -234,6 +257,39 @@ impl<'a> Reader<'a> { /// [`crate::describe`]. Iterative (a pending counter, not /// recursion), and every step consumes at least one byte, so /// adversarial nesting terminates at the truncation error. + /// Read a map keyed by strictly ascending in-memory indices — the + /// shape every exception, owner and units section shares. The + /// header is gated against the payload before anything is + /// allocated (`per_entry` is the fewest bytes one entry can + /// occupy), each key is narrowed and checked against its + /// predecessor, and `value` reads the value with the reader + /// positioned on it. `what` names the section in the three errors + /// this can raise. + pub fn ascending_map( + &mut self, + what: &str, + per_entry: usize, + mut value: impl FnMut(&mut Self) -> Result, + ) -> Result, Error> { + let n = match self.head()? { + Head::Map(n) if n <= self.remaining() / per_entry => n, + Head::Map(_) => return Err(Error::new(format!("{what} longer than payload"))), + _ => return Err(Error::new(format!("{what} expected"))), + }; + let mut out = Vec::with_capacity(n); + let mut prev: Option = None; + for _ in 0..n { + let key = self.index()?; + if prev.is_some_and(|p| key <= p) { + return Err(Error::new(format!("{what} indices not ascending"))); + } + prev = Some(key); + let v = value(self)?; + out.push((key, v)); + } + Ok(out) + } + pub fn skip_items(&mut self, count: u64) -> Result<(), Error> { let mut pending = count; while pending > 0 { diff --git a/crates/sysmlv2-cbor/src/decode.rs b/crates/sysmlv2-cbor/src/decode.rs index 4b284e5..1451c27 100644 --- a/crates/sysmlv2-cbor/src/decode.rs +++ b/crates/sysmlv2-cbor/src/decode.rs @@ -4,7 +4,6 @@ //! ordinal keys re-expand to property names, reference indices //! re-expand to `{"@id": …}` objects, `@ref` text survives verbatim. -use crate::Error; use crate::cbor::{Head, Reader}; use crate::encode::{ FLAG_ELIDE_IDS, FLAG_FULL_FORM, FLAG_IMPLIED_OWNERS, FLAG_UNIT_PATHS, OWNER_SLOTS, @@ -13,6 +12,7 @@ use crate::encode::{ use crate::tables::{ CBOR_TABLES_VERSION, CborField, ENUM_TABLES, K_ENUM, K_LITERAL, K_REF, K_REF_LIST, K_STR_LIST, }; +use crate::{Error, ErrorKind}; use serde_json::{Map, Number, Value, json}; use uuid::Uuid; @@ -36,7 +36,7 @@ impl Presence<'_> { Presence::Small(bits) => n_fields >= 64 || bits >> n_fields == 0, Presence::Big(bytes) => { bytes.len() == n_fields.div_ceil(8) - && (n_fields % 8 == 0 || bytes[n_fields / 8] >> (n_fields % 8) == 0) + && (n_fields.is_multiple_of(8) || bytes[n_fields / 8] >> (n_fields % 8) == 0) } }; if ok { @@ -47,7 +47,7 @@ impl Presence<'_> { } } -pub(crate) fn read_uuid_table(r: &mut Reader, n: usize) -> Result, Error> { +pub(crate) fn read_uuids(r: &mut Reader, n: usize) -> Result, Error> { // Each entry takes a 1-byte head + 16 UUID bytes. if n > r.remaining() / 17 { return Err(Error::new("UUID table longer than payload")); @@ -55,24 +55,37 @@ pub(crate) fn read_uuid_table(r: &mut Reader, n: usize) -> Result, E let mut out = Vec::with_capacity(n); for _ in 0..n { let b: [u8; 16] = r.bstr(16)?.try_into().unwrap(); - out.push(Uuid::from_bytes(b).to_string()); + out.push(Uuid::from_bytes(b)); } Ok(out) } +/// [`read_uuids`] spelled the way the reference tables want it. +pub(crate) fn read_uuid_table(r: &mut Reader, n: usize) -> Result, Error> { + Ok(read_uuids(r, n)?.iter().map(Uuid::to_string).collect()) +} + +/// The reference index space, in wire order: the payload's own ids, +/// then (delta forms) the created ids, then the externals. The three +/// stay separate tables so a delta never has to concatenate a copy of +/// the base's id table to read one reference. pub(crate) struct Tables<'a> { pub(crate) ids: &'a [String], + pub(crate) created: &'a [String], pub(crate) exts: &'a [String], } impl Tables<'_> { pub(crate) fn reference(&self, index: u64) -> Result { - let i = index as usize; + let out_of_range = || Error::new(format!("reference index {index} out of range")); + let i = usize::try_from(index).map_err(|_| out_of_range())?; + let locals = self.ids.len() + self.created.len(); let id = self .ids .get(i) - .or_else(|| self.exts.get(i.wrapping_sub(self.ids.len()))) - .ok_or_else(|| Error::new(format!("reference index {index} out of range")))?; + .or_else(|| self.created.get(i.wrapping_sub(self.ids.len()))) + .or_else(|| self.exts.get(i.wrapping_sub(locals))) + .ok_or_else(out_of_range)?; Ok(json!({ "@id": id })) } } @@ -120,8 +133,9 @@ pub(crate) fn read_value(r: &mut Reader, t: &Tables, field: &CborField) -> Resul } (K_ENUM, Head::Uint(i)) => { let table = ENUM_TABLES[etbl as usize]; - let s = *table - .get(i as usize) + let s = *usize::try_from(i) + .ok() + .and_then(|i| table.get(i)) .ok_or_else(|| Error::new(format!("{prop}: enum index {i} out of range")))?; Value::String(s.to_owned()) } @@ -169,8 +183,9 @@ pub(crate) fn read_element_body( id: &str, ) -> Result { let code = r.uint()?; - let (ty, fields) = tables - .get(code as usize) + let (ty, fields) = usize::try_from(code) + .ok() + .and_then(|c| tables.get(c)) .ok_or_else(|| Error::new(format!("type code {code} out of range")))?; let presence = match r.head()? { Head::Uint(bits) => Presence::Small(bits), @@ -185,17 +200,19 @@ pub(crate) fn read_element_body( Head::Map(n) => n, _ => return Err(Error::new("element fields are a map")), }; - let mut prev: i32 = -1; + let mut prev: Option = None; for _ in 0..entries { let ord = r.uint()?; - if ord as i32 <= prev { + if prev.is_some_and(|p| ord <= p) { return Err(Error::new(format!("{ty}: field ordinals not ascending"))); } - prev = ord as i32; - let field = fields - .get(ord as usize) + prev = Some(ord); + let at = usize::try_from(ord) + .ok() + .filter(|&at| at < fields.len()) .ok_or_else(|| Error::new(format!("{ty}: field ordinal {ord} out of range")))?; - if presence.get(ord as usize) { + let field = &fields[at]; + if presence.get(at) { return Err(Error::new(format!( "{ty}.{}: both presence bit and value", field.0 @@ -256,24 +273,60 @@ type Resolver<'a> = &'a dyn Fn(&str) -> Option; /// decode reads element records through the generated tables; the /// scheme axis is returned `(scheme, flags)` for the caller to gate /// only where id derivation is actually in play. -pub(crate) fn parse_header(header: u64) -> Result<(u8, u8), Error> { +/// The header word's four axes, unpacked: `layout u8 · tables u16 · +/// scheme u8 · flags u8`. Unpacking only — which axes gate is the +/// caller's call (payload inspection reports them all and gates only +/// the layout). +// Each cast takes one whole field of the word, whose width the range +// check pins — the narrowing is the unpacking. +#[allow(clippy::cast_possible_truncation)] +pub(crate) fn header_axes(header: u64) -> Result<(u8, u16, u8, u8), Error> { if header >> 40 != 0 { return Err(Error::new("unrecognized header word")); } - let layout = (header >> 32) as u8; - let tables = (header >> 16) as u16; - let scheme = (header >> 8) as u8; - let flags = header as u8; + Ok(( + (header >> 32) as u8, + (header >> 16) as u16, + (header >> 8) as u8, + header as u8, + )) +} + +/// Refuse a flag this reader does not implement: the payload comes +/// from a newer writer and must not be read as though it did not set +/// one. +pub(crate) fn gate_flags(flags: u8, known: u8) -> Result<(), Error> { + if flags & !known != 0 { + return Err(Error::new(format!("unknown header flags {flags:#x}"))); + } + Ok(()) +} + +/// The units section: element index in the payload's own order → that +/// unit's source path, ascending. +pub(crate) fn read_units(r: &mut Reader) -> Result, Error> { + r.ascending_map("unit-path map", 2, |r| match r.head()? { + Head::Tstr(n) => Ok(r.tstr_body(n)?.to_owned()), + _ => Err(Error::new("unit path is a text string")), + }) +} + +pub(crate) fn parse_header(header: u64) -> Result<(u8, u8), Error> { + let (layout, tables, scheme, flags) = header_axes(header)?; if layout != crate::LAYOUT_VERSION { - return Err(Error::new(format!( - "layout version {layout} unsupported (decoder carries {})", - crate::LAYOUT_VERSION - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "layout version {layout} unsupported (decoder carries {})", + crate::LAYOUT_VERSION + ), + )); } if tables != CBOR_TABLES_VERSION { - return Err(Error::new(format!( - "table version {tables} unsupported (decoder carries {CBOR_TABLES_VERSION})" - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!("table version {tables} unsupported (decoder carries {CBOR_TABLES_VERSION})"), + )); } Ok((scheme, flags)) } @@ -290,13 +343,19 @@ fn decode( let arity = r.array()?; let (scheme, flags) = parse_header(r.uint()?)?; if flags & crate::delta::FLAG_DELTA != 0 { - return Err(Error::new( + return Err(Error::of( + ErrorKind::WrongForm, "delta payload; apply with apply_delta_cbor against its base", )); } - if flags & !(FLAG_ELIDE_IDS | FLAG_FULL_FORM | FLAG_UNIT_PATHS | FLAG_IMPLIED_OWNERS) != 0 { - return Err(Error::new(format!("unknown header flags {flags:#x}"))); - } + gate_flags( + flags, + FLAG_ELIDE_IDS + | FLAG_FULL_FORM + | FLAG_UNIT_PATHS + | FLAG_IMPLIED_OWNERS + | crate::encode::FLAG_EXPLICIT_IDS, + )?; let with_units = flags & FLAG_UNIT_PATHS != 0; let implied = flags & FLAG_IMPLIED_OWNERS != 0; let expect_arity = 4 + usize::from(implied) + usize::from(with_units); @@ -313,20 +372,27 @@ fn decode( // The derivation-scheme axis gates only payloads that actually // derive ids; explicit-id payloads decode regardless of it. if elided && scheme != crate::ID_SCHEME_VERSION { - return Err(Error::new(format!( - "id-derivation scheme {scheme} unsupported (decoder carries {}); \ - the payload's ids cannot be recovered here", - crate::ID_SCHEME_VERSION - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "id-derivation scheme {scheme} unsupported (decoder carries {}); \ + the payload's ids cannot be recovered here", + crate::ID_SCHEME_VERSION + ), + )); } match expect_full { Some(false) if full => { - return Err(Error::new( + return Err(Error::of( + ErrorKind::WrongForm, "full-form payload; decode with from_full_cbor (compact is the ingest form)", )); } Some(true) if !full => { - return Err(Error::new("compact payload; decode with from_compact_cbor")); + return Err(Error::of( + ErrorKind::WrongForm, + "compact payload; decode with from_compact_cbor", + )); } _ => {} } @@ -335,7 +401,8 @@ fn decode( } let resolver = if elided { Some(resolver.ok_or_else(|| { - Error::new( + Error::of( + ErrorKind::NeedsResolver, "id-elided payload; decode with from_compact_cbor_elided (or from_cbor_with) \ and, for library-typed models, the library name resolver", ) @@ -348,30 +415,17 @@ fn decode( let exts = read_uuid_table(&mut r, n_ext)?; // Id section: the id table, or (elided) the exception map + digest. - let mut exceptions: Vec<(u64, Uuid)> = Vec::new(); + let mut exceptions: Vec<(usize, Uuid)> = Vec::new(); let mut digest: Option = None; let mut ids: Vec = Vec::new(); if elided { if r.array()? != 2 { return Err(Error::new("elided id section is array(2)")); } - let m = match r.head()? { - Head::Map(m) => m, - _ => return Err(Error::new("exception map expected")), - }; - if m > r.remaining() / 18 { - return Err(Error::new("exception map longer than payload")); - } - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()?; - if k as i64 <= prev { - return Err(Error::new("exception indices not ascending")); - } - prev = k as i64; + exceptions = r.ascending_map("exception map", 18, |r| { let b: [u8; 16] = r.bstr(16)?.try_into().unwrap(); - exceptions.push((k, Uuid::from_bytes(b))); - } + Ok(Uuid::from_bytes(b)) + })?; let d: [u8; 16] = r.bstr(16)?.try_into().unwrap(); digest = Some(Uuid::from_bytes(d)); } else { @@ -385,7 +439,7 @@ fn decode( return Err(Error::new("element count longer than payload")); } ids = (0..n).map(placeholder).collect(); - if exceptions.last().is_some_and(|&(k, _)| k as usize >= n) { + if exceptions.last().is_some_and(|&(k, _)| k >= n) { return Err(Error::new("exception index out of range")); } } else if ids.len() != n { @@ -393,6 +447,7 @@ fn decode( } let tables = Tables { ids: &ids, + created: &[], exts: &exts, }; let mut out = Vec::with_capacity(n); @@ -405,51 +460,24 @@ fn decode( let mut owner_exceptions: std::collections::HashMap = std::collections::HashMap::new(); if implied { - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("owner-exception map longer than payload")), - _ => return Err(Error::new("owner-exception map expected")), - }; - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()?; - if k as i64 <= prev { - return Err(Error::new("owner-exception indices not ascending")); - } - if k as usize >= n { - return Err(Error::new("owner-exception index out of range")); - } - prev = k as i64; - let bits = r.uint()?; - if bits == 0 || bits > 3 { - return Err(Error::new("owner-exception bits out of range")); - } - owner_exceptions.insert(k as usize, bits); + let entries = r.ascending_map("owner-exception map", 2, |r| match r.uint()? { + bits @ 1..=3 => Ok(bits), + _ => Err(Error::new("owner-exception bits out of range")), + })?; + if entries.last().is_some_and(|&(k, _)| k >= n) { + return Err(Error::new("owner-exception index out of range")); } + owner_exceptions = entries.into_iter().collect(); } // Unit structure: element index of each unit's root namespace → // that unit's source path. let mut units: Vec<(u64, String)> = Vec::new(); if with_units { - let m = match r.head()? { - Head::Map(m) => m, - _ => return Err(Error::new("unit-path map expected")), - }; - if m > r.remaining() / 2 { - return Err(Error::new("unit-path map longer than payload")); - } - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()?; - if k as i64 <= prev { - return Err(Error::new("unit root indices not ascending")); - } - if k as usize >= n { - return Err(Error::new("unit root index out of range")); - } - prev = k as i64; - units.push((k, read_string(&mut r)?)); + let entries = read_units(&mut r)?; + if entries.last().is_some_and(|&(k, _)| k >= n) { + return Err(Error::new("unit root index out of range")); } + units = entries.into_iter().map(|(k, p)| (k as u64, p)).collect(); } if !r.done() { return Err(Error::new("trailing bytes after payload")); @@ -495,10 +523,7 @@ fn decode( // means library skew (the effective-name chains resolved // against a different library), derivation drift across codec // versions, or exception-map corruption. Never continue. - let exceptions: std::collections::HashMap = exceptions - .into_iter() - .map(|(k, u)| (k as usize, u)) - .collect(); + let exceptions: std::collections::HashMap = exceptions.into_iter().collect(); let finals = sysmlv2_model::ids::assign_ids(&value, &exceptions, external_name) .map_err(Error::new)?; let expect = digest.unwrap(); diff --git a/crates/sysmlv2-cbor/src/delta.rs b/crates/sysmlv2-cbor/src/delta.rs index 7a2eb8e..97dabd1 100644 --- a/crates/sysmlv2-cbor/src/delta.rs +++ b/crates/sysmlv2-cbor/src/delta.rs @@ -37,10 +37,10 @@ //! replay owner changes as explicit ops and base copies are never //! touched), and the units section (flag 0x10). -use crate::Error; use crate::cbor::{Head, Reader, Writer}; -use crate::decode::{Tables, read_element_body, read_uuid_table}; +use crate::decode::{Tables, gate_flags, read_element_body, read_units, read_uuid_table}; use crate::encode::{Interner, elems_of, table_set, write_element}; +use crate::{Error, ErrorKind}; use serde_json::Value; use std::collections::{HashMap, HashSet}; use uuid::Uuid; @@ -57,14 +57,21 @@ pub(crate) const OP_SPLICE: u64 = 2; /// A spec-canonical version identifier carried as an opaque claim /// (e.g. key 0 = project id, 1 = commit id, 2 = a service URI). +/// +/// Non-exhaustive: the wire may learn further claim shapes. #[derive(Debug, Clone, PartialEq)] +#[non_exhaustive] pub enum Claim { Id(Uuid), Text(String), } -/// Delta encoding options. +/// Delta encoding options. Build one from [`DeltaOptions::new`] (or +/// [`Default`]) and the `with_*` setters; the fields stay readable and +/// assignable, but the struct is non-exhaustive, so later options +/// never break a caller that spelled its own literal. #[derive(Default)] +#[non_exhaustive] pub struct DeltaOptions { /// Id-keyed identities and external base references — larger, but /// applicable best-effort to a divergent base. @@ -84,6 +91,35 @@ pub struct DeltaOptions { pub units: Vec<(usize, String)>, } +impl DeltaOptions { + /// Strict identities, no claims, no units. + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// Set [`Self::portable`]. + #[must_use] + pub fn with_portable(mut self, portable: bool) -> Self { + self.portable = portable; + self + } + + /// Set [`Self::claims`]. + #[must_use] + pub fn with_claims(mut self, claims: Vec<(u64, Claim)>) -> Self { + self.claims = claims; + self + } + + /// Set [`Self::units`]. + #[must_use] + pub fn with_units(mut self, units: Vec<(usize, String)>) -> Self { + self.units = units; + self + } +} + fn delta_ns() -> Uuid { Uuid::new_v5(&Uuid::NAMESPACE_URL, b"sysmlv2-cbor:delta-base") } @@ -117,9 +153,49 @@ fn targets(index: &HashMap<&str, usize>, e: &Value, key: &str) -> Vec { /// root appended in payload order. Emission-order-independent — the /// footing for [`state_digest`] and every delta index space. pub fn delta_canonical(compact: &Value) -> Result { + Ok(Value::Array( + canonical_views(compact)?.into_iter().cloned().collect(), + )) +} + +/// The payload's elements in delta-canonical order, borrowed. Digests, +/// diffs and applies all walk these views, so canonicalizing a model +/// costs a vector of pointers rather than a copy of it. +pub(crate) fn canonical_views(compact: &Value) -> Result, Error> { let arr = compact .as_array() .ok_or_else(|| Error::new("compact payload is a flat element array"))?; + Ok(canonical_order(arr)?.into_iter().map(|i| &arr[i]).collect()) +} + +/// [`delta_canonical`] for a payload we already own: the elements move +/// into canonical order instead of being copied into it. +fn canonical_owned(applied: Value) -> Result { + let Value::Array(arr) = applied else { + return Err(Error::new("compact payload is a flat element array")); + }; + let order = canonical_order(&arr)?; + let mut slots: Vec> = arr.into_iter().map(Some).collect(); + Ok(Value::Array( + order + .into_iter() + .map(|i| { + slots[i] + .take() + .expect("the canonical order lists each element once") + }) + .collect(), + )) +} + +/// Borrowed views over an array that is already in canonical order. +fn views(arr: &[Value]) -> Vec<&Value> { + arr.iter().collect() +} + +/// The delta-canonical order as a permutation of the payload's own +/// positions — the shape [`delta_canonical`] materializes. +fn canonical_order(arr: &[Value]) -> Result, Error> { let n = arr.len(); let mut index: HashMap<&str, usize> = HashMap::with_capacity(n); for (i, e) in arr.iter().enumerate() { @@ -161,9 +237,7 @@ pub fn delta_canonical(compact: &Value) -> Result { order.push(i); } } - Ok(Value::Array( - order.into_iter().map(|i| arr[i].clone()).collect(), - )) + Ok(order) } /// Content digest of a model state: `uuid5` over the canonical compact @@ -171,10 +245,10 @@ pub fn delta_canonical(compact: &Value) -> Result { /// transport-independent; [`empty_base_digest`] is its fixed point for /// the empty model (the API's "first commit" base). pub fn state_digest(compact: &Value) -> Result { - digest_of_canonical(&delta_canonical(compact)?) + digest_of_canonical(&canonical_views(compact)?) } -fn digest_of_canonical(canon: &Value) -> Result { +fn digest_of_canonical(canon: &[&Value]) -> Result { // The digest space canonicalizes with owners spelled — pinned // independently of wire-format elision, so digests recorded // before the owner-elision flag existed stay valid forever. @@ -185,6 +259,10 @@ fn digest_of_canonical(canon: &Value) -> Result { } /// The recognizable digest of the empty base. +/// +/// # Panics +/// Never in practice: the empty element array always encodes. +#[must_use] pub fn empty_base_digest() -> Uuid { state_digest(&Value::Array(Vec::new())).expect("empty model encodes") } @@ -207,14 +285,18 @@ pub fn empty_base_digest() -> Uuid { /// /// Not for same-session diffs: session identity survives moves, which /// path matching cannot see — diff those payloads as they are. +/// +/// # Panics +/// If an element of either payload has no string `@id`. Id derivation +/// runs first and refuses such a payload, so a `Value` that reached +/// this point already carries them. pub fn rebase_ids(base: &Value, target: &Value) -> Result { - let flat = |v: &Value| -> Result, Error> { + fn array(v: &Value) -> Result<&Vec, Error> { v.as_array() - .cloned() .ok_or_else(|| Error::new("compact payload is a flat element array")) - }; - let base_arr = flat(base)?; - let mut out = flat(target)?; + } + let base_arr = array(base)?; + let mut out = array(target)?.clone(); let none = |_: &str| None; let base_paths = sysmlv2_model::ids::segment_paths(base, &none).map_err(Error::new)?; let target_paths = sysmlv2_model::ids::segment_paths(target, &none).map_err(Error::new)?; @@ -267,7 +349,7 @@ pub fn rebase_ids(base: &Value, target: &Value) -> Result { .collect() }; let (base_roots, target_roots) = (roots(&base_paths), roots(&target_paths)); - let base_keys = keyed(&base_arr, &base_roots); + let base_keys = keyed(base_arr, &base_roots); let target_keys = keyed(&out, &target_roots); let mut pair: HashMap = HashMap::new(); let mut base_used: HashSet = HashSet::new(); @@ -383,14 +465,14 @@ pub fn rebase_ids(base: &Value, target: &Value) -> Result { .into_iter() .filter(|c| !pair_elem.contains_key(c)) .collect(); - let unb: Vec = children(&base_arr, &base_index, b) + let unb: Vec = children(base_arr, &base_index, b) .into_iter() .filter(|c| !base_paired.contains(c)) .collect(); let (mut i, mut j) = (0usize, 0usize); while i < unt.len() && j < unb.len() { let (tc, bc) = (unt[i], unb[j]); - if align_key(&out, &target_index, tc) == align_key(&base_arr, &base_index, bc) { + if align_key(&out, &target_index, tc) == align_key(base_arr, &base_index, bc) { adopt(tc, bc, &out, &mut remap, &mut pair_elem, &mut base_paired); queue.push((tc, bc)); i += 1; @@ -528,7 +610,7 @@ fn plan_patch(base: &Value, target: &Value) -> Option> { (Some(_), None) => FieldOp::Unset, (None, None) => continue, }; - ops.push((ord as u8, op)); + ops.push((u8::try_from(ord).ok()?, op)); } // Self-check: replaying the ops over the base must reproduce the // target exactly — this guards keys outside the field table and @@ -641,15 +723,16 @@ fn read_patch(r: &mut Reader, t: &Tables, n: usize, base_elem: &Value) -> Result if n > r.remaining() / 2 { return Err(Error::new("patch longer than payload")); } - let mut prev: i32 = -1; + let mut prev: Option = None; for _ in 0..n { let ord = r.uint()?; - if ord as i32 <= prev { + if prev.is_some_and(|p| ord <= p) { return Err(Error::new(format!("{ty}: patch ordinals not ascending"))); } - prev = ord as i32; - let field = fields - .get(ord as usize) + prev = Some(ord); + let field = usize::try_from(ord) + .ok() + .and_then(|ord| fields.get(ord)) .ok_or_else(|| Error::new(format!("{ty}: field ordinal {ord} out of range")))?; if r.array()? != 2 { return Err(Error::new("patch op is array(2)")); @@ -669,8 +752,8 @@ fn read_patch(r: &mut Reader, t: &Tables, n: usize, base_elem: &Value) -> Result if r.array()? != 3 { return Err(Error::new("splice op is array(3)")); } - let at = r.uint()? as usize; - let del = r.uint()? as usize; + let at = r.index()?; + let del = r.index()?; let len = r.array()?; if len > r.remaining() { return Err(Error::new("splice items longer than payload")); @@ -712,12 +795,10 @@ fn delta_encode( opts: &DeltaOptions, elide: Option, ) -> Result, Error> { - let base_canon = delta_canonical(base)?; - let target_canon = delta_canonical(target)?; - let base_digest = digest_of_canonical(&base_canon)?; - let result_digest = digest_of_canonical(&target_canon)?; - let base_arr = base_canon.as_array().unwrap(); - let target_arr = target_canon.as_array().unwrap(); + let base_arr = canonical_views(base)?; + let target_arr = canonical_views(target)?; + let base_digest = digest_of_canonical(&base_arr)?; + let result_digest = digest_of_canonical(&target_arr)?; // Ownership backpointers on shipped element records elide // against derivation over the **canonical target** — the identical @@ -729,7 +810,7 @@ fn delta_encode( .enumerate() .map(|(i, e)| (e["@id"].as_str().expect("canonicalized"), i)) .collect(); - let target_owners = crate::encode::derive_owners(target_arr); + let target_owners = crate::encode::derive_owners(target_arr.iter().copied()); let derived_pair = |e: &Value| -> [Option<&str>; 2] { let ti = canon_pos[e["@id"].as_str().unwrap()]; target_owners[ti].map(|s| s.map(|j| target_arr[j]["@id"].as_str().unwrap())) @@ -777,7 +858,7 @@ fn delta_encode( let base_by_id: HashMap<&str, usize> = base_ids.iter().enumerate().map(|(i, &s)| (s, i)).collect(); let mut target_ids: HashSet<&str> = HashSet::with_capacity(target_arr.len()); - for e in target_arr { + for &e in &target_arr { if !target_ids.insert(e["@id"].as_str().expect("canonicalized")) { return Err(Error::new(format!("duplicate element @id `{}`", e["@id"]))); } @@ -785,9 +866,9 @@ fn delta_encode( // updates/deletes ascending by base position, creates in target order. let mut touched: Vec<(usize, Option<&Value>)> = Vec::new(); - for e in target_arr { + for &e in &target_arr { if let Some(&i) = base_by_id.get(e["@id"].as_str().unwrap()) { - if base_arr[i] != *e { + if base_arr[i] != e { touched.push((i, Some(e))); } } @@ -805,17 +886,17 @@ fn delta_encode( .iter() .enumerate() .filter(|(_, e)| !base_by_id.contains_key(e["@id"].as_str().unwrap())) + .map(|(i, &e)| (i, e)) .collect(); - // Element records for external collection + writing. - let payload_value = Value::Array( - touched - .iter() - .filter_map(|&(_, v)| v.cloned()) - .chain(creates.iter().map(|&(_, v)| v.clone())) - .collect(), - ); - let payload_elems = elems_of(&payload_value, table_set(false))?; + // Element records for external collection + writing — views, so + // the records are read where they already are. + let payload: Vec<&Value> = touched + .iter() + .filter_map(|&(_, v)| v) + .chain(creates.iter().map(|&(_, v)| v)) + .collect(); + let payload_elems = elems_of(&payload, table_set(false))?; let created_ids: Vec = creates .iter() .map(|(_, e)| parse_uuid(e["@id"].as_str().unwrap())) @@ -828,6 +909,7 @@ fn delta_encode( // the applier prove its recovered ids are exactly these. let elision: Option = match elide { Some(external_name) => { + let target_canon = Value::Array(target_arr.iter().copied().cloned().collect()); let derived = sysmlv2_model::ids::derive_ids(&target_canon, external_name).map_err(Error::new)?; let exceptions = creates @@ -897,7 +979,7 @@ fn delta_encode( let plan = if opts.portable { None } else { - plan_patch(&base_arr[i], target_elem) + plan_patch(base_arr[i], target_elem) }; let mut chose_whole = true; let bytes = match plan { @@ -930,7 +1012,7 @@ fn delta_encode( } } - let mut w = Writer::with_magic(); + let mut w = Writer::with_magic_for(payload_elems.len()); w.array(7 + usize::from(!units.is_empty())); let flags = FLAG_DELTA | crate::encode::FLAG_IMPLIED_OWNERS @@ -1111,20 +1193,23 @@ fn apply( // (created table + identities) apply regardless of it. let (scheme, flags) = crate::decode::parse_header(r.uint()?)?; if flags & FLAG_DELTA == 0 { - return Err(Error::new("not a delta payload; decode with from_cbor")); + return Err(Error::of( + ErrorKind::WrongForm, + "not a delta payload; decode with from_cbor", + )); } let portable = flags & FLAG_DELTA_PORTABLE != 0; let elided = flags & crate::encode::FLAG_ELIDE_IDS != 0; let with_units = flags & crate::encode::FLAG_UNIT_PATHS != 0; let implied = flags & crate::encode::FLAG_IMPLIED_OWNERS != 0; - let known = FLAG_DELTA - | FLAG_DELTA_PORTABLE - | crate::encode::FLAG_ELIDE_IDS - | crate::encode::FLAG_UNIT_PATHS - | crate::encode::FLAG_IMPLIED_OWNERS; - if flags & !known != 0 { - return Err(Error::new(format!("unknown header flags {flags:#x}"))); - } + gate_flags( + flags, + FLAG_DELTA + | FLAG_DELTA_PORTABLE + | crate::encode::FLAG_ELIDE_IDS + | crate::encode::FLAG_UNIT_PATHS + | crate::encode::FLAG_IMPLIED_OWNERS, + )?; let expect_arity = 6 + usize::from(implied) + usize::from(with_units); if arity != expect_arity { return Err(Error::new(format!( @@ -1138,11 +1223,14 @@ fn apply( return Err(Error::new("id elision applies to strict deltas only")); } if elided && scheme != crate::ID_SCHEME_VERSION { - return Err(Error::new(format!( - "id-derivation scheme {scheme} unsupported (decoder carries {}); \ - the delta's created ids cannot be recovered here", - crate::ID_SCHEME_VERSION - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "id-derivation scheme {scheme} unsupported (decoder carries {}); \ + the delta's created ids cannot be recovered here", + crate::ID_SCHEME_VERSION + ), + )); } if lenient && !portable { return Err(Error::new( @@ -1152,7 +1240,8 @@ fn apply( } let resolver = if elided { Some(resolver.ok_or_else(|| { - Error::new( + Error::of( + ErrorKind::NeedsResolver, "id-elided delta; apply with apply_delta_cbor_with and, for \ library-typed models, the library name resolver", ) @@ -1184,25 +1273,28 @@ fn apply( } } - let base_canon = delta_canonical(base)?; - let held_digest = digest_of_canonical(&base_canon)?; + let base_arr = canonical_views(base)?; + let held_digest = digest_of_canonical(&base_arr)?; let base_matched = held_digest == base_digest; if !base_matched && !lenient { - return Err(Error::new( + return Err(Error::of( + ErrorKind::BaseDigestMismatch, "held base does not match the delta's base digest — fetch the declared \ base (see the payload's claims) or, for a portable delta, apply \ leniently and review the report", )); } - let base_arr = base_canon.as_array().unwrap(); - let declared_b = r.uint()? as usize; + let declared_b = r.index()?; if portable { if declared_b != 0 { return Err(Error::new("portable delta declares no base index space")); } } else if declared_b != base_arr.len() { - return Err(Error::new("base element count differs from the held base")); + return Err(Error::of( + ErrorKind::BaseDigestMismatch, + "base element count differs from the held base", + )); } let n_ext = r.array()?; let exts = read_uuid_table(&mut r, n_ext)?; @@ -1215,28 +1307,18 @@ fn apply( if r.array()? != 3 { return Err(Error::new("elided created-id section is array(3)")); } - let n_created = r.uint()? as usize; + let n_created = r.index()?; if n_created > r.remaining() { return Err(Error::new("created count longer than payload")); } - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 18 => m, - Head::Map(_) => return Err(Error::new("exception map longer than payload")), - _ => return Err(Error::new("exception map expected")), - }; - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()? as usize; - if k as i64 <= prev { - return Err(Error::new("exception indices not ascending")); - } - if k >= n_created { - return Err(Error::new("exception index out of range")); - } - prev = k as i64; + let entries = r.ascending_map("exception map", 18, |r| { let b: [u8; 16] = r.bstr(16)?.try_into().unwrap(); - created_exceptions.insert(k, Uuid::from_bytes(b)); + Ok(Uuid::from_bytes(b)) + })?; + if entries.last().is_some_and(|&(k, _)| k >= n_created) { + return Err(Error::new("exception index out of range")); } + created_exceptions = entries.into_iter().collect(); let d: [u8; 16] = r.bstr(16)?.try_into().unwrap(); created_digest = Some(Uuid::from_bytes(d)); (0..n_created).map(crate::decode::placeholder).collect() @@ -1250,17 +1332,12 @@ fn apply( .iter() .map(|e| e["@id"].as_str().unwrap().to_owned()) .collect(); - let combined: Vec = if portable { - created.clone() - } else { - base_ids - .iter() - .cloned() - .chain(created.iter().cloned()) - .collect() - }; + // Strict identities index the base then the created ids; portable + // ones carry base references as externals, so the base table is + // not part of that space. let tables = Tables { - ids: &combined, + ids: if portable { &[] } else { &base_ids }, + created: &created, exts: &exts, }; let field_tables = table_set(false); @@ -1310,11 +1387,11 @@ fn apply( let identity = match r.head()? { Head::Null => Ident::Create, Head::Uint(i) if !portable => { - let i = i as usize; - if i >= base_arr.len() { - return Err(Error::new(format!("change target {i} out of range"))); - } - Ident::Base(i) + let at = usize::try_from(i) + .ok() + .filter(|&at| at < base_arr.len()) + .ok_or_else(|| Error::new(format!("change target {i} out of range")))?; + Ident::Base(at) } Head::Bstr(16) if portable => { let u = Uuid::from_bytes(r.take(16)?.try_into().unwrap()); @@ -1352,7 +1429,7 @@ fn apply( let Ident::Base(i) = identity else { return Err(Error::new("patch record targets a base element")); }; - let element = read_patch(&mut r, &tables, m, &base_arr[i])?; + let element = read_patch(&mut r, &tables, m, base_arr[i])?; replaced.insert(i, element); } Head::Array(3) => { @@ -1420,31 +1497,19 @@ fn apply( // bits, only meaningful on records that shipped whole elements. let mut owner_bits_by_id: HashMap = HashMap::new(); if implied { - let mut bits_by_ordinal: HashMap = HashMap::new(); - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("owner-exception map longer than payload")), - _ => return Err(Error::new("owner-exception map expected")), - }; - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()? as usize; - if k as i64 <= prev { - return Err(Error::new("owner-exception indices not ascending")); - } - if k >= record_elem_ids.len() { + let entries = r.ascending_map("owner-exception map", 2, |r| match r.uint()? { + bits @ 1..=3 => Ok(bits), + _ => Err(Error::new("owner-exception bits out of range")), + })?; + for &(k, _) in &entries { + if record_elem_ids.get(k).is_none() { return Err(Error::new("owner-exception index out of range")); } - prev = k as i64; - let bits = r.uint()?; - if bits == 0 || bits > 3 { - return Err(Error::new("owner-exception bits out of range")); - } if record_elem_ids[k].is_none() { return Err(Error::new("owner-exception record did not ship an element")); } - bits_by_ordinal.insert(k, bits); } + let bits_by_ordinal: HashMap = entries.into_iter().collect(); // Later records win an id (portable replaces): iterate in // record order so the surviving record's bits apply. for (k, id) in record_elem_ids.iter().enumerate() { @@ -1458,26 +1523,9 @@ fn apply( // validated against the result length once it is assembled. let mut units: Vec<(usize, String)> = Vec::new(); if with_units { - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("unit-path map longer than payload")), - _ => return Err(Error::new("unit-path map expected")), - }; - let mut prev: i64 = -1; - for _ in 0..m { - let i = r.uint()? as usize; - if i as i64 <= prev { - return Err(Error::new("unit root indices not ascending")); - } - prev = i as i64; - let path = match r.head()? { - Head::Tstr(n) => r.tstr_body(n)?.to_owned(), - _ => return Err(Error::new("unit path is a text string")), - }; - if path.is_empty() { - return Err(Error::new("empty unit path")); - } - units.push((i, path)); + units = read_units(&mut r)?; + if units.iter().any(|(_, path)| path.is_empty()) { + return Err(Error::new("empty unit path")); } } @@ -1486,7 +1534,7 @@ fn apply( if deleted.contains(&i) { continue; } - result.push(replaced.remove(&i).unwrap_or_else(|| e.clone())); + result.push(replaced.remove(&i).unwrap_or_else(|| (*e).clone())); } result.extend(appended); if !r.done() { @@ -1551,7 +1599,7 @@ fn apply( .collect(); } } - let mut value = delta_canonical(&applied)?; + let mut value = canonical_owned(applied)?; if implied { // Re-materialize elided backpointers on the shipped records: // derivation runs over the canonicalized applied state — the @@ -1596,7 +1644,7 @@ fn apply( } } if base_matched { - let got = digest_of_canonical(&value)?; + let got = digest_of_canonical(&views(value.as_array().unwrap()))?; if got != result_digest { return Err(Error::new( "applied state does not match the delta's result digest — the \ diff --git a/crates/sysmlv2-cbor/src/describe.rs b/crates/sysmlv2-cbor/src/describe.rs index d8bb142..5aa69c4 100644 --- a/crates/sysmlv2-cbor/src/describe.rs +++ b/crates/sysmlv2-cbor/src/describe.rs @@ -11,6 +11,7 @@ //! not compute with it. use crate::cbor::{Head, Reader}; +use crate::decode::{gate_flags, header_axes, read_units}; use crate::delta::{FLAG_DELTA, FLAG_DELTA_PORTABLE}; use crate::encode::{FLAG_ELIDE_IDS, FLAG_FULL_FORM}; use crate::{Error, strip_magic}; @@ -21,6 +22,14 @@ use uuid::Uuid; /// truncating (the counts stay exact either way). const TARGET_CAP: usize = 64; +/// The units section, rendered for the summary. +fn unit_summary(r: &mut Reader) -> Result, Error> { + Ok(read_units(r)? + .into_iter() + .map(|(index, path)| json!({ "index": index, "path": path })) + .collect()) +} + fn uuid16(r: &mut Reader) -> Result { Ok(Uuid::from_bytes(r.bstr(16)?.try_into().unwrap())) } @@ -30,6 +39,7 @@ fn uuid16(r: &mut Reader) -> Result { /// ```json /// { /// "form": "compact" | "full" | "delta", +/// "explicitIds": bool (compact: the ids are not all graph-derived), /// "bytes": 1234, /// "versions": { "layout": 1, "tables": 1, "scheme": 1, /// "supported": true }, @@ -59,17 +69,17 @@ fn uuid16(r: &mut Reader) -> Result { /// (only the wire layout must match — without it the structure cannot /// be read); `versions.supported` says whether this build's decoders /// would accept the payload outright. +/// +/// # Panics +/// Never in practice: the only unwrapping is of literal JSON objects +/// this function has just built. pub fn describe(bytes: &[u8]) -> Result { let mut r = Reader::new(strip_magic(bytes)?); let arity = r.array()?; - let header = r.uint()?; - if header >> 40 != 0 { - return Err(Error::new("unrecognized header word")); - } - let layout = (header >> 32) as u8; - let tables = (header >> 16) as u16; - let scheme = (header >> 8) as u8; - let flags = header as u8; + // Inspection reports the version axes rather than gating them — + // all but the layout, without which the structure cannot be read + // at all. + let (layout, tables, scheme, flags) = header_axes(r.uint()?)?; if layout != crate::LAYOUT_VERSION { return Err(Error::new(format!( "layout version {layout} unsupported (this build carries {})", @@ -81,15 +91,17 @@ pub fn describe(bytes: &[u8]) -> Result { let full = flags & FLAG_FULL_FORM != 0; let with_units = flags & crate::FLAG_UNIT_PATHS != 0; let implied = flags & crate::FLAG_IMPLIED_OWNERS != 0; - let known = FLAG_DELTA - | FLAG_DELTA_PORTABLE - | FLAG_ELIDE_IDS - | FLAG_FULL_FORM - | crate::FLAG_UNIT_PATHS - | crate::FLAG_IMPLIED_OWNERS; - if flags & !known != 0 { - return Err(Error::new(format!("unknown header flags {flags:#x}"))); - } + let explicit_ids = flags & crate::FLAG_EXPLICIT_IDS != 0; + gate_flags( + flags, + FLAG_DELTA + | FLAG_DELTA_PORTABLE + | FLAG_ELIDE_IDS + | FLAG_FULL_FORM + | crate::FLAG_UNIT_PATHS + | crate::FLAG_IMPLIED_OWNERS + | crate::FLAG_EXPLICIT_IDS, + )?; let supported = tables == crate::tables::CBOR_TABLES_VERSION && (!elided || scheme == crate::ID_SCHEME_VERSION); let mut out = Map::new(); @@ -119,6 +131,7 @@ pub fn describe(bytes: &[u8]) -> Result { } out.insert("idsElided".into(), json!(elided)); out.insert("impliedOwners".into(), json!(implied)); + out.insert("explicitIds".into(), json!(explicit_ids)); let n_ext = r.array()?; if n_ext > r.remaining() / 17 { return Err(Error::new("UUID table longer than payload")); @@ -131,15 +144,9 @@ pub fn describe(bytes: &[u8]) -> Result { if r.array()? != 2 { return Err(Error::new("elided id section is array(2)")); } - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 18 => m, - Head::Map(_) => return Err(Error::new("exception map longer than payload")), - _ => return Err(Error::new("exception map expected")), - }; - for _ in 0..m { - r.uint()?; - r.bstr(16)?; - } + let m = r + .ascending_map("exception map", 18, |r| r.bstr(16).map(|_| ()))? + .len(); out.insert("exceptions".into(), json!(m)); out.insert("idDigest".into(), json!(uuid16(&mut r)?.to_string())); } else { @@ -159,34 +166,14 @@ pub fn describe(bytes: &[u8]) -> Result { r.skip_items(elements as u64)?; if implied { // Owner exceptions: element index → absent-key bits. - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("owner-exception map longer than payload")), - _ => return Err(Error::new("owner-exception map expected")), - }; - for _ in 0..m { - r.uint()?; - r.uint()?; - } + let m = r + .ascending_map("owner-exception map", 2, |r| r.uint().map(|_| ()))? + .len(); out.insert("ownerExceptions".into(), json!(m)); } if with_units { // Unit structure: root element index → source path. - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("unit-path map longer than payload")), - _ => return Err(Error::new("unit-path map expected")), - }; - let mut units = Vec::with_capacity(m); - for _ in 0..m { - let index = r.uint()?; - let path = match r.head()? { - Head::Tstr(n) => r.tstr_body(n)?.to_owned(), - _ => return Err(Error::new("unit path is a text string")), - }; - units.push(json!({ "index": index, "path": path })); - } - out.insert("units".into(), json!(units)); + out.insert("units".into(), json!(unit_summary(&mut r)?)); } if !r.done() { return Err(Error::new("trailing bytes after payload")); @@ -239,19 +226,13 @@ pub fn describe(bytes: &[u8]) -> Result { if r.array()? != 3 { return Err(Error::new("elided created-id section is array(3)")); } - let n = r.uint()? as usize; + let n = r.index()?; if n > r.remaining() { return Err(Error::new("created count longer than payload")); } - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 18 => m, - Head::Map(_) => return Err(Error::new("exception map longer than payload")), - _ => return Err(Error::new("exception map expected")), - }; - for _ in 0..m { - r.uint()?; - r.bstr(16)?; - } + let m = r + .ascending_map("exception map", 18, |r| r.bstr(16).map(|_| ()))? + .len(); exceptions = Some(m); id_digest = Some(uuid16(&mut r)?); n @@ -315,6 +296,9 @@ pub fn describe(bytes: &[u8]) -> Result { } }, // Field-patch update: map of ordinal → op pairs. + Head::Map(m) if m > r.remaining() / 2 => { + return Err(Error::new("patch longer than payload")); + } Head::Map(m) => match identity { Some(id) => { updates += 1; @@ -333,33 +317,15 @@ pub fn describe(bytes: &[u8]) -> Result { // bits on records that shipped whole elements. let mut owner_exceptions: Option = None; if implied { - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("owner-exception map longer than payload")), - _ => return Err(Error::new("owner-exception map expected")), - }; - for _ in 0..m { - r.uint()?; - r.uint()?; - } - owner_exceptions = Some(m); + owner_exceptions = Some( + r.ascending_map("owner-exception map", 2, |r| r.uint().map(|_| ()))? + .len(), + ); } // Units section: result element index → source path. let mut units = Vec::new(); if with_units { - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("unit-path map longer than payload")), - _ => return Err(Error::new("unit-path map expected")), - }; - for _ in 0..m { - let index = r.uint()?; - let path = match r.head()? { - Head::Tstr(n) => r.tstr_body(n)?.to_owned(), - _ => return Err(Error::new("unit path is a text string")), - }; - units.push(json!({ "index": index, "path": path })); - } + units = unit_summary(&mut r)?; } if !r.done() { return Err(Error::new("trailing bytes after payload")); diff --git a/crates/sysmlv2-cbor/src/encode.rs b/crates/sysmlv2-cbor/src/encode.rs index 151a62c..ac1b8d8 100644 --- a/crates/sysmlv2-cbor/src/encode.rs +++ b/crates/sysmlv2-cbor/src/encode.rs @@ -50,6 +50,14 @@ pub const FLAG_UNIT_PATHS: u8 = 16; /// (`to_compact_cbor_canonical`), which always spells owners. pub const FLAG_IMPLIED_OWNERS: u8 = 32; +/// Header flag marking a compact payload whose element ids are +/// **explicit**: at least one id is not the graph derivation of IDS.md +/// (a document loaded from another producer, or one carrying foreign +/// ids), so a receiver must not re-derive ids from the structure. Set by +/// a session that holds explicit ids; informational for decoders, which +/// always read the id table. Id elision is refused for such payloads. +pub const FLAG_EXPLICIT_IDS: u8 = 64; + /// The two backpointers and the forward list each derives from: /// slot 0 = `owningRelationship` ← membership in some element's /// `ownedRelatedElement`; slot 1 = `owningRelatedElement` ← @@ -69,15 +77,22 @@ pub(crate) fn owner_bit(slot: usize) -> u64 { /// null). The first claimant in element order, then list order, wins; /// encoder and decoder agree by running this identical rule over the /// identical arrays. -pub(crate) fn derive_owners(arr: &[Value]) -> Vec<[Option; 2]> { - let mut index: HashMap<&str, usize> = HashMap::with_capacity(arr.len()); - for (i, e) in arr.iter().enumerate() { +pub(crate) fn derive_owners<'a, I>(elements: I) -> Vec<[Option; 2]> +where + I: IntoIterator, + I::IntoIter: Clone, +{ + let elements = elements.into_iter(); + let mut index: HashMap<&str, usize> = HashMap::new(); + let mut n = 0usize; + for (i, e) in elements.clone().enumerate() { + n = i + 1; if let Some(id) = e.get("@id").and_then(Value::as_str) { index.entry(id).or_insert(i); } } - let mut owners = vec![[None, None]; arr.len()]; - for (i, e) in arr.iter().enumerate() { + let mut owners = vec![[None, None]; n]; + for (i, e) in elements.enumerate() { for (slot, (_, forward)) in OWNER_SLOTS.iter().enumerate() { let targets = e.get(*forward).and_then(Value::as_array); for t in targets.into_iter().flatten() { @@ -119,6 +134,17 @@ pub(crate) fn ctx(ty: &str, prop: &str, what: &str) -> Error { Error::new(format!("{ty}.{prop}: {what}")) } +/// A metaclass's position in a field table as the 16-bit wire type +/// code. The generated tables are far shorter than that code space — +/// `tables_fit_the_wire_code_spaces` holds it — so this never fails in +/// practice; it is spelled as a conversion rather than a narrowing cast +/// so a regenerated table could never wrap a code into another +/// metaclass's. +pub(crate) fn wire_code(position: usize) -> Result { + u16::try_from(position) + .map_err(|_| Error::new("metaclass table outgrew the wire type-code space")) +} + fn parse_uuid(s: &str) -> Result { Uuid::try_parse(s).map_err(|_| Error::new(format!("invalid UUID `{s}`"))) } @@ -133,15 +159,23 @@ pub(crate) struct Elem<'a> { pub(crate) uuid: Uuid, } +/// The payload's elements as borrowed views, in payload order — the +/// form every encoding pass walks, so a re-ordered or filtered element +/// list costs a vector of pointers instead of a copy of the model. +pub(crate) fn element_views(value: &Value) -> Result, Error> { + Ok(value + .as_array() + .ok_or_else(|| Error::new("interchange payload is a flat element array"))? + .iter() + .collect()) +} + pub(crate) fn elems_of<'a>( - value: &'a Value, + elements: &[&'a Value], tables: &'static [(&'static str, &'static [CborField])], ) -> Result>, Error> { - let arr = value - .as_array() - .ok_or_else(|| Error::new("interchange payload is a flat element array"))?; - let mut out = Vec::with_capacity(arr.len()); - for e in arr { + let mut out = Vec::with_capacity(elements.len()); + for &e in elements { let obj = e .as_object() .ok_or_else(|| Error::new("element is an object"))?; @@ -149,9 +183,11 @@ pub(crate) fn elems_of<'a>( .get("@type") .and_then(Value::as_str) .ok_or_else(|| Error::new("element has a string @type"))?; - let code = tables - .binary_search_by(|(n, _)| n.cmp(&ty)) - .map_err(|_| Error::new(format!("unknown @type `{ty}`")))? as u16; + let code = wire_code( + tables + .binary_search_by(|(n, _)| n.cmp(&ty)) + .map_err(|_| Error::new(format!("unknown @type `{ty}`")))?, + )?; let id = obj .get("@id") .and_then(Value::as_str) @@ -185,13 +221,52 @@ pub(crate) fn default_value(field: &CborField, id: &str) -> Option { }) } -/// `{"@id": …}` target UUID, if the value is an id-based reference. -pub(crate) fn ref_uuid(v: &Value) -> Result, Error> { - let Value::Object(o) = v else { return Ok(None) }; +/// Is `value` the field's default — [`default_value`]'s +/// allocation-free twin, for the callers that only compare. `id` feeds +/// the `elementId` mirror rule; a kind with no default (a literal) is +/// never equal to one. +pub(crate) fn is_default_value(field: &CborField, id: &str, value: &Value) -> bool { + let (_, kind, etbl, dflt) = *field; + match kind { + K_BOOL => value.as_bool() == Some(dflt == 1), + K_STR | K_REF => value.is_null(), + K_STR_LIST | K_REF_LIST => value.as_array().is_some_and(Vec::is_empty), + K_ENUM => match dflt { + 255 => value.is_null(), + d => { + value.is_string() + && value.as_str() + == ENUM_TABLES + .get(etbl as usize) + .and_then(|t| t.get(d as usize)) + .copied() + } + }, + K_ELEMENT_ID => value.as_str() == Some(id), + _ => false, + } +} + +/// What a reference value points at. +pub(crate) enum RefTarget<'a> { + /// `{"@id": …}` — an element identity, interned to a wire index. + Id(Uuid), + /// `{"@ref": …}` — a symbolic reference, carried verbatim. + Symbolic(&'a str), +} + +/// Classify a reference value. Every other shape — a non-object, an +/// empty object, extra keys, a non-string target — is an error, so no +/// caller has to assume the shape a reference list item did not have. +pub(crate) fn ref_target(v: &Value) -> Result, Error> { + let bad = || Error::new("reference is {\"@id\": …} or {\"@ref\": …}"); + let Value::Object(o) = v else { + return Err(bad()); + }; match (o.len(), o.get("@id"), o.get("@ref")) { - (1, Some(Value::String(s)), None) => parse_uuid(s).map(Some), - (1, None, Some(Value::String(_))) => Ok(None), - _ => Err(Error::new("reference is {\"@id\": …} or {\"@ref\": …}")), + (1, Some(Value::String(s)), None) => parse_uuid(s).map(RefTarget::Id), + (1, None, Some(Value::String(s))) => Ok(RefTarget::Symbolic(s)), + _ => Err(bad()), } } @@ -225,13 +300,17 @@ impl Interner { let ord = ordinal(e.fields, key) .ok_or_else(|| ctx(e.ty, key, "not a compact-form property"))?; let kind = e.fields[ord as usize].1; - let targets: Box> = match (kind, value) { - (K_REF, v) => Box::new(std::iter::once(v)), - (K_REF_LIST, Value::Array(a)) => Box::new(a.iter()), + // A null single reference is the non-default null + // `write_value` spells; any other non-object shape is + // refused there with the field's own message. + let targets: &[Value] = match (kind, value) { + (K_REF, Value::Object(_)) => std::slice::from_ref(value), + (K_REF_LIST, Value::Array(a)) => a, _ => continue, }; for t in targets { - if let Some(u) = ref_uuid(t)? { + let target = ref_target(t).map_err(|err| ctx(e.ty, key, &err.to_string()))?; + if let RefTarget::Id(u) = target { if !local.contains_key(&u) { ext.insert(u); } @@ -258,9 +337,9 @@ impl Interner { } pub(crate) fn write_ref(w: &mut Writer, interner: &Interner, v: &Value) -> Result<(), Error> { - match ref_uuid(v)? { - Some(u) => w.uint(interner.index(u)), - None => w.tstr(v["@ref"].as_str().unwrap()), + match ref_target(v)? { + RefTarget::Id(u) => w.uint(interner.index(u)), + RefTarget::Symbolic(s) => w.tstr(s), } Ok(()) } @@ -285,11 +364,13 @@ pub(crate) fn write_value( w.tstr(s.as_str().ok_or_else(|| bad("string list holds strings"))?); } } - (K_REF, Value::Object(_)) => write_ref(w, interner, v)?, + (K_REF, Value::Object(_)) => { + write_ref(w, interner, v).map_err(|err| ctx(ty, prop, &err.to_string()))?; + } (K_REF_LIST, Value::Array(a)) => { w.array(a.len()); for t in a { - write_ref(w, interner, t)?; + write_ref(w, interner, t).map_err(|err| ctx(ty, prop, &err.to_string()))?; } } (K_ENUM, Value::String(s)) => { @@ -323,9 +404,11 @@ pub(crate) fn write_element( implied_owners: Option<&[Option<&str>; 2]>, ) -> Result<(), Error> { // Presence bits: u64 fast path, byte-string bitmap for the wide - // full-form field lists (bit i of byte i/8, little-endian). - let mut bits = vec![0u8; e.fields.len().div_ceil(8)]; - let mut entries: Vec<(u8, &Value)> = Vec::new(); + // full-form field lists (bit i of byte i/8, little-endian). The + // wire ordinal is a byte, so no field list is longer than 256 and + // no bitmap wider than 32 — it rides the stack. + let mut bits = [0u8; 32]; + let mut entries: Vec<(u8, &Value)> = Vec::with_capacity(e.obj.len()); 'keys: for (key, value) in e.obj { if key == "@id" || key == "@type" { continue; @@ -351,23 +434,19 @@ pub(crate) fn write_element( // Interner::build verified every key. let ord = ordinal(e.fields, key).unwrap(); let field = &e.fields[ord as usize]; - if default_value(field, e.id).is_some_and(|d| d == *value) { + if is_default_value(field, e.id, value) { bits[ord as usize / 8] |= 1 << (ord % 8); } else { entries.push((ord, value)); } } - entries.sort_by_key(|&(ord, _)| ord); + entries.sort_unstable_by_key(|&(ord, _)| ord); w.array(3); w.uint(e.code as u64); if e.fields.len() <= 64 { - let mut presence = 0u64; - for (i, b) in bits.iter().enumerate() { - presence |= (*b as u64) << (i * 8); - } - w.uint(presence); + w.uint(u64::from_le_bytes(std::array::from_fn(|i| bits[i]))); } else { - w.bstr(&bits); + w.bstr(&bits[..e.fields.len().div_ceil(8)]); } w.map(entries.len()); for (ord, value) in entries { @@ -416,9 +495,8 @@ fn write_units(w: &mut Writer, units: &[(usize, String)]) { /// the two ingredients [`FLAG_IMPLIED_OWNERS`] encoding needs. pub(crate) type OwnerPlan<'a> = (Vec<[Option<&'a str>; 2]>, Vec<(u64, u64)>); -pub(crate) fn owner_plan<'a>(value: &'a Value, elems: &[Elem<'a>]) -> OwnerPlan<'a> { - let arr = value.as_array().expect("elems_of validated the array"); - let owners = derive_owners(arr); +pub(crate) fn owner_plan<'a>(elements: &[&Value], elems: &[Elem<'a>]) -> OwnerPlan<'a> { + let owners = derive_owners(elements.iter().copied()); let derived: Vec<[Option<&str>; 2]> = owners .iter() .map(|o| o.map(|s| s.map(|j| elems[j].id))) @@ -455,24 +533,35 @@ fn write_owner_exceptions(w: &mut Writer, exceptions: &[(u64, u64)]) { } fn encode( - value: &Value, + elements: &[&Value], full: bool, units: &[(usize, String)], implied_owners: bool, ) -> Result, Error> { - let elems = elems_of(value, table_set(full))?; + encode_flagged(elements, full, units, implied_owners, 0) +} + +fn encode_flagged( + elements: &[&Value], + full: bool, + units: &[(usize, String)], + implied_owners: bool, + extra_flags: u8, +) -> Result, Error> { + let elems = elems_of(elements, table_set(full))?; let units = check_units(units, elems.len())?; let interner = Interner::build(&elems)?; let implied = implied_owners && !full; - let owners = implied.then(|| owner_plan(value, &elems)); + let owners = implied.then(|| owner_plan(elements, &elems)); let mut flags = if full { FLAG_FULL_FORM } else { 0 }; + flags |= extra_flags; if units.is_some() { flags |= FLAG_UNIT_PATHS; } if implied { flags |= FLAG_IMPLIED_OWNERS; } - let mut w = Writer::with_magic(); + let mut w = Writer::with_magic_for(elems.len()); w.array(4 + usize::from(implied) + usize::from(units.is_some())); w.uint(header_word(flags)); w.array(interner.ext.len()); @@ -500,14 +589,14 @@ fn encode( /// backpointers travel implied ([`FLAG_IMPLIED_OWNERS`]) — decode /// re-derives them, Value-identically. pub fn to_compact_cbor(value: &Value) -> Result, Error> { - encode(value, false, &[], true) + encode(&element_views(value)?, false, &[], true) } /// The digest-space encoding: owners always spelled, no /// [`FLAG_IMPLIED_OWNERS`]. State digests canonicalize through this, /// so wire-format elision never moves a digest. Not a wire emitter. -pub(crate) fn to_compact_cbor_canonical(value: &Value) -> Result, Error> { - encode(value, false, &[], false) +pub(crate) fn to_compact_cbor_canonical(elements: &[&Value]) -> Result, Error> { + encode(elements, false, &[], false) } /// [`to_compact_cbor`] carrying the model's **unit structure**: each @@ -519,7 +608,23 @@ pub fn to_compact_cbor_with_units( value: &Value, units: &[(usize, String)], ) -> Result, Error> { - encode(value, false, units, true) + encode(&element_views(value)?, false, units, true) +} + +/// [`to_compact_cbor_with_units`] for a model whose ids are **explicit** +/// (not all graph-derived): the payload carries [`FLAG_EXPLICIT_IDS`] so +/// a receiver never re-derives them. The element records are identical. +pub fn to_compact_cbor_with_units_explicit( + value: &Value, + units: &[(usize, String)], +) -> Result, Error> { + encode_flagged( + &element_views(value)?, + false, + units, + true, + FLAG_EXPLICIT_IDS, + ) } /// The digest namespace for [`id_digest`] (fixed, versioned with the @@ -562,7 +667,8 @@ pub fn to_compact_cbor_elided_with_units( external_name: &dyn Fn(&str) -> Option, units: &[(usize, String)], ) -> Result, Error> { - let elems = elems_of(value, table_set(false))?; + let elements = element_views(value)?; + let elems = elems_of(&elements, table_set(false))?; let units = check_units(units, elems.len())?; let interner = Interner::build(&elems)?; let derived = sysmlv2_model::ids::derive_ids(value, external_name).map_err(Error::new)?; @@ -573,12 +679,12 @@ pub fn to_compact_cbor_elided_with_units( .map(|(i, e)| (i as u64, e.uuid)) .collect(); let digest = id_digest(elems.iter().map(|e| e.uuid)); - let (owner_derived, owner_exceptions) = owner_plan(value, &elems); + let (owner_derived, owner_exceptions) = owner_plan(&elements, &elems); let mut flags = FLAG_ELIDE_IDS | FLAG_IMPLIED_OWNERS; if units.is_some() { flags |= FLAG_UNIT_PATHS; } - let mut w = Writer::with_magic(); + let mut w = Writer::with_magic_for(elems.len()); w.array(5 + usize::from(units.is_some())); w.uint(header_word(flags)); w.array(interner.ext.len()); @@ -611,11 +717,66 @@ pub fn to_compact_cbor_elided_with_units( /// without running derivation — full-form CBOR is never an ingest /// format: lift consumes the compact form. pub fn to_full_cbor(value: &Value) -> Result, Error> { - encode(value, true, &[], false) + encode(&element_views(value)?, true, &[], false) } /// [`to_full_cbor`] carrying the model's unit structure (see /// [`to_compact_cbor_with_units`]). pub fn to_full_cbor_with_units(value: &Value, units: &[(usize, String)]) -> Result, Error> { - encode(value, true, units, false) + encode(&element_views(value)?, true, units, false) +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Building a field's default and recognizing one are the same + /// rule, stated twice for the callers that only need to compare. + /// Over every field of every metaclass in both table sets, the two + /// agree on the default itself and on a spread of other values. + #[test] + fn the_two_default_rules_agree_on_every_field() { + let id = "00000000-0000-4000-8000-000000000001"; + let other = "00000000-0000-4000-8000-000000000002"; + let probes = [ + Value::Null, + Value::Bool(true), + Value::Bool(false), + Value::String(id.to_owned()), + Value::String(other.to_owned()), + Value::String(String::new()), + Value::Array(Vec::new()), + Value::Array(vec![Value::Null]), + serde_json::json!(0), + serde_json::json!({ "@id": id }), + ]; + for tables in [table_set(false), table_set(true)] { + for (ty, fields) in tables { + for field in *fields { + let built = default_value(field, id); + for probe in &probes { + assert_eq!( + is_default_value(field, id, probe), + built.as_ref() == Some(probe), + "{ty}.{}: {probe} against {built:?}", + field.0 + ); + } + // Every enum vocabulary word, so the default word + // is told apart from its neighbours. + if field.1 == K_ENUM && field.2 != 255 { + for word in ENUM_TABLES[field.2 as usize] { + let probe = Value::String((*word).to_owned()); + assert_eq!( + is_default_value(field, id, &probe), + built.as_ref() == Some(&probe), + "{ty}.{}: enum word {word}", + field.0 + ); + } + } + } + } + } + } } diff --git a/crates/sysmlv2-cbor/src/index.rs b/crates/sysmlv2-cbor/src/index.rs index a6a66e3..7ad9525 100644 --- a/crates/sysmlv2-cbor/src/index.rs +++ b/crates/sysmlv2-cbor/src/index.rs @@ -23,10 +23,12 @@ //! delta's base digest before trusting index resolution. use crate::cbor::{Head, Reader}; -use crate::decode::{Tables, read_element_body, read_uuid_table, read_value}; +use crate::decode::{ + Tables, gate_flags, read_element_body, read_units, read_uuid_table, read_uuids, read_value, +}; use crate::delta::{Claim, FLAG_DELTA, FLAG_DELTA_PORTABLE, OP_SET, OP_SPLICE, OP_UNSET}; -use crate::encode::{FLAG_ELIDE_IDS, FLAG_IMPLIED_OWNERS, FLAG_UNIT_PATHS, table_set}; -use crate::{Error, delta_canonical}; +use crate::encode::{FLAG_ELIDE_IDS, FLAG_IMPLIED_OWNERS, FLAG_UNIT_PATHS, table_set, wire_code}; +use crate::{Error, ErrorKind}; use serde_json::Value; use std::collections::HashMap; use uuid::Uuid; @@ -51,9 +53,13 @@ pub struct BaseIndex { impl BaseIndex { /// Build (and canonicalize) from a compact element array. + /// + /// # Panics + /// If an element has no string `@id`. Canonicalization runs first + /// and refuses such a payload, so one that reached this point + /// carries them. pub fn from_compact(compact: &Value) -> Result { - let canon = delta_canonical(compact)?; - let arr = canon.as_array().unwrap(); + let arr = crate::delta::canonical_views(compact)?; let tables = table_set(false); let mut ids = Vec::with_capacity(arr.len()); let mut types = Vec::with_capacity(arr.len()); @@ -68,8 +74,8 @@ impl BaseIndex { .binary_search_by(|(n, _)| n.cmp(&ty)) .map_err(|_| Error::new(format!("unknown @type `{ty}`")))?; ids.push(Uuid::try_parse(id).map_err(|_| Error::new(format!("invalid UUID `{id}`")))?); - types.push(code as u16); - pos.entry(id).or_insert(i as u32); + types.push(wire_code(code)?); + pos.entry(id).or_insert(adjacency_pos(i)?); } let adjacency = |key: &str| -> Vec> { arr.iter() @@ -92,30 +98,36 @@ impl BaseIndex { }) } + #[must_use] pub fn len(&self) -> usize { self.ids.len() } + #[must_use] pub fn is_empty(&self) -> bool { self.ids.is_empty() } /// Element id at canonical position `i`. + #[must_use] pub fn id(&self, i: usize) -> Uuid { self.ids[i] } /// Concrete-metaclass wire code at canonical position `i`. + #[must_use] pub fn type_code(&self, i: usize) -> u16 { self.types[i] } /// The ids in canonical order — the strict-delta index space. + #[must_use] pub fn ids(&self) -> &[Uuid] { &self.ids } /// Versioned, checksummed binary form (the registry artifact). + #[must_use] pub fn to_bytes(&self) -> Vec { let mut b = Vec::with_capacity(self.ids.len() * 20 + 16); b.extend_from_slice(INDEX_MAGIC); @@ -145,10 +157,13 @@ impl BaseIndex { return Err(Error::new("not a base-index artifact")); } if bytes[4] != INDEX_VERSION { - return Err(Error::new(format!( - "base-index version {} unsupported (this build carries {INDEX_VERSION})", - bytes[4] - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "base-index version {} unsupported (this build carries {INDEX_VERSION})", + bytes[4] + ), + )); } let (body, sum) = bytes.split_at(bytes.len() - 16); if Uuid::new_v5(&index_ns(), body).as_bytes() != sum { @@ -158,7 +173,7 @@ impl BaseIndex { b: &body[5..], at: 0, }; - let n = r.uvarint()? as usize; + let n = r.index()?; if n > body.len() / 16 { return Err(Error::new("base-index count longer than artifact")); } @@ -166,24 +181,32 @@ impl BaseIndex { for _ in 0..n { ids.push(Uuid::from_bytes(r.take16()?)); } + // Type codes index the compact field tables on every later + // use (patch resolution, transition), so range-check them here. + let n_types = table_set(false).len(); let mut types = Vec::with_capacity(n); for _ in 0..n { - types.push(r.uvarint()? as u16); + let code = r.uvarint()?; + let code = u16::try_from(code) + .ok() + .filter(|&c| usize::from(c) < n_types) + .ok_or_else(|| Error::new(format!("base-index type code {code} out of range")))?; + types.push(code); } let lists = |r: &mut VarReader| -> Result>, Error> { let mut out = Vec::with_capacity(n); for _ in 0..n { - let m = r.uvarint()? as usize; + let m = r.index()?; if m > body.len() { return Err(Error::new("base-index list longer than artifact")); } let mut l = Vec::with_capacity(m); for _ in 0..m { - let x = r.uvarint()?; - if x as usize >= n { - return Err(Error::new("base-index adjacency out of range")); - } - l.push(x as u32); + let x = u32::try_from(r.uvarint()?) + .ok() + .filter(|&x| (x as usize) < n) + .ok_or_else(|| Error::new("base-index adjacency out of range"))?; + l.push(x); } out.push(l); } @@ -203,6 +226,15 @@ impl BaseIndex { } } +/// An element's canonical position as a 32-bit adjacency entry. The +/// adjacency lists address the index's own elements, so a snapshot +/// that outgrows the 32-bit space is refused rather than aliased onto +/// a different element. +fn adjacency_pos(position: usize) -> Result { + u32::try_from(position) + .map_err(|_| Error::new("snapshot outgrew the 32-bit adjacency index space")) +} + fn uvarint(b: &mut Vec, mut v: u64) { loop { let byte = (v & 0x7f) as u8; @@ -227,7 +259,7 @@ impl VarReader<'_> { let byte = *self .b .get(self.at) - .ok_or_else(|| Error::new("truncated base-index artifact"))?; + .ok_or_else(|| Error::of(ErrorKind::Truncated, "truncated base-index artifact"))?; self.at += 1; v |= ((byte & 0x7f) as u64) << shift; if byte & 0x80 == 0 { @@ -237,19 +269,28 @@ impl VarReader<'_> { Err(Error::new("overlong varint in base-index artifact")) } + /// Read a varint as an in-memory index, length or position + /// ([`Reader::index_of`]). + fn index(&mut self) -> Result { + Reader::index_of(self.uvarint()?) + } + fn take16(&mut self) -> Result<[u8; 16], Error> { let end = self.at + 16; let s = self .b .get(self.at..end) - .ok_or_else(|| Error::new("truncated base-index artifact"))?; + .ok_or_else(|| Error::of(ErrorKind::Truncated, "truncated base-index artifact"))?; self.at = end; Ok(s.try_into().unwrap()) } } /// A resolved change target. +/// +/// Non-exhaustive: further identity modes would land here. #[derive(Debug, Clone, PartialEq)] +#[non_exhaustive] pub enum RecordTarget { /// A create; `id` comes from the created-id table. Create { id: Uuid }, @@ -261,7 +302,10 @@ pub enum RecordTarget { /// One field-level patch operation, values decoded to JSON shape /// (references as `{"@id": …}` / `{"@ref": …}`). +/// +/// Non-exhaustive: further opcodes would land here. #[derive(Debug, Clone, PartialEq)] +#[non_exhaustive] pub enum PatchOp { Set(Value), Unset, @@ -323,28 +367,32 @@ fn resolve(bytes: &[u8], base: Option<&BaseIndex>) -> Result) -> Result return Err(Error::new("claim is bstr(16) or text")), } } - let declared_b = r.uint()? as usize; + let declared_b = r.index()?; if let Some(base) = base { if declared_b != base.len() { - return Err(Error::new( + return Err(Error::of( + ErrorKind::BaseDigestMismatch, "base element count differs from the index — wrong or stale index", )); } @@ -386,13 +435,17 @@ fn resolve(bytes: &[u8], base: Option<&BaseIndex>) -> Result = base - .map(|b| b.ids.iter().map(Uuid::to_string).collect()) - .unwrap_or_default(); - let combined: Vec = base_ids.iter().cloned().chain(created.clone()).collect(); + .into_iter() + .flat_map(|b| b.ids.iter().map(Uuid::to_string)) + .collect(); + let created_ids: Vec = created.iter().map(Uuid::to_string).collect(); let tables = Tables { - ids: &combined, + ids: &base_ids, + created: &created_ids, exts: &exts, }; let field_tables = table_set(false); @@ -410,23 +463,21 @@ fn resolve(bytes: &[u8], base: Option<&BaseIndex>) -> Result { - let id = created + let &id = created .get(next_created) .ok_or_else(|| Error::new("created id table exhausted"))?; next_created += 1; - RecordTarget::Create { - id: Uuid::try_parse(id).unwrap(), - } + RecordTarget::Create { id } } Head::Uint(i) if !portable => { - let i = i as usize; let base = base.unwrap(); - if i >= base.len() { - return Err(Error::new(format!("change target {i} out of range"))); - } + let at = usize::try_from(i) + .ok() + .filter(|&at| at < base.len()) + .ok_or_else(|| Error::new(format!("change target {i} out of range")))?; RecordTarget::Base { - index: i, - id: base.ids[i], + index: at, + id: base.ids[at], } } Head::Bstr(16) if portable => RecordTarget::Id { @@ -472,22 +523,11 @@ fn resolve(bytes: &[u8], base: Option<&BaseIndex>) -> Result m, - Head::Map(_) => return Err(Error::new("owner-exception map longer than payload")), - _ => return Err(Error::new("owner-exception map expected")), - }; - let mut prev: i64 = -1; - for _ in 0..m { - let k = r.uint()? as usize; - if k as i64 <= prev { - return Err(Error::new("owner-exception indices not ascending")); - } - prev = k as i64; - let bits = r.uint()?; - if bits == 0 || bits > 3 { - return Err(Error::new("owner-exception bits out of range")); - } + let entries = r.ascending_map("owner-exception map", 2, |r| match r.uint()? { + bits @ 1..=3 => Ok(bits), + _ => Err(Error::new("owner-exception bits out of range")), + })?; + for (k, bits) in entries { let rec = records .get_mut(k) .ok_or_else(|| Error::new("owner-exception index out of range"))?; @@ -499,18 +539,10 @@ fn resolve(bytes: &[u8], base: Option<&BaseIndex>) -> Result = Vec::new(); if with_units { - let m = match r.head()? { - Head::Map(m) if m <= r.remaining() / 2 => m, - Head::Map(_) => return Err(Error::new("unit-path map longer than payload")), - _ => return Err(Error::new("unit-path map expected")), - }; - for _ in 0..m { - let i = r.uint()?; - match r.head()? { - Head::Tstr(n) => units.push((i, r.tstr_body(n)?.to_owned())), - _ => return Err(Error::new("unit path is a text string")), - } - } + units = read_units(&mut r)? + .into_iter() + .map(|(i, path)| (i as u64, path)) + .collect(); } if !r.done() { return Err(Error::new("trailing bytes after payload")); @@ -536,15 +568,16 @@ fn parse_patch_ops( return Err(Error::new("patch longer than payload")); } let mut ops = Vec::with_capacity(n); - let mut prev: i32 = -1; + let mut prev: Option = None; for _ in 0..n { let ord = r.uint()?; - if ord as i32 <= prev { + if prev.is_some_and(|p| ord <= p) { return Err(Error::new("patch ordinals not ascending")); } - prev = ord as i32; - let field = fields - .get(ord as usize) + prev = Some(ord); + let field = usize::try_from(ord) + .ok() + .and_then(|ord| fields.get(ord)) .ok_or_else(|| Error::new(format!("field ordinal {ord} out of range")))?; if r.array()? != 2 { return Err(Error::new("patch op is array(2)")); @@ -561,8 +594,8 @@ fn parse_patch_ops( if r.array()? != 3 { return Err(Error::new("splice op is array(3)")); } - let at = r.uint()? as usize; - let del = r.uint()? as usize; + let at = r.index()?; + let del = r.index()?; let len = r.array()?; if len > r.remaining() { return Err(Error::new("splice items longer than payload")); @@ -625,10 +658,11 @@ impl ResolvedDelta { .get("@type") .and_then(Value::as_str) .ok_or_else(|| Error::new("element record has a string @type"))?; - let code = tables - .binary_search_by(|(n, _)| n.cmp(&ty)) - .map_err(|_| Error::new(format!("unknown @type `{ty}`")))? - as u16; + let code = wire_code( + tables + .binary_search_by(|(n, _)| n.cmp(&ty)) + .map_err(|_| Error::new(format!("unknown @type `{ty}`")))?, + )?; let list = |key: &str| -> Vec { e.get(key) .and_then(Value::as_array) @@ -697,19 +731,15 @@ impl ResolvedDelta { .chain(appended) .collect(); // Canonical walk over structure (the delta_canonical rule). - let pos: HashMap = { + let pos: HashMap = { let mut m = HashMap::with_capacity(payload.len()); for (i, n) in payload.iter().enumerate() { - m.entry(n.id).or_insert(i); + m.entry(n.id).or_insert(adjacency_pos(i)?); } m }; - let resolve_list = |l: &[Uuid]| -> Vec { - l.iter() - .filter_map(|u| pos.get(u)) - .map(|&i| i as u32) - .collect() - }; + let resolve_list = + |l: &[Uuid]| -> Vec { l.iter().filter_map(|u| pos.get(u).copied()).collect() }; let kids: Vec> = payload.iter().map(|n| resolve_list(&n.kids)).collect(); let rels: Vec> = payload.iter().map(|n| resolve_list(&n.rels)).collect(); let n = payload.len(); @@ -741,11 +771,10 @@ impl ResolvedDelta { walk.push(i); } } - let renum: HashMap = walk - .iter() - .enumerate() - .map(|(k, &i)| (i, k as u32)) - .collect(); + let mut renum: HashMap = HashMap::with_capacity(walk.len()); + for (k, &i) in walk.iter().enumerate() { + renum.insert(i, adjacency_pos(k)?); + } Ok(BaseIndex { ids: walk.iter().map(|&i| payload[i].id).collect(), types: walk.iter().map(|&i| payload[i].ty).collect(), @@ -760,3 +789,90 @@ impl ResolvedDelta { }) } } + +#[cfg(test)] +mod tests { + use super::*; + + /// A one-element artifact carrying `code` as its type code, sealed + /// with the artifact checksum so the reader reaches the code + /// instead of stopping at the seal. Layout: magic, version, the + /// element count, one id, the type code, then that element's two + /// empty adjacency lists. + fn crafted(code: u64) -> Vec { + let mut body = INDEX_MAGIC.to_vec(); + body.push(INDEX_VERSION); + uvarint(&mut body, 1); + body.extend_from_slice(&[0x11; 16]); + uvarint(&mut body, code); + body.extend_from_slice(&[0, 0]); + let sum = Uuid::new_v5(&index_ns(), &body); + body.extend_from_slice(sum.as_bytes()); + body + } + + /// Artifacts whose body is mutated and then **re-sealed**, so the + /// reader walks the mutation instead of stopping at the checksum — + /// the coverage a byte-level fuzz of a sealed artifact cannot + /// reach. Deterministic, seeded. + #[test] + fn resealed_mutations_never_panic() { + let compact = serde_json::json!([ + { "@type": "Package", "@id": "00000000-0000-4000-8000-000000000001", + "ownedRelationship": [{ "@id": "00000000-0000-4000-8000-000000000002" }] }, + { "@type": "OwningMembership", "@id": "00000000-0000-4000-8000-000000000002", + "ownedRelatedElement": [{ "@id": "00000000-0000-4000-8000-000000000003" }] }, + { "@type": "Package", "@id": "00000000-0000-4000-8000-000000000003" }, + ]); + let sealed = BaseIndex::from_compact(&compact).unwrap().to_bytes(); + let body = &sealed[..sealed.len() - 16]; + // xorshift64*, so the sweep is the same on every run. + let mut state = 0xBA5E_1DE0_0000_0001_u64; + let mut next = move || { + state ^= state >> 12; + state ^= state << 25; + state ^= state >> 27; + state.wrapping_mul(0x2545_F491_4F6C_DD1D) + }; + for _ in 0..4000 { + let mut mutated = body.to_vec(); + let i = usize::try_from(next() % mutated.len() as u64).expect("below a usize"); + match next() % 3 { + 0 => mutated[i] ^= 1u8 << (next() % 8), + 1 => mutated.truncate(i), + _ => mutated[i] = next().to_le_bytes()[0], + } + let sum = Uuid::new_v5(&index_ns(), &mutated); + mutated.extend_from_slice(sum.as_bytes()); + // Err is fine; panicking is not. A survivor must also + // round-trip, since it is by then a well-formed index. + if let Ok(index) = BaseIndex::from_bytes(&mutated) { + assert_eq!( + BaseIndex::from_bytes(&index.to_bytes()).unwrap(), + index, + "a loaded index re-seals to itself" + ); + } + } + } + + #[test] + fn crafted_type_codes_out_of_range_are_refused() { + let package = u64::from(crate::type_code("Package").unwrap()); + assert!( + BaseIndex::from_bytes(&crafted(package)).is_ok(), + "the crafting reaches the code, not the checksum" + ); + for code in [ + table_set(false).len() as u64, + u64::from(u16::MAX), + 70_000, + u64::MAX, + ] { + let err = BaseIndex::from_bytes(&crafted(code)) + .unwrap_err() + .to_string(); + assert!(err.contains("type code"), "code {code}: {err}"); + } + } +} diff --git a/crates/sysmlv2-cbor/src/lib.rs b/crates/sysmlv2-cbor/src/lib.rs index aadad66..3f474f5 100644 --- a/crates/sysmlv2-cbor/src/lib.rs +++ b/crates/sysmlv2-cbor/src/lib.rs @@ -11,6 +11,13 @@ //! canonical field/type/table ordering) and plain RFC 8949 — any //! off-the-shelf CBOR reader can walk it. +// Wire integers are 64-bit and `usize` is not: a payload read on a +// 32-bit target (the wasm hosts) must refuse an out-of-range index +// rather than wrap into a different one. Every narrowing cast in the +// crate is therefore either a checked conversion or carries its own +// justification. +#![warn(clippy::cast_possible_truncation)] + mod canonical; mod cbor; mod decode; @@ -33,9 +40,10 @@ pub use delta::{ }; pub use describe::describe; pub use encode::{ - FLAG_ELIDE_IDS, FLAG_FULL_FORM, FLAG_IMPLIED_OWNERS, FLAG_UNIT_PATHS, to_compact_cbor, - to_compact_cbor_elided, to_compact_cbor_elided_with_units, to_compact_cbor_with_units, - to_full_cbor, to_full_cbor_with_units, + FLAG_ELIDE_IDS, FLAG_EXPLICIT_IDS, FLAG_FULL_FORM, FLAG_IMPLIED_OWNERS, FLAG_UNIT_PATHS, + to_compact_cbor, to_compact_cbor_elided, to_compact_cbor_elided_with_units, + to_compact_cbor_with_units, to_compact_cbor_with_units_explicit, to_full_cbor, + to_full_cbor_with_units, }; pub use sysmlv2_model::cbor_tables as tables; @@ -69,49 +77,103 @@ pub const ID_SCHEME_VERSION: u8 = 1; pub(crate) fn strip_magic(bytes: &[u8]) -> Result<&[u8], Error> { match bytes.strip_prefix(MAGIC) { Some(rest) => Ok(rest), - None => Err(Error::new( + None => Err(Error::of( + ErrorKind::MissingMagic, "not an s2c payload (missing the RFC 9277 magic — tag 55799 \ wrapping tag 0x24533243, \"$S2C\")", )), } } +/// What a codec error *is*, for callers that act on the classes +/// differently — refetch a base, fetch a resolver, route to another +/// entry point, or give up on the bytes. The [`fmt::Display`] text +/// stays the explanation; this is the decision. +/// +/// Non-exhaustive: later wire generations will distinguish more. +#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] +#[non_exhaustive] +pub enum ErrorKind { + /// The bytes do not open with the payload magic — not an s2c + /// payload at all. + MissingMagic, + /// A version axis (wire layout, generated tables, id-derivation + /// scheme, base-index or resolver artifact) this build does not + /// implement. + UnsupportedVersion, + /// An id-elided payload reached an entry point that carries no + /// name resolver. + NeedsResolver, + /// A well-formed payload of the wrong kind for this entry point + /// (a delta to a snapshot decoder, a full form to the compact + /// one, and so on) — the message names the one to use. + WrongForm, + /// The held base is not the one the delta names. + BaseDigestMismatch, + /// The payload ends inside an item. + Truncated, + /// Anything else refused on the way in or out: a structure the + /// wire format does not allow, or a `Value` outside the compact + /// interchange shape. + Malformed, +} + /// Codec error: malformed input on decode, or a `Value` outside the -/// compact interchange shape on encode. +/// compact interchange shape on encode. [`Error::kind`] classifies it; +/// the [`fmt::Display`] text explains it. #[derive(Debug)] -pub struct Error(String); +pub struct Error { + kind: ErrorKind, + message: String, +} impl Error { - fn new(msg: impl Into) -> Self { - Self(msg.into()) + fn new(message: impl Into) -> Self { + Self::of(ErrorKind::Malformed, message) + } + + fn of(kind: ErrorKind, message: impl Into) -> Self { + Self { + kind, + message: message.into(), + } + } + + /// The class this error falls in. + #[must_use] + pub fn kind(&self) -> ErrorKind { + self.kind } } impl fmt::Display for Error { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - f.write_str(&self.0) + f.write_str(&self.message) } } impl std::error::Error for Error {} /// Wire type code for a metaclass name, if it is a concrete metaclass. +#[must_use] pub fn type_code(name: &str) -> Option { tables::METACLASS_FIELDS .binary_search_by(|(n, _)| n.cmp(&name)) .ok() - .map(|i| i as u16) + .and_then(|i| u16::try_from(i).ok()) } /// Field table for a wire type code. +#[must_use] pub fn fields_of(code: u16) -> Option<&'static [tables::CborField]> { tables::METACLASS_FIELDS.get(code as usize).map(|(_, f)| *f) } /// Wire ordinal of `prop` within a field table. +#[must_use] pub fn ordinal(fields: &'static [tables::CborField], prop: &str) -> Option { fields .binary_search_by(|(n, _, _, _)| n.cmp(&prop)) .ok() - .map(|i| i as u8) + .and_then(|i| u8::try_from(i).ok()) } diff --git a/crates/sysmlv2-cbor/src/resolver.rs b/crates/sysmlv2-cbor/src/resolver.rs index 6ddbf0d..9eb26a2 100644 --- a/crates/sysmlv2-cbor/src/resolver.rs +++ b/crates/sysmlv2-cbor/src/resolver.rs @@ -22,7 +22,7 @@ //! library_state_digest`] against a store's pinned stdlib commit //! digest is the caller's binding check. -use crate::Error; +use crate::{Error, ErrorKind}; use serde_json::Value; use std::collections::{HashMap, HashSet}; @@ -57,9 +57,13 @@ impl StdlibResolver { } let version = v.get("formatVersion").and_then(Value::as_u64).unwrap_or(0); if version != 1 { - return Err(Error::new(format!( - "resolver artifact format version {version} unsupported (this build carries 1)" - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "resolver artifact format version {version} unsupported \ + (this build carries 1)" + ), + )); } let uint = |key: &str| -> Result { v.get(key) @@ -111,12 +115,22 @@ impl StdlibResolver { .collect() }) .unwrap_or_default(); + // Each version axis is compared against this build's, so a + // value that does not fit its width must refuse rather than + // narrow into a version it is not (65537 is not tables + // version 1). + let tables_version = uint("tablesVersion")?; + let scheme_version = uint("schemeVersion")?; + let units = uint("units")?; Ok(Self { toolkit: str_field("toolkit")?, - tables_version: uint("tablesVersion")? as u16, - scheme_version: uint("schemeVersion")? as u8, + tables_version: u16::try_from(tables_version) + .map_err(|_| Error::new("resolver artifact `tablesVersion` is out of range"))?, + scheme_version: u8::try_from(scheme_version) + .map_err(|_| Error::new("resolver artifact `schemeVersion` is out of range"))?, library_state_digest: str_field("libraryStateDigest")?, - units: uint("units")? as usize, + units: usize::try_from(units) + .map_err(|_| Error::new("resolver artifact `units` is out of range"))?, forward, inverse, collisions, @@ -127,18 +141,24 @@ impl StdlibResolver { /// this build decodes with — same doctrine as the wire header. pub fn assert_compatible(&self) -> Result<(), Error> { if self.tables_version != crate::tables::CBOR_TABLES_VERSION { - return Err(Error::new(format!( - "resolver artifact tables version {} unsupported (this build carries {})", - self.tables_version, - crate::tables::CBOR_TABLES_VERSION - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "resolver artifact tables version {} unsupported (this build carries {})", + self.tables_version, + crate::tables::CBOR_TABLES_VERSION + ), + )); } if self.scheme_version != crate::ID_SCHEME_VERSION { - return Err(Error::new(format!( - "resolver artifact id-scheme version {} unsupported (this build carries {})", - self.scheme_version, - crate::ID_SCHEME_VERSION - ))); + return Err(Error::of( + ErrorKind::UnsupportedVersion, + format!( + "resolver artifact id-scheme version {} unsupported (this build carries {})", + self.scheme_version, + crate::ID_SCHEME_VERSION + ), + )); } Ok(()) } @@ -146,6 +166,7 @@ impl StdlibResolver { /// The last effective-name segment for a library id — the exact /// signature id-elided decode wants. Pass as /// `&|s| resolver.external_name(s)`. + #[must_use] pub fn external_name(&self, id: &str) -> Option { self.forward.get(id).and_then(|s| s.last()).cloned() } @@ -163,26 +184,32 @@ impl StdlibResolver { /// Whether a qualified name was excluded from the inverse because /// distinct elements claim it. + #[must_use] pub fn is_collision(&self, qname: &str) -> bool { self.collisions.contains(qname) } + #[must_use] pub fn library_state_digest(&self) -> &str { &self.library_state_digest } + #[must_use] pub fn toolkit(&self) -> &str { &self.toolkit } + #[must_use] pub fn units(&self) -> usize { self.units } + #[must_use] pub fn forward_len(&self) -> usize { self.forward.len() } + #[must_use] pub fn inverse_len(&self) -> usize { self.inverse.len() } diff --git a/crates/sysmlv2-cbor/tests/delta.rs b/crates/sysmlv2-cbor/tests/delta.rs index 9d5d36d..e6a061f 100644 --- a/crates/sysmlv2-cbor/tests/delta.rs +++ b/crates/sysmlv2-cbor/tests/delta.rs @@ -5,6 +5,7 @@ //! documented report; the empty base is a recognizable constant. use serde_json::Value; +use std::fmt::Write as _; use sysmlv2_cbor::{ DeltaOptions, apply_delta_cbor, apply_delta_cbor_lenient, delta_canonical, delta_compact_cbor, empty_base_digest, rebase_ids, state_digest, @@ -35,10 +36,7 @@ const TARGET_UNIT: &str = "package P { }"; fn opts(portable: bool) -> DeltaOptions { - DeltaOptions { - portable, - ..Default::default() - } + DeltaOptions::new().with_portable(portable) } #[test] @@ -91,6 +89,82 @@ fn canonicalization_is_emission_order_independent() { ); } +/// The canonical order is computed once, as a permutation, and then +/// either borrowed (digests, diffs) or moved through (apply). All three +/// must land on the identical array — including for a payload with +/// several roots, unreachable elements, and a shuffled emission order, +/// where the walk falls back to appending what it never visited. +#[test] +fn borrowed_and_applied_canonicalization_agree_on_a_ragged_payload() { + let id = |n: u8| format!("00000000-0000-4000-8000-0000000000{n:02x}"); + let pkg = |n: u8, owned: &[u8]| { + serde_json::json!({ + "@type": "Package", "@id": id(n), + "ownedRelationship": owned.iter().map(|&t| serde_json::json!({ "@id": id(t) })) + .collect::>(), + }) + }; + let membership = |n: u8, member: u8| { + serde_json::json!({ + "@type": "OwningMembership", "@id": id(n), + "ownedRelatedElement": [{ "@id": id(member) }], + "memberElement": { "@id": id(member) }, + }) + }; + // Two owning roots plus two elements nothing owns at all. + let model = Value::Array(vec![ + pkg(1, &[3]), + pkg(2, &[5]), + membership(3, 4), + pkg(4, &[]), + membership(5, 6), + pkg(6, &[]), + pkg(7, &[]), + pkg(8, &[]), + ]); + // The same payload with the owned elements emitted elsewhere; the + // roots keep their relative order, which is the one thing the + // canonical walk takes from emission order. + let shuffled = Value::Array(vec![ + pkg(1, &[3]), + membership(5, 6), + pkg(2, &[5]), + pkg(6, &[]), + membership(3, 4), + pkg(4, &[]), + pkg(7, &[]), + pkg(8, &[]), + ]); + let ids_of = |v: &Value| -> Vec { + v.as_array() + .unwrap() + .iter() + .map(|e| e["@id"].as_str().unwrap().to_owned()) + .collect() + }; + let want = delta_canonical(&model).unwrap(); + assert_eq!( + ids_of(&want), + [1, 3, 4, 2, 5, 6, 7, 8].map(id).to_vec(), + "ownership preorder from each root, then what nothing owns" + ); + assert_eq!(delta_canonical(&shuffled).unwrap(), want); + assert_eq!( + state_digest(&model).unwrap(), + state_digest(&shuffled).unwrap() + ); + // The applied state canonicalizes through the owned path. + let empty = Value::Array(Vec::new()); + for portable in [false, true] { + let bytes = delta_compact_cbor(&empty, &model, &opts(portable)).unwrap(); + assert_eq!( + apply_delta_cbor(&bytes, &empty).unwrap(), + want, + "portable={portable}" + ); + } +} + #[test] fn strict_refuses_a_divergent_base_hard() { let base = compact_of(&[("m.sysml", BASE_UNIT)]); @@ -463,7 +537,7 @@ fn patched_updates_make_big_owner_inserts_constant_size() { let body = |n: usize, extra: bool| { let mut s = String::from("package P {\n"); for k in 0..n { - s.push_str(&format!(" part def D{k};\n")); + writeln!(s, " part def D{k};").unwrap(); } if extra { s.push_str(" attribute q;\n"); @@ -607,10 +681,7 @@ fn units_ride_the_delta_and_apply_returns_them() { let bytes = delta_compact_cbor( &base, &target, - &DeltaOptions { - units: target_units.clone(), - ..Default::default() - }, + &DeltaOptions::new().with_units(target_units.clone()), ) .unwrap(); let (got, report) = sysmlv2_cbor::apply_delta_cbor_report(&bytes, &base).unwrap(); @@ -652,10 +723,7 @@ fn rename_only_change_is_a_legal_delta() { let bytes = delta_compact_cbor( &base, &target, - &DeltaOptions { - units: target_units, - ..Default::default() - }, + &DeltaOptions::new().with_units(target_units), ) .unwrap(); let d = sysmlv2_cbor::describe(&bytes).unwrap(); @@ -683,11 +751,7 @@ fn units_refuse_portable() { let err = delta_compact_cbor( &base, &target, - &DeltaOptions { - portable: true, - units, - ..Default::default() - }, + &DeltaOptions::new().with_portable(true).with_units(units), ) .unwrap_err(); assert!(err.to_string().contains("strict deltas only"), "{err}"); @@ -708,10 +772,7 @@ fn units_compose_with_elision() { let bytes = sysmlv2_cbor::delta_compact_cbor_elided( &base, &target, - &DeltaOptions { - units: target_units.clone(), - ..Default::default() - }, + &DeltaOptions::new().with_units(target_units), &|_| None, ) .unwrap(); @@ -922,7 +983,7 @@ mod implied_owner_deltas { const M: &str = "00000000-0000-4000-8000-00000000000e"; const KID: &str = "00000000-0000-4000-8000-00000000000f"; - fn pkg(id: &str, name: &str, owned: &[&str], owner: Value) -> Value { + fn pkg(id: &str, name: &str, owned: &[&str], owner: &Value) -> Value { json!({ "@type": "Package", "@id": id, "elementId": id, "declaredName": name, "isImpliedIncluded": false, @@ -946,10 +1007,10 @@ mod implied_owner_deltas { fn state(owner: &str) -> Value { Value::Array(vec![ - pkg(A, "A", if owner == A { &[M] } else { &[] }, Value::Null), - pkg(B, "B", if owner == B { &[M] } else { &[] }, Value::Null), + pkg(A, "A", if owner == A { &[M] } else { &[] }, &Value::Null), + pkg(B, "B", if owner == B { &[M] } else { &[] }, &Value::Null), membership(owner), - pkg(KID, "Kid", &[], json!({"@id": M})), + pkg(KID, "Kid", &[], &json!({"@id": M})), ]) } @@ -994,7 +1055,7 @@ mod implied_owner_deltas { // A is owned by M per the forward list but carries no // backpointer keys at all (absent-key exceptions), and M is // owned by nothing while claiming B. - let target = Value::Array(vec![bare(A, &[]), inconsistent.clone()]); + let target = Value::Array(vec![bare(A, &[]), inconsistent]); let base = Value::Array(Vec::new()); let bytes = delta_compact_cbor(&base, &target, &opts(false)).unwrap(); let got = apply_delta_cbor(&bytes, &base).unwrap(); diff --git a/crates/sysmlv2-cbor/tests/describe.rs b/crates/sysmlv2-cbor/tests/describe.rs index 0a01376..a0bcf9e 100644 --- a/crates/sysmlv2-cbor/tests/describe.rs +++ b/crates/sysmlv2-cbor/tests/describe.rs @@ -55,11 +55,9 @@ fn delta_summaries_expose_digests_claims_and_changes() { let base = compact_of(BASE); let target = compact_of(TARGET); for portable in [false, true] { - let opts = DeltaOptions { - portable, - claims: vec![(1, sysmlv2_cbor::Claim::Id(uuid::Uuid::nil()))], - ..Default::default() - }; + let opts = DeltaOptions::new() + .with_portable(portable) + .with_claims(vec![(1, sysmlv2_cbor::Claim::Id(uuid::Uuid::nil()))]); let bytes = delta_compact_cbor(&base, &target, &opts).unwrap(); let d = describe(&bytes).unwrap(); assert_eq!(d["form"], "delta"); @@ -107,3 +105,111 @@ fn mutated_payloads_never_panic_under_describe() { } } } + +// ---- hand-assembled payloads ---- + +/// A definite-length CBOR head (major type + argument, shortest form). +fn head(out: &mut Vec, major: u8, arg: u64) { + let m = major << 5; + if let Ok(b) = u8::try_from(arg) { + if b < 24 { + out.push(m | b); + } else { + out.extend_from_slice(&[m | 24, b]); + } + } else if let Ok(s) = u16::try_from(arg) { + out.push(m | 25); + out.extend_from_slice(&s.to_be_bytes()); + } else if let Ok(w) = u32::try_from(arg) { + out.push(m | 26); + out.extend_from_slice(&w.to_be_bytes()); + } else { + out.push(m | 27); + out.extend_from_slice(&arg.to_be_bytes()); + } +} + +/// A strict delta over a one-element base whose single change record +/// is a field patch with `patch_entries` map entries declared; the +/// caller appends the entries (if any) and the trailing sections. +fn strict_delta_with_patch_head(patch_entries: u64) -> Vec { + let mut b = sysmlv2_cbor::MAGIC.to_vec(); + head(&mut b, 4, 7); // array(7): header … owner exceptions + let header = (u64::from(sysmlv2_cbor::LAYOUT_VERSION) << 32) + | (u64::from(sysmlv2_cbor::tables::CBOR_TABLES_VERSION) << 16) + | (u64::from(sysmlv2_cbor::ID_SCHEME_VERSION) << 8) + | u64::from(sysmlv2_cbor::FLAG_DELTA | sysmlv2_cbor::FLAG_IMPLIED_OWNERS); + head(&mut b, 0, header); + head(&mut b, 4, 3); // base section + head(&mut b, 2, 16); + b.extend_from_slice(&[0; 16]); + head(&mut b, 2, 16); + b.extend_from_slice(&[0; 16]); + head(&mut b, 5, 0); // claims + head(&mut b, 0, 1); // base element count + head(&mut b, 4, 0); // externals + head(&mut b, 4, 0); // created ids + head(&mut b, 4, 1); // one change record + head(&mut b, 4, 2); + head(&mut b, 0, 0); // target: base index 0 + head(&mut b, 5, patch_entries); // the patch map head + b +} + +#[test] +fn patch_map_headers_are_gated_against_the_payload() { + // A well-formed patch (ordinal 0 → unset) describes as one patched + // update, proving the assembly reaches the patch branch. + let mut ok = strict_delta_with_patch_head(1); + head(&mut ok, 0, 0); + head(&mut ok, 4, 2); + head(&mut ok, 0, 1); // OP_UNSET + ok.push(0xF6); // null + head(&mut ok, 5, 0); // owner exceptions + let d = describe(&ok).unwrap(); + assert_eq!(d["delta"]["patchedUpdates"], 1); + assert_eq!(d["delta"]["changes"]["updates"], 1); + // A patch map claiming 2^63 entries must be an error, never an + // overflow while sizing the skip. Which error depends on the + // target's pointer width: where a length does not fit a `usize` the + // reader refuses it as a length before the payload gate sees it, so + // both spellings are the refusal this pins. + for claimed in [1u64 << 63, u64::MAX, 1 << 32, 1 << 20] { + let mut bad = strict_delta_with_patch_head(claimed); + head(&mut bad, 5, 0); + let err = describe(&bad).unwrap_err().to_string(); + assert!( + err.contains("longer than payload") || err.contains("length overflow"), + "{claimed}: {err}" + ); + } +} + +/// Index-keyed sections must be strictly ascending, and inspection +/// holds the same rule the decoders do — it used to walk the owner and +/// unit maps without looking at their keys at all. +#[test] +fn descending_section_indices_are_refused() { + let mut ok = strict_delta_with_patch_head(1); + head(&mut ok, 0, 0); // ordinal 0 + head(&mut ok, 4, 2); + head(&mut ok, 0, 1); // OP_UNSET + ok.push(0xF6); // null + // Two owner-exception entries whose keys ascend: accepted. + let mut good = ok.clone(); + head(&mut good, 5, 2); + for key in [0u64, 1] { + head(&mut good, 0, key); + head(&mut good, 0, 1); // bits + } + assert_eq!(describe(&good).unwrap()["delta"]["ownerExceptions"], 2); + // The same two entries, descending: refused. + let mut bad = ok; + head(&mut bad, 5, 2); + for key in [1u64, 0] { + head(&mut bad, 0, key); + head(&mut bad, 0, 1); + } + let err = describe(&bad).unwrap_err().to_string(); + assert!(err.contains("not ascending"), "{err}"); +} diff --git a/crates/sysmlv2-cbor/tests/elide.rs b/crates/sysmlv2-cbor/tests/elide.rs index 34d189e..e602b65 100644 --- a/crates/sysmlv2-cbor/tests/elide.rs +++ b/crates/sysmlv2-cbor/tests/elide.rs @@ -97,7 +97,7 @@ fn foreign_ids_land_in_exceptions_and_still_round_trip() { .enumerate() .take(40) { - if i % 3 == 0 { + if i.is_multiple_of(3) { let foreign = format!("{:08x}-1234-4abc-8def-{:012x}", i, i * 7 + 1); e["@id"] = Value::String(foreign.clone()); e["elementId"] = Value::String(foreign); diff --git a/crates/sysmlv2-cbor/tests/fuzz.rs b/crates/sysmlv2-cbor/tests/fuzz.rs index 523bf89..fc5a7e3 100644 --- a/crates/sysmlv2-cbor/tests/fuzz.rs +++ b/crates/sysmlv2-cbor/tests/fuzz.rs @@ -147,24 +147,40 @@ fn random_well_typed_models_round_trip() { } } +/// One mutation of a payload: flip a bit, cut it short, or overwrite a +/// byte outright. +fn mutate(rng: &mut Rng, bytes: &[u8]) -> Vec { + let mut out = bytes.to_vec(); + if out.is_empty() { + return out; + } + match rng.below(3) { + 0 => { + let i = rng.below(out.len()); + out[i] ^= 1 << rng.below(8); + } + 1 => out.truncate(rng.below(out.len())), + _ => { + let i = rng.below(out.len()); + out[i] = rng.next() as u8; + } + } + out +} + +/// Arbitrary bytes of arbitrary length. +fn noise(rng: &mut Rng) -> Vec { + let len = rng.below(200); + (0..len).map(|_| rng.next() as u8).collect() +} + #[test] fn mutated_payloads_never_panic() { let mut rng = Rng(0xDEAD_BEEF_0BAD_CAFE); let base = to_compact_cbor(&random_model(&mut Rng(42))).unwrap(); for _ in 0..4000 { - let mut bytes = base.clone(); - match rng.below(3) { - 0 => { - let i = rng.below(bytes.len()); - bytes[i] ^= 1 << rng.below(8); - } - 1 => bytes.truncate(rng.below(bytes.len())), - _ => { - let i = rng.below(bytes.len()); - bytes[i] = rng.next() as u8; - } - } - let _ = from_compact_cbor(&bytes); // Err is fine; panicking is not + // Err is fine; panicking is not. + let _ = from_compact_cbor(&mutate(&mut rng, &base)); } } @@ -172,9 +188,7 @@ fn mutated_payloads_never_panic() { fn arbitrary_bytes_never_panic() { let mut rng = Rng(0x0123_4567_89AB_CDEF); for _ in 0..4000 { - let len = rng.below(200); - let bytes: Vec = (0..len).map(|_| rng.next() as u8).collect(); - let _ = from_compact_cbor(&bytes); + let _ = from_compact_cbor(&noise(&mut rng)); } } @@ -184,18 +198,208 @@ fn mutated_elided_payloads_never_panic() { let model = random_model(&mut Rng(7)); let base = sysmlv2_cbor::to_compact_cbor_elided(&model, &|_| None).unwrap(); for _ in 0..4000 { - let mut bytes = base.clone(); - match rng.below(3) { - 0 => { - let i = rng.below(bytes.len()); - bytes[i] ^= 1 << rng.below(8); - } - 1 => bytes.truncate(rng.below(bytes.len())), - _ => { - let i = rng.below(bytes.len()); - bytes[i] = rng.next() as u8; - } - } + let bytes = mutate(&mut rng, &base); let _ = sysmlv2_cbor::from_compact_cbor_elided(&bytes, &|_| None); } } + +#[test] +fn mutated_full_form_payloads_never_panic() { + let mut rng = Rng(0xF011_F011_0000_0001); + let base = sysmlv2_cbor::to_full_cbor(&random_model(&mut Rng(11))).unwrap(); + for _ in 0..4000 { + let _ = sysmlv2_cbor::from_full_cbor(&mutate(&mut rng, &base)); + let _ = sysmlv2_cbor::from_full_cbor(&noise(&mut rng)); + } +} + +/// A base and a target that differ: the target drops one element and +/// adds another, so the delta carries creates, deletes and updates. +fn delta_fixture(seed: u64) -> (Value, Value) { + let base = random_model(&mut Rng(seed)); + let mut target = base.as_array().unwrap().clone(); + target.pop(); + let extra = random_model(&mut Rng(seed ^ 0xFFFF)); + target.extend(extra.as_array().unwrap().iter().cloned()); + // Re-derived ids can collide across the two draws; keep the first. + let mut seen = std::collections::HashSet::new(); + target.retain(|e| seen.insert(e["@id"].as_str().unwrap().to_owned())); + (base, Value::Array(target)) +} + +#[test] +fn mutated_deltas_never_panic_on_apply() { + use sysmlv2_cbor::{ + DeltaOptions, apply_delta_cbor, apply_delta_cbor_lenient, apply_delta_cbor_report, + }; + let mut rng = Rng(0xDE17_A000_0000_0001); + let (base, target) = delta_fixture(23); + for portable in [false, true] { + let opts = DeltaOptions::new().with_portable(portable); + let delta = sysmlv2_cbor::delta_compact_cbor(&base, &target, &opts).unwrap(); + // The unmutated delta applies cleanly — the fixture is a real + // delta, not a payload every mutation would reject anyway. + assert!( + apply_delta_cbor(&delta, &base).is_ok(), + "portable={portable}" + ); + for _ in 0..4000 { + let bytes = mutate(&mut rng, &delta); + let _ = apply_delta_cbor(&bytes, &base); + let _ = apply_delta_cbor_report(&bytes, &base); + let _ = apply_delta_cbor_lenient(&bytes, &base); + let _ = apply_delta_cbor(&noise(&mut rng), &base); + } + } +} + +#[test] +fn mutated_and_arbitrary_bytes_never_panic_under_describe() { + let mut rng = Rng(0xDE5C_21BE_0000_0001); + let (base, target) = delta_fixture(31); + let forms = [ + to_compact_cbor(&base).unwrap(), + sysmlv2_cbor::to_full_cbor(&base).unwrap(), + sysmlv2_cbor::to_compact_cbor_elided(&base, &|_| None).unwrap(), + sysmlv2_cbor::delta_compact_cbor(&base, &target, &Default::default()).unwrap(), + ]; + for form in &forms { + for _ in 0..4000 { + let _ = sysmlv2_cbor::describe(&mutate(&mut rng, form)); + let _ = sysmlv2_cbor::describe(&noise(&mut rng)); + } + } +} + +/// A mutated base-index artifact dies at its checksum, so these +/// iterations pin the seal, not the reader behind it: the body's own +/// sweep re-seals what it mutates and lives beside the reader. The delta +/// halves below are not sealed and do reach resolution. +#[test] +fn mutated_deltas_and_sealed_artifacts_never_panic_on_resolution() { + use sysmlv2_cbor::index::{BaseIndex, resolve_portable_delta, resolve_strict_delta}; + let mut rng = Rng(0x10DE_C0DE_0000_0001); + let (base, target) = delta_fixture(47); + let index = BaseIndex::from_compact(&base).unwrap(); + let artifact = index.to_bytes(); + let strict = sysmlv2_cbor::delta_compact_cbor(&base, &target, &Default::default()).unwrap(); + let portable = sysmlv2_cbor::delta_compact_cbor( + &base, + &target, + &sysmlv2_cbor::DeltaOptions::new().with_portable(true), + ) + .unwrap(); + // The unmutated inputs resolve, so the loop below is mutating + // something that otherwise works. + assert!(resolve_strict_delta(&strict, &index).is_ok()); + assert!(resolve_portable_delta(&portable).is_ok()); + for _ in 0..4000 { + let _ = BaseIndex::from_bytes(&mutate(&mut rng, &artifact)); + let _ = BaseIndex::from_bytes(&noise(&mut rng)); + let _ = resolve_strict_delta(&mutate(&mut rng, &strict), &index); + let _ = resolve_portable_delta(&mutate(&mut rng, &portable)); + let _ = resolve_strict_delta(&noise(&mut rng), &index); + let _ = resolve_portable_delta(&noise(&mut rng)); + } +} + +/// One structural mutation of a well-typed model: the shapes a +/// malformed producer emits — wrong value kinds, non-object +/// references, nulls, missing `@id`/`@type`, arrays where scalars +/// belong. +fn mutate_model(rng: &mut Rng, model: &Value) -> Value { + let mut arr = model.as_array().unwrap().clone(); + if arr.is_empty() { + return Value::Array(arr); + } + let at = rng.below(arr.len()); + match rng.below(9) { + 0 => arr[at] = Value::String(short_name(rng)), + 1 => arr[at] = Value::Array(vec![arr[at].clone()]), + 2 => { + arr[at].as_object_mut().unwrap().remove("@id"); + } + 3 => { + arr[at].as_object_mut().unwrap().remove("@type"); + } + 4 => { + arr[at]["@type"] = Value::String(short_name(rng)); + } + 5 => { + arr[at][short_name(rng)] = Value::Bool(true); + } + 6 => return Value::Object(serde_json::Map::new()), + _ => { + // Replace one property's value with a foreign shape. + let obj = arr[at].as_object_mut().unwrap(); + let keys: Vec = obj.keys().cloned().collect(); + let key = keys[rng.below(keys.len())].clone(); + obj.insert( + key, + match rng.below(6) { + 0 => Value::Null, + 1 => Value::Bool(rng.chance(50)), + 2 => json!(rng.next() >> 8), + 3 => Value::String(short_name(rng)), + 4 => json!([short_name(rng)]), + _ => json!({ "@ref": rng.next() }), + }, + ); + } + } + Value::Array(arr) +} + +#[test] +fn structurally_mutated_models_are_errors_not_panics() { + use sysmlv2_cbor::{ + DeltaOptions, delta_compact_cbor, state_digest, to_compact_cbor_elided, to_full_cbor, + }; + let mut rng = Rng(0xE4C0_DE00_0000_0001); + let well_typed = random_model(&mut Rng(101)); + let opts = DeltaOptions::new(); + for _ in 0..4000 { + let model = mutate_model(&mut rng, &well_typed); + // Err or Ok, never a panic, on every encoding entry point. + let _ = to_compact_cbor(&model); + let _ = to_full_cbor(&model); + let _ = state_digest(&model); + let _ = to_compact_cbor_elided(&model, &|_| None); + let _ = delta_compact_cbor(&well_typed, &model, &opts); + let _ = delta_compact_cbor(&model, &well_typed, &opts); + let _ = sysmlv2_cbor::graph_normalize(&model); + let _ = sysmlv2_cbor::index::BaseIndex::from_compact(&model); + } +} + +/// Reference-list items and single references that are not +/// `{"@id": …}` / `{"@ref": …}` objects are encoder errors on every +/// entry point that encodes — never a panic. +#[test] +fn malformed_references_are_errors_not_panics() { + use sysmlv2_cbor::{delta_compact_cbor, state_digest, to_compact_cbor_elided}; + let id = "00000000-0000-4000-8000-000000000001"; + let empty = json!([]); + for item in [ + json!("x"), + Value::Null, + json!(1), + json!([]), + json!({}), + json!({ "@id": 1 }), + json!({ "@ref": null }), + json!({ "@id": id, "@ref": "x" }), + ] { + let model = json!([{ "@type": "Package", "@id": id, "ownedRelationship": [item] }]); + assert!(to_compact_cbor(&model).is_err(), "{item}"); + assert!(state_digest(&model).is_err(), "{item}"); + assert!(to_compact_cbor_elided(&model, &|_| None).is_err(), "{item}"); + let opts = sysmlv2_cbor::DeltaOptions::default(); + assert!(delta_compact_cbor(&empty, &model, &opts).is_err(), "{item}"); + assert!(delta_compact_cbor(&model, &empty, &opts).is_err(), "{item}"); + } + for member in [json!("x"), json!(1), json!([]), json!({})] { + let model = json!([{ "@type": "OwningMembership", "@id": id, "memberElement": member }]); + assert!(to_compact_cbor(&model).is_err(), "{member}"); + } +} diff --git a/crates/sysmlv2-cbor/tests/resolver.rs b/crates/sysmlv2-cbor/tests/resolver.rs index 7dd0329..d9c5bc3 100644 --- a/crates/sysmlv2-cbor/tests/resolver.rs +++ b/crates/sysmlv2-cbor/tests/resolver.rs @@ -115,6 +115,42 @@ fn collision_and_version_policies_are_loud() { assert!(StdlibResolver::from_value(&v).is_err()); } +/// A version axis wider than the field it names is refused outright. +/// It used to be narrowed instead, so an artifact declaring tables +/// version 65537 passed as version 1 and cleared the compatibility +/// gate it should have failed. +#[test] +fn oversized_version_axes_never_narrow_into_a_supported_one() { + let artifact = |key: &str, value: u64| { + let mut v = serde_json::json!({ + "format": "sysmlv2-stdlib-resolver", "formatVersion": 1, + "toolkit": "t", "tablesVersion": sysmlv2_cbor::tables::CBOR_TABLES_VERSION, + "schemeVersion": sysmlv2_cbor::ID_SCHEME_VERSION, + "libraryStateDigest": "d", "units": 1, + "forward": {}, "inverse": {}, + }); + v[key] = serde_json::json!(value); + v + }; + assert!(StdlibResolver::from_value(&artifact("tablesVersion", 1)).is_ok()); + for (key, value) in [ + ( + "tablesVersion", + u64::from(sysmlv2_cbor::tables::CBOR_TABLES_VERSION) + (1 << 16), + ), + ( + "schemeVersion", + u64::from(sysmlv2_cbor::ID_SCHEME_VERSION) + (1 << 8), + ), + ] { + let err = StdlibResolver::from_value(&artifact(key, value)) + .err() + .map(|e| e.to_string()) + .unwrap_or_else(|| panic!("{key} = {value} loaded")); + assert!(err.contains(key) && err.contains("out of range"), "{err}"); + } +} + #[test] fn generated_collisions_never_leak_into_the_inverse() { let Some(model) = library_model() else { return }; diff --git a/crates/sysmlv2-cbor/tests/roundtrip.rs b/crates/sysmlv2-cbor/tests/roundtrip.rs index fd896b7..d952a1d 100644 --- a/crates/sysmlv2-cbor/tests/roundtrip.rs +++ b/crates/sysmlv2-cbor/tests/roundtrip.rs @@ -120,7 +120,7 @@ fn decode_rejects_malformed_payloads() { odd_scheme[16] = 0xFF; assert!(from_compact_cbor(&odd_scheme).is_ok()); // The id-elision flag needs the resolver-aware decoder. - let mut elided = good.clone(); + let mut elided = good; elided[17] |= FLAG_ELIDE_IDS; let err = from_compact_cbor(&elided).unwrap_err().to_string(); assert!( @@ -240,7 +240,7 @@ fn implied_owners_round_trip_every_deviation() { let wrong = json!({"@id": "22222222-2222-4222-8222-222222222222"}); let by_ref = json!({"@ref": "Some::Path"}); for (name, owner_state) in [ - ("consistent-derived", consistent.clone()), + ("consistent-derived", consistent), ("inconsistent-value", wrong), ("explicit-null-under-owner", Value::Null), ("ref-spelled", by_ref), @@ -291,3 +291,64 @@ fn digest_space_is_pinned_across_wire_revisions() { "4d2d226c-0d83-5bd7-81f9-7b366288ecbe", ); } + +/// Callers act on the error classes differently — refetch a base, +/// fetch a resolver, route to another entry point, give up on the +/// bytes — so each class is reachable and says which it is. The +/// `Display` text stays the explanation. +#[test] +fn errors_classify_what_the_caller_should_do() { + use sysmlv2_cbor::{ + DeltaOptions, ErrorKind, apply_delta_cbor, delta_compact_cbor, from_full_cbor, + to_compact_cbor_elided, + }; + let model = |name: &str| { + let parsed = parse_source(&format!("package {name} {{ part def V; }}")); + to_compact_json(&parsed.unit) + }; + let one = model("P"); + let other = model("Q"); + let payload = to_compact_cbor(&one).unwrap(); + + let kind = |e: sysmlv2_cbor::Error| e.kind(); + assert_eq!( + kind(from_compact_cbor(b"not an s2c payload at all").unwrap_err()), + ErrorKind::MissingMagic + ); + // The header word sits right after the magic and the body's array + // head, spelled as a full-width uint: its fourth byte is the wire + // layout generation. + let mut wrong_layout = payload.clone(); + wrong_layout[13] = 9; + assert_eq!( + kind(from_compact_cbor(&wrong_layout).unwrap_err()), + ErrorKind::UnsupportedVersion + ); + let elided = to_compact_cbor_elided(&one, &|_| None).unwrap(); + assert_eq!( + kind(from_compact_cbor(&elided).unwrap_err()), + ErrorKind::NeedsResolver + ); + assert_eq!( + kind(from_full_cbor(&payload).unwrap_err()), + ErrorKind::WrongForm + ); + let delta = delta_compact_cbor(&one, &other, &DeltaOptions::default()).unwrap(); + assert_eq!( + kind(from_compact_cbor(&delta).unwrap_err()), + ErrorKind::WrongForm + ); + assert_eq!( + kind(apply_delta_cbor(&delta, &other).unwrap_err()), + ErrorKind::BaseDigestMismatch + ); + assert_eq!( + kind(from_compact_cbor(&payload[..payload.len() - 1]).unwrap_err()), + ErrorKind::Truncated + ); + let unknown = + json!([{ "@type": "NotAMetaclass", "@id": "00000000-0000-4000-8000-000000000001" }]); + let err = to_compact_cbor(&unknown).unwrap_err(); + assert!(err.to_string().contains("unknown @type"), "{err}"); + assert_eq!(kind(err), ErrorKind::Malformed); +} diff --git a/crates/sysmlv2-cbor/tests/tables.rs b/crates/sysmlv2-cbor/tests/tables.rs index c144412..ab3e5ca 100644 --- a/crates/sysmlv2-cbor/tests/tables.rs +++ b/crates/sysmlv2-cbor/tests/tables.rs @@ -7,8 +7,8 @@ use serde_json::Value; use std::fs; use std::path::PathBuf; use sysmlv2_cbor::tables::{ - CborField, ENUM_NAMES, ENUM_TABLES, K_BOOL, K_ELEMENT_ID, K_ENUM, K_LITERAL, K_REF, K_REF_LIST, - K_STR, K_STR_LIST, METACLASS_FIELDS, + CborField, ENUM_NAMES, ENUM_TABLES, FULL_METACLASS_FIELDS, K_BOOL, K_ELEMENT_ID, K_ENUM, + K_LITERAL, K_REF, K_REF_LIST, K_STR, K_STR_LIST, METACLASS_FIELDS, }; fn goldens_expected() -> PathBuf { @@ -84,6 +84,38 @@ fn tables_are_canonically_ordered() { } } +/// The wire spells a metaclass as a 16-bit code and a property as an +/// 8-bit ordinal, and the lookups convert into those widths rather than +/// truncating — so a table that outgrew either space would start +/// answering "unknown metaclass" / "not a compact-form property" for +/// real names. Hold both spaces here, on both table sets. +#[test] +fn tables_fit_the_wire_code_spaces() { + for (which, tables) in [ + ("compact", METACLASS_FIELDS), + ("full", FULL_METACLASS_FIELDS), + ] { + assert!( + u16::try_from(tables.len()).is_ok(), + "{which} metaclass table fits the 16-bit type-code space ({})", + tables.len() + ); + for (name, fields) in tables { + assert!( + u8::try_from(fields.len()).is_ok(), + "{which} {name}: {} fields fit the 8-bit ordinal space", + fields.len() + ); + } + } + let (last, _) = METACLASS_FIELDS[METACLASS_FIELDS.len() - 1]; + assert_eq!( + sysmlv2_cbor::type_code(last), + u16::try_from(METACLASS_FIELDS.len() - 1).ok(), + "the highest metaclass still answers its own code" + ); +} + #[test] fn tables_cover_the_golden_corpus() { let dir = goldens_expected(); diff --git a/crates/sysmlv2-cli/Cargo.toml b/crates/sysmlv2-cli/Cargo.toml index 46d228f..08fc42e 100644 --- a/crates/sysmlv2-cli/Cargo.toml +++ b/crates/sysmlv2-cli/Cargo.toml @@ -44,4 +44,4 @@ xattr = "1" [dev-dependencies] sysmlv2-testkit.workspace = true -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } diff --git a/crates/sysmlv2-cli/src/kpar.rs b/crates/sysmlv2-cli/src/kpar.rs index 07b81e1..59c9bb1 100644 --- a/crates/sysmlv2-cli/src/kpar.rs +++ b/crates/sysmlv2-cli/src/kpar.rs @@ -46,7 +46,7 @@ pub fn read(bytes: &[u8]) -> Result { meta = serde_json::from_slice(data) .map_err(|e| format!(".meta.json is not valid JSON: {e}"))?; } - n if n.ends_with(".sysml") || n.ends_with(".kerml") => { + n if crate::is_model_source(n) => { let source = String::from_utf8(data.clone()).map_err(|_| format!("`{n}` is not UTF-8"))?; units.push(KparUnit { @@ -82,55 +82,104 @@ pub fn read(bytes: &[u8]) -> Result { }) } +/// A little-endian field of `header`, which the caller has already +/// bounded: `at` is a fixed offset inside a fixed-size header, so the +/// slicing cannot fail. +fn u16_of(header: &[u8], at: usize) -> usize { + u16::from_le_bytes([header[at], header[at + 1]]) as usize +} + +fn u32_of(header: &[u8], at: usize) -> usize { + u32::from_le_bytes([header[at], header[at + 1], header[at + 2], header[at + 3]]) as usize +} + +/// Everything one archive may expand to. +/// +/// A project archive holds model sources; the largest real ones are a few +/// megabytes. The archive's own headers say how far each entry expands, +/// so they cannot also be the budget — a crafted directory can declare an +/// entry that inflates to far more than the file's own size suggests, and +/// can name it as many times as it has records. One ceiling over +/// everything the archive expands to bounds both. +const MAX_INFLATED: usize = 512 * 1024 * 1024; + +/// Every offset and length below comes from the archive itself, so none +/// of them is trusted: each header and each span is taken with a checked +/// addition and a bounds-checked slice, and an archive that points past +/// its own end is rejected with a message instead of an index panic. +/// The additions matter on a 32-bit target, where an offset near the top +/// of the `u32` field range would otherwise wrap and slip past a guard. fn zip_entries(bytes: &[u8]) -> Result)>, String> { + let mut inflated_total = 0usize; // End-of-central-directory: scan backwards for PK\x05\x06. let eocd = bytes .windows(4) .rposition(|w| w == b"PK\x05\x06") .ok_or("not a ZIP archive (no end-of-central-directory)")?; - let u16_at = |o: usize| -> usize { u16::from_le_bytes([bytes[o], bytes[o + 1]]) as usize }; - let u32_at = |o: usize| -> usize { - u32::from_le_bytes([bytes[o], bytes[o + 1], bytes[o + 2], bytes[o + 3]]) as usize - }; - if eocd + 22 > bytes.len() { - return Err("truncated end-of-central-directory".into()); - } - let count = u16_at(eocd + 10); - let mut off = u32_at(eocd + 16); + let end = bytes + .get(eocd..eocd + 22) + .ok_or("truncated end-of-central-directory")?; + let count = u16_of(end, 10); + let mut off = u32_of(end, 16); let mut out = Vec::new(); for _ in 0..count { - if off + 46 > bytes.len() || &bytes[off..off + 4] != b"PK\x01\x02" { - return Err("malformed central directory".into()); - } - let method = u16_at(off + 10); - let csize = u32_at(off + 20); - let usize_ = u32_at(off + 24); - let name_len = u16_at(off + 28); - let extra_len = u16_at(off + 30); - let comment_len = u16_at(off + 32); - let local_off = u32_at(off + 42); - let name = String::from_utf8_lossy(&bytes[off + 46..off + 46 + name_len]).into_owned(); + let header = off + .checked_add(46) + .and_then(|to| bytes.get(off..to)) + .filter(|h| h.starts_with(b"PK\x01\x02")) + .ok_or("malformed central directory")?; + let method = u16_of(header, 10); + let csize = u32_of(header, 20); + let declared = u32_of(header, 24); + let name_len = u16_of(header, 28); + let extra_len = u16_of(header, 30); + let comment_len = u16_of(header, 32); + let local_off = u32_of(header, 42); + let name_at = off + 46; + let name = name_at + .checked_add(name_len) + .and_then(|to| bytes.get(name_at..to)) + .map(|n| String::from_utf8_lossy(n).into_owned()) + .ok_or("malformed central directory")?; // Local header: skip its (possibly different) name/extra lengths. - if local_off + 30 > bytes.len() || &bytes[local_off..local_off + 4] != b"PK\x03\x04" { - return Err(format!("malformed local header for `{name}`")); - } - let lname = u16_at(local_off + 26); - let lextra = u16_at(local_off + 28); - let data_start = local_off + 30 + lname + lextra; - let data = bytes - .get(data_start..data_start + csize) + let local = local_off + .checked_add(30) + .and_then(|to| bytes.get(local_off..to)) + .filter(|h| h.starts_with(b"PK\x03\x04")) + .ok_or_else(|| format!("malformed local header for `{name}`"))?; + let lname = u16_of(local, 26); + let lextra = u16_of(local, 28); + let data = local_off + .checked_add(30) + .and_then(|at| at.checked_add(lname)) + .and_then(|at| at.checked_add(lextra)) + .and_then(|at| Some((at, at.checked_add(csize)?))) + .and_then(|(at, to)| bytes.get(at..to)) .ok_or_else(|| format!("truncated data for `{name}`"))?; + // What is left of the archive-wide ceiling also caps this entry, + // so a declared size larger than the budget is refused before a + // byte of it is decompressed. + let budget = MAX_INFLATED - inflated_total; + if declared > budget { + return Err(format!("`{name}` expands past the archive size limit")); + } let inflated = match method { 0 => data.to_vec(), - 8 => miniz_oxide::inflate::decompress_to_vec(data) + // The central directory declares the inflated size, so it + // also caps it: an entry that expands past what it claims is + // refused rather than allowed to exhaust memory. + 8 => miniz_oxide::inflate::decompress_to_vec_with_limit(data, declared) .map_err(|e| format!("cannot inflate `{name}`: {e}"))?, m => return Err(format!("`{name}` uses unsupported compression method {m}")), }; - if inflated.len() != usize_ { + if inflated.len() != declared { return Err(format!("size mismatch for `{name}`")); } + inflated_total += inflated.len(); out.push((name, inflated)); - off += 46 + name_len + extra_len + comment_len; + off = off + .checked_add(46 + name_len + extra_len + comment_len) + .ok_or("malformed central directory")?; } Ok(out) } @@ -141,9 +190,16 @@ fn zip_entries(bytes: &[u8]) -> Result)>, String> { /// given root names, metamodel URI chosen by dialect, SHA-256 checksums, /// `created` = now), then the units — deflate entries with the normative /// zeroed date (1980-01-01), so archives are byte-deterministic apart -/// from the creation timestamp. -pub fn write(project_name: &str, version: &str, units: &[(String, String, String)]) -> Vec { - let sysml = units.iter().any(|(f, _, _)| f.ends_with(".sysml")); +/// from the creation timestamp. Fails when a name, an entry or the whole +/// archive outgrows the 16/32-bit header fields. +pub fn write( + project_name: &str, + version: &str, + units: &[(String, String, String)], +) -> Result, String> { + let sysml = units + .iter() + .any(|(f, _, _)| crate::has_extension(f, "sysml")); let metamodel = if sysml { "https://www.omg.org/spec/SysML/20250201" } else { @@ -182,7 +238,15 @@ pub fn write(project_name: &str, version: &str, units: &[(String, String, String zip_write(&entries) } -fn zip_write(entries: &[(String, Vec)]) -> Vec { +/// The ZIP headers this writer emits hold offsets and sizes in 32 bits +/// and counts and name lengths in 16, and there is no ZIP64 record to +/// escape into; anything that does not fit is refused rather than +/// silently truncated into a header that describes a different archive. +fn too_large(what: impl std::fmt::Display) -> String { + format!("archive too large (no ZIP64 support): {what}") +} + +fn zip_write(entries: &[(String, Vec)]) -> Result, String> { let mut out = Vec::new(); let mut central = Vec::new(); // The normative archives' zeroed timestamp: 1980-01-01 00:00. @@ -198,7 +262,13 @@ fn zip_write(entries: &[(String, Vec)]) -> Vec { } else { (0, data) }; - let local_off = out.len() as u32; + let local_off = + u32::try_from(out.len()).map_err(|_| too_large(format_args!("entry offset")))?; + let csize = u32::try_from(payload.len()) + .map_err(|_| too_large(format_args!("compressed `{name}`")))?; + let usize_ = u32::try_from(data.len()).map_err(|_| too_large(format_args!("`{name}`")))?; + let name_len = + u16::try_from(name.len()).map_err(|_| too_large(format_args!("the name `{name}`")))?; out.extend_from_slice(b"PK\x03\x04"); out.extend_from_slice(&20u16.to_le_bytes()); // version needed out.extend_from_slice(&0u16.to_le_bytes()); // flags @@ -206,9 +276,9 @@ fn zip_write(entries: &[(String, Vec)]) -> Vec { out.extend_from_slice(&dos_time.to_le_bytes()); out.extend_from_slice(&dos_date.to_le_bytes()); out.extend_from_slice(&crc.to_le_bytes()); - out.extend_from_slice(&(payload.len() as u32).to_le_bytes()); - out.extend_from_slice(&(data.len() as u32).to_le_bytes()); - out.extend_from_slice(&(name.len() as u16).to_le_bytes()); + out.extend_from_slice(&csize.to_le_bytes()); + out.extend_from_slice(&usize_.to_le_bytes()); + out.extend_from_slice(&name_len.to_le_bytes()); out.extend_from_slice(&0u16.to_le_bytes()); // extra out.extend_from_slice(name.as_bytes()); out.extend_from_slice(payload); @@ -221,24 +291,28 @@ fn zip_write(entries: &[(String, Vec)]) -> Vec { central.extend_from_slice(&dos_time.to_le_bytes()); central.extend_from_slice(&dos_date.to_le_bytes()); central.extend_from_slice(&crc.to_le_bytes()); - central.extend_from_slice(&(payload.len() as u32).to_le_bytes()); - central.extend_from_slice(&(data.len() as u32).to_le_bytes()); - central.extend_from_slice(&(name.len() as u16).to_le_bytes()); + central.extend_from_slice(&csize.to_le_bytes()); + central.extend_from_slice(&usize_.to_le_bytes()); + central.extend_from_slice(&name_len.to_le_bytes()); central.extend_from_slice(&[0u8; 8]); // extra/comment/disk/internal central.extend_from_slice(&0u32.to_le_bytes()); // external attrs central.extend_from_slice(&local_off.to_le_bytes()); central.extend_from_slice(name.as_bytes()); } - let cd_off = out.len() as u32; + let cd_off = u32::try_from(out.len()) + .map_err(|_| too_large(format_args!("central-directory offset")))?; + let cd_len = + u32::try_from(central.len()).map_err(|_| too_large(format_args!("central directory")))?; + let count = u16::try_from(entries.len()).map_err(|_| too_large(format_args!("entry count")))?; out.extend_from_slice(¢ral); out.extend_from_slice(b"PK\x05\x06"); out.extend_from_slice(&[0u8; 4]); // disk numbers - out.extend_from_slice(&(entries.len() as u16).to_le_bytes()); - out.extend_from_slice(&(entries.len() as u16).to_le_bytes()); - out.extend_from_slice(&(central.len() as u32).to_le_bytes()); + out.extend_from_slice(&count.to_le_bytes()); + out.extend_from_slice(&count.to_le_bytes()); + out.extend_from_slice(&cd_len.to_le_bytes()); out.extend_from_slice(&cd_off.to_le_bytes()); out.extend_from_slice(&0u16.to_le_bytes()); // comment - out + Ok(out) } // ---- hashing --------------------------------------------------------------- @@ -371,7 +445,7 @@ mod tests { "package M;\n".to_string(), "M".to_string(), )]; - let bytes = write("Test", "1.0.0", &units); + let bytes = write("Test", "1.0.0", &units).expect("writable"); let kpar = read(&bytes).expect("readable"); assert_eq!(kpar.units.len(), 1); assert_eq!(kpar.units[0].source, "package M;\n"); @@ -379,4 +453,146 @@ mod tests { assert_eq!(kpar.project["name"], "Test"); assert_eq!(kpar.meta["index"]["M"], "M.sysml"); } + + /// An archive whose one unit is repetitive enough to be stored + /// deflated, so the inflation path is exercised. + fn sample() -> Vec { + let units = vec![( + "M.sysml".to_string(), + format!("package M {{\n{}}}\n", " part def P;\n".repeat(200)), + "M".to_string(), + )]; + write("Test", "1.0.0", &units).expect("writable") + } + + fn u16_at(bytes: &[u8], at: usize) -> usize { + u16::from_le_bytes(bytes[at..at + 2].try_into().unwrap()) as usize + } + + fn put_u16(bytes: &mut [u8], at: usize, v: u16) { + bytes[at..at + 2].copy_from_slice(&v.to_le_bytes()); + } + + fn put_u32(bytes: &mut [u8], at: usize, v: u32) { + bytes[at..at + 4].copy_from_slice(&v.to_le_bytes()); + } + + /// Offsets of the central-directory headers, in archive order. The + /// archive carries no trailing comment, so its end record is the + /// last 22 bytes. + fn headers(bytes: &[u8]) -> Vec { + let end = bytes.len() - 22; + let count = u16_at(bytes, end + 10); + let mut off = u32::from_le_bytes(bytes[end + 16..end + 20].try_into().unwrap()) as usize; + let mut out = Vec::new(); + for _ in 0..count { + out.push(off); + off += 46 + u16_at(bytes, off + 28) + u16_at(bytes, off + 30) + u16_at(bytes, off + 32); + } + out + } + + /// The message from an archive the reader must refuse. + fn refusal(bytes: &[u8]) -> String { + match read(bytes) { + Ok(_) => panic!("the archive was accepted"), + Err(e) => e, + } + } + + fn deflated_header(bytes: &[u8]) -> usize { + headers(bytes) + .into_iter() + .find(|&h| u16_at(bytes, h + 10) == 8) + .expect("one entry is stored deflated") + } + + #[test] + fn a_name_running_past_the_end_is_refused() { + let mut bytes = sample(); + let header = headers(&bytes)[0]; + put_u16(&mut bytes, header + 28, u16::MAX); + let err = refusal(&bytes); + assert!(err.contains("malformed central directory"), "{err}"); + } + + #[test] + fn a_central_directory_running_past_the_end_is_refused() { + // Both a directory that starts just short of the end and one + // whose offset is near the top of the 32-bit field — the latter + // is what wraps where a pointer is 32 bits wide. + for start in [u32::MAX - 10, u32::try_from(sample().len() - 2).unwrap()] { + let mut bytes = sample(); + let end = bytes.len() - 22; + put_u32(&mut bytes, end + 16, start); + let err = refusal(&bytes); + assert!(err.contains("malformed central directory"), "{err}"); + } + } + + #[test] + fn a_local_offset_running_past_the_end_is_refused() { + for local in [u32::MAX - 10, 1] { + let mut bytes = sample(); + let header = headers(&bytes)[0]; + put_u32(&mut bytes, header + 42, local); + let err = refusal(&bytes); + assert!(err.contains("malformed local header"), "{err}"); + } + } + + #[test] + fn entry_data_running_past_the_end_is_refused() { + let mut bytes = sample(); + let header = headers(&bytes)[0]; + put_u32(&mut bytes, header + 20, u32::MAX); + let err = refusal(&bytes); + assert!(err.contains("truncated data"), "{err}"); + } + + #[test] + fn a_declared_size_that_understates_the_entry_caps_inflation() { + let mut bytes = sample(); + let header = deflated_header(&bytes); + put_u32(&mut bytes, header + 24, 4); + let err = refusal(&bytes); + assert!(err.contains("cannot inflate"), "{err}"); + } + + #[test] + fn a_declared_size_that_overstates_the_entry_is_refused() { + let mut bytes = sample(); + let header = deflated_header(&bytes); + put_u32(&mut bytes, header + 24, 10_000_000); + let err = refusal(&bytes); + assert!(err.contains("size mismatch"), "{err}"); + } + + /// The ceiling is over everything the archive expands to, not over + /// one entry: a declared size past it is refused before a byte is + /// decompressed, and a size that would fit on its own is refused once + /// the entries before it have spent part of the budget. + #[test] + fn a_declared_size_past_the_archive_ceiling_is_refused() { + let mut bytes = sample(); + let header = deflated_header(&bytes); + put_u32(&mut bytes, header + 24, MAX_INFLATED as u32 + 1); + let err = refusal(&bytes); + assert!(err.contains("expands past the archive size limit"), "{err}"); + + // Exactly the ceiling, on an entry that is not the first: what + // the entries before it expanded to is already spent. + let mut bytes = sample(); + let header = headers(&bytes)[1]; + put_u32(&mut bytes, header + 24, MAX_INFLATED as u32); + let err = refusal(&bytes); + assert!(err.contains("expands past the archive size limit"), "{err}"); + } + + #[test] + fn a_truncated_archive_is_refused() { + let bytes = sample(); + let err = refusal(&bytes[..bytes.len() / 2]); + assert!(err.contains("not a ZIP archive"), "{err}"); + } } diff --git a/crates/sysmlv2-cli/src/lib.rs b/crates/sysmlv2-cli/src/lib.rs new file mode 100644 index 0000000..fd440e6 --- /dev/null +++ b/crates/sysmlv2-cli/src/lib.rs @@ -0,0 +1,5248 @@ +//! `sysmlv2` — CLI for the sysmlv2-parser library: convert, format, and check +//! SysML v2 / KerML models. +//! +//! [`run`] is the whole command line: it parses one argument list and +//! returns the status the process should end with, so a caller — the +//! binary beside this library, or a test — drives the verbs without +//! spawning anything. + +use clap::{Parser, Subcommand, ValueEnum}; +use std::collections::{HashMap, HashSet}; +use std::fs::{OpenOptions, Permissions}; +use std::io::{self, BufWriter, IsTerminal, Write}; +use std::path::{Path, PathBuf}; +use std::process::ExitCode; +use sysmlv2_parser::Diagnostic; +use sysmlv2_parser::ast::Dialect; +use sysmlv2_parser::full::{model_to_full_json_with, to_full_json_with}; +use sysmlv2_parser::json::{library_name_map, model_to_compact_json_with_units, to_compact_json}; +use sysmlv2_parser::lift::from_compact_json_with_names; +use sysmlv2_parser::model::Model; +use sysmlv2_parser::parser::{Parse, parse_kerml_source, parse_source}; +use sysmlv2_parser::print::{Indent, PrintOptions, format_source_with, print_source_opts}; +use sysmlv2_parser::span::{LineIndex, Span}; + +mod kpar; + +/// Load a prepared standard library; the model layer also shares its immutable +/// prefix across SDK/session rebuilds. Any legacy recording is saved after build. +/// A cache the loader could not write is reported here — this process has a +/// standard error stream to report it on, the library does not. +fn load_library(model: &mut Model, dir: &Path) -> std::io::Result> { + let load = sysmlv2_parser::prepared::load_library_with_cache(model, dir)?; + // One cache location, one cause, one remedy: several unwritable cache + // files in a run say the same thing, so the first speaks for the run. + if let Some(warning) = load.warnings.first() { + static SAID: std::sync::Once = std::sync::Once::new(); + SAID.call_once(|| eprintln!("warning: {warning}")); + } + Ok(load.recording_path) +} + +/// Inverse of [`flexo_payload`] for Flexo *responses*: unwrap +/// `{payload, identity}` change records when present and normalize the +/// server's empty-string property values back to null, so the element +/// list lifts like ordinary interchange JSON. +fn flexo_unwrap(value: serde_json::Value) -> serde_json::Value { + fn empties_to_null(v: &mut serde_json::Value) { + match v { + serde_json::Value::Object(map) => { + for (_, val) in map.iter_mut() { + if val.as_str() == Some("") { + *val = serde_json::Value::Null; + } else { + empties_to_null(val); + } + } + } + serde_json::Value::Array(items) => items.iter_mut().for_each(empties_to_null), + _ => {} + } + } + let serde_json::Value::Array(items) = value else { + return value; + }; + let wrapped = !items.is_empty() + && items + .iter() + .all(|r| r.get("payload").is_some() && r.get("identity").is_some()); + let mut elements: Vec = if wrapped { + items.into_iter().map(|mut r| r["payload"].take()).collect() + } else { + items + }; + elements.iter_mut().for_each(empties_to_null); + serde_json::Value::Array(elements) +} + +/// Flexo MMS commit conventions: name each root namespace after its source +/// file (Flexo stores the file name in the root's `qualifiedName` and +/// splits documents on it when reading back), then wrap every element as a +/// `{payload, identity}` change record with null property values emptied +/// (matching the Flexo MMS payload shape byte for byte). +fn flexo_payload(mut json: serde_json::Value, input_names: &[String]) -> serde_json::Value { + let serde_json::Value::Array(elements) = &mut json else { + return json; + }; + let mut root_i = 0usize; + for e in elements.iter_mut() { + let is_root = e.get("@type").and_then(|v| v.as_str()) == Some("Namespace") + && e.get("owningRelationship") + .is_none_or(serde_json::Value::is_null); + if is_root { + if let Some(name) = input_names.get(root_i) { + e["qualifiedName"] = serde_json::Value::String(name.clone()); + } + root_i += 1; + } + } + fn nulls_to_empty(v: &mut serde_json::Value) { + match v { + serde_json::Value::Object(map) => { + for (_, val) in map.iter_mut() { + if val.is_null() { + *val = serde_json::Value::String(String::new()); + } else { + nulls_to_empty(val); + } + } + } + serde_json::Value::Array(items) => items.iter_mut().for_each(nulls_to_empty), + _ => {} + } + } + let wrapped = elements + .iter() + .map(|e| { + let id = e.get("@id").cloned().unwrap_or(serde_json::Value::Null); + let mut payload = e.clone(); + nulls_to_empty(&mut payload); + serde_json::json!({ "payload": payload, "identity": { "@id": id } }) + }) + .collect(); + serde_json::Value::Array(wrapped) +} + +/// Why a run ended before its verb finished. +#[derive(Debug)] +pub enum CliError { + /// Everything this run had to say is already out — diagnostics on + /// stderr, a partial result on stdout, a reader that closed the + /// pipe — and this is the status to end with. + Reported(ExitCode), + /// One line for stderr, which the entry point prints as `error: {}`. + Message(String), +} + +impl std::fmt::Display for CliError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + CliError::Reported(_) => Ok(()), + CliError::Message(message) => f.write_str(message), + } + } +} + +/// The helpers that predate this type report their own message and +/// answer with a status, so `?` carries them straight through. +impl From for CliError { + fn from(code: ExitCode) -> Self { + CliError::Reported(code) + } +} + +/// An error whose message the entry point prints. +fn fail(message: impl Into) -> CliError { + CliError::Message(message.into()) +} + +/// One verb's outcome as the run's exit status: a message that has not +/// been printed yet is printed here, and everything else already has +/// its status. +fn finish(outcome: Result<(), CliError>) -> ExitCode { + match outcome { + Ok(()) => ExitCode::SUCCESS, + Err(CliError::Reported(code)) => code, + Err(e) => { + eprintln!("error: {e}"); + ExitCode::FAILURE + } + } +} + +/// Does `name` end in the extension `ext` (spelled without its dot)? +/// A file name is matched without regard to the case of its extension, +/// so `Model.SysML` is as much a model source as `model.sysml` — and, +/// through [`dialect_of`], parses in the same dialect. +fn has_extension(name: impl AsRef, ext: &str) -> bool { + name.as_ref() + .extension() + .is_some_and(|e| e.eq_ignore_ascii_case(ext)) +} + +/// Is `name` a textual model source — `.sysml` or `.kerml`, in any case? +fn is_model_source(name: impl AsRef) -> bool { + let name = name.as_ref(); + has_extension(name, "sysml") || has_extension(name, "kerml") +} + +/// File name for one split document: the root namespace's recorded name +/// when it is a plain model file name (the Flexo convention), else a +/// numbered fallback. +fn doc_file_name(root_name: Option<&str>, index: usize) -> String { + if let Some(name) = root_name { + let base = Path::new(name) + .file_name() + .map(|n| n.to_string_lossy().into_owned()) + .unwrap_or_default(); + let safe = !base.is_empty() + && base + .chars() + .all(|c| c != ':' && c != '*' && c != '?' && c != '"'); + if safe && is_model_source(&base) { + return base; + } + } + format!("document-{}.sysml", index + 1) +} + +/// Persist the outcomes recorded by the first build after [`load_library`] +/// armed recording. Best-effort: the cache is an accelerator only. +fn save_library_cache(model: &Model, path: Option) { + if let (Some(path), Some(cache)) = (path, model.take_recorded_library_cache()) { + let _ = cache.save(&path); + } +} + +#[derive(Parser)] +#[command( + name = "sysmlv2", + version, + about = "Parse, convert, format, and check SysML v2 / KerML models", + long_about = "Parse, convert, format, and check OMG SysML v2 / KerML textual models.\n\ + \n\ + Conversion matrix (--to):\n\ + \x20 text textual notation (.sysml / .kerml)\n\ + \x20 compact-json KerML 10.4 compact interchange form\n\ + \x20 compact-cbor binary re-encoding of the compact form\n\ + \x20 full-json derived properties + implied relationships (schema-valid)\n\ + \x20 full-cbor binary re-encoding of the full form (emit view)\n\ + \x20 kpar KerML 10.3 project archive (zipped units + manifests)\n\ + \n\ + Inputs may be textual (.sysml / .kerml), interchange JSON (.json),\ + compact CBOR (.s2c), or project archives (.kpar, expanded to\n\ + their textual units);\n\ + full-form JSON input is normalized to compact automatically.\n\ + Pass --lib (e.g. the OMG sysml.library directory) to resolve\n\ + standard-library references to their normative element IDs — and to\n\ + name them again when converting JSON back to text.\n\ + \n\ + Anywhere a file path is accepted, `-` reads from stdin (parsed as\n\ + SysML unless the input is sniffed as JSON).\n\ + \n\ + Standard-library loads are cached automatically: the first run\n\ + against a library records a sealed snapshot (resolutions + element\n\ + ids) under ~/.cache/sysmlv2/, keyed by library content and stamped\n\ + with the exact toolkit build — later runs replay it, and any\n\ + mismatch (including a toolkit rebuilt from changed sources at the\n\ + same version) rebuilds cold and refreshes the file. Set\n\ + SYSMLV2_CACHE_DIR to relocate the cache or SYSMLV2_LIB_CACHE=off\n\ + to disable it (e.g. for benchmarking).\n\ + \n\ + Ambient model context: when SYSMLV2_MODEL_DIR names a directory,\n\ + its .sysml/.kerml files stand in for omitted input files (fmt\n\ + honors this under --check only), and a stderr note records that\n\ + ambient state supplied the inputs (silence it with -q).\n\ + SYSMLV2_LIB_DIR fills --lib the same way wherever it is accepted.\n\ + With the variable set, --help ends with the active context.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 convert model.sysml --to compact-json\n\ + \x20 sysmlv2 convert model.sysml --to compact-json --lib sysml.library/ -o model.json\n\ + \x20 cat model.sysml | sysmlv2 convert - --to compact-json\n\ + \x20 sysmlv2 fmt src/**/*.sysml\n\ + \x20 sysmlv2 fmt --check model.sysml\n\ + \x20 sysmlv2 check model.sysml lib.kerml\n\ + \x20 sysmlv2 parse model.sysml --ast" +)] +struct Cli { + #[command(subcommand)] + command: Command, + /// Suppress informational stderr notes (e.g. the ambient + /// model-context line printed when SYSMLV2_MODEL_DIR supplies the + /// input files) + #[arg(short, long, global = true)] + quiet: bool, + /// Keep quoted power-product unit spellings (`'m³⋅s⁻²'`) opaque + /// instead of expanding them by parsing the name — the evaluator + /// then treats such a unit as its own base dimension, convertible + /// with nothing [env: SYSMLV2_UNIT_SPELLINGS=off] + #[arg(long = "no-unit-spellings", global = true)] + no_unit_spellings: bool, +} + +#[derive(Clone, Copy, PartialEq, ValueEnum)] +enum Target { + /// Textual notation + Text, + /// Compact interchange JSON (KerML 10.4; no implied relationships) + CompactJson, + /// Compact interchange CBOR: the deterministic binary + /// re-encoding of compact JSON (binary output; use -o) + CompactCbor, + /// Full interchange JSON: derived properties + implied relationships + FullJson, + /// Full interchange CBOR: the binary re-encoding of full JSON + /// (emit view only; binary output; use -o) + FullCbor, + /// KerML 10.3 project archive (.kpar): zipped textual units + manifests + Kpar, +} + +/// How `check` and `lint` report their findings. +#[derive(Clone, Copy, PartialEq, ValueEnum)] +enum ReportFormat { + /// Human-readable diagnostics on stderr, one block per finding + Text, + /// One JSON document on stdout, `{"findings": [...], "summary": + /// {...}}`, with one item shape for check and lint; the + /// per-finding text and the count lines are not printed. The exit + /// status is the text mode's (--strict fails on any finding at + /// all; a refused --fix counts as an error), which the summary's + /// per-severity counts do not encode + Json, +} + +/// Which diagram `viz` renders. The command line spells the view +/// repertoire; `ic` and `seq` are the accepted short spellings. +#[cfg(feature = "viz")] +#[derive(Clone, Copy, PartialEq, ValueEnum)] +pub enum DiagramView { + /// Structure: packages, definitions, usages + Tree, + /// Parts, ports, and connector edges + #[value(alias = "ic")] + Interconnection, + /// State machines: states, transitions, entry/do/exit + State, + /// Action flows: actions, control nodes, successions, flows + Action, + /// Lifelines and messages, ordered by event successions + #[value(alias = "seq")] + Sequence, + /// Use cases: actors, subjects, objectives, «include» edges + Case, + /// Everything on one canvas: structure, connectors, behaviors, + /// cases, typing + Mixed, +} + +#[cfg(feature = "viz")] +impl From for sysmlv2_viz::View { + fn from(view: DiagramView) -> Self { + match view { + DiagramView::Tree => sysmlv2_viz::View::Tree, + DiagramView::Interconnection => sysmlv2_viz::View::Interconnection, + DiagramView::State => sysmlv2_viz::View::State, + DiagramView::Action => sysmlv2_viz::View::Action, + DiagramView::Sequence => sysmlv2_viz::View::Sequence, + DiagramView::Case => sysmlv2_viz::View::Case, + DiagramView::Mixed => sysmlv2_viz::View::Mixed, + } + } +} + +/// Edge routing for `viz`. Absent, the diagram keeps the renderer's +/// own splines, which is why there is no command-line spelling for it. +#[cfg(feature = "viz")] +#[derive(Clone, Copy, PartialEq, ValueEnum)] +pub enum DiagramLineStyle { + /// Straight segments through the routed points + Polyline, + /// Right-angled segments + Ortho, +} + +#[cfg(feature = "viz")] +impl From for sysmlv2_viz::LineStyle { + fn from(style: DiagramLineStyle) -> Self { + match style { + DiagramLineStyle::Polyline => sysmlv2_viz::LineStyle::Polyline, + DiagramLineStyle::Ortho => sysmlv2_viz::LineStyle::Ortho, + } + } +} + +#[derive(Subcommand)] +enum Command { + /// Convert a model between textual notation and interchange JSON + #[command( + long_about = "Convert a model between textual notation and interchange JSON/CBOR.\n\ + \n\ + The input format is detected from the file extension:\n\ + .sysml / .kerml parse as textual notation; .json is lifted from\n\ + the interchange form (full-form JSON is normalized to compact —\n\ + implied relationships dropped, derived properties ignored);\n\ + .s2c decodes as compact-form CBOR and then flows like .json.\n\ + With --lib, text→JSON resolves standard-library references to\n\ + their normative KerML 9.1 element IDs, and JSON→text turns those\n\ + IDs back into qualified names.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 convert model.sysml --to compact-json\n\ + \x20 sysmlv2 convert model.json --to text -o model.sysml\n\ + \x20 sysmlv2 convert model.json --to text --min-qual # shortest reference spellings\n\ + \x20 sysmlv2 convert full.json --to compact-json # normalize full → compact\n\ + \x20 sysmlv2 convert model.sysml --to compact-cbor -o model.s2c\n\ + \x20 sysmlv2 convert model.s2c --to text # binary → textual notation\n\ + \x20 sysmlv2 convert model.sysml --to compact-json --lib spec-refs/SysML-v2-Release/sysml.library" + )] + Convert { + /// Input files (.sysml / .kerml — several form one model with one + /// root namespace per file), or a single .json / .s2c; `-` for + /// stdin (text or JSON); optional when SYSMLV2_MODEL_DIR is set + inputs: Vec, + /// Output format + #[arg(long, value_enum)] + to: Target, + /// Output file (defaults to stdout). For `--to text` with a + /// multi-document JSON input, an existing directory splits the + /// output into one file per root namespace + #[arg(short, long)] + output: Option, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Flexo MMS conventions on JSON output: each root namespace's + /// qualifiedName is set to its source file name and every element + /// is wrapped as a `{payload, identity}` change record + #[arg(long)] + flexo: bool, + /// JSON → text only: respell every reference with the shortest + /// spelling that still resolves to the same element (bare name + /// where unambiguous, a qualified suffix where needed), verified + /// by reparse; without it references print as always-correct + /// `$::`-rooted paths + #[arg(long = "min-qual")] + min_qual: bool, + /// --to compact-cbor only: omit graph-derivable element ids + /// (IDS.md) — receivers recompute them, verified by the + /// payload's integrity digest. Composes with --delta-base + /// (strict deltas: created ids elide). Decode/apply against + /// the same --lib version the payload was encoded with + #[arg(long = "elide-ids")] + elide_ids: bool, + /// Delta base (compact .json or .s2c). With --to compact-cbor + /// the output becomes a delta against it; with a + /// delta .s2c input the delta is applied to it first + #[arg(long = "delta-base")] + delta_base: Option, + /// Delta output only: id-keyed identities, applicable + /// best-effort to divergent bases (larger than the strict + /// indexed default) + #[arg(long = "delta-portable", requires = "delta_base")] + delta_portable: bool, + /// Indentation for textual output: `tabs` or a space count + /// (default 4) + #[arg(long, value_parser = parse_indent_arg, default_value = "4")] + indent: Indent, + /// Emit the resolved standard library itself — every element + /// of the --lib units, each under its normative KerML 9.1 id — + /// instead of converting a model. The complement of a normal + /// conversion, whose output holds just the user units' elements + /// while its library references dangle by design. Takes no + /// inputs; targets compact-json and compact-cbor + #[arg( + long, + requires = "lib", + conflicts_with_all = ["flexo", "min_qual", "elide_ids", "delta_base", "delta_portable"] + )] + library: bool, + }, + /// Inspect payload files, or diff/apply them at payload identity + #[command( + long_about = "Inspect interchange payload files without loading them as a\n\ + model: what each file is (compact/full snapshot or delta),\n\ + its header versions, element and change counts, and its\n\ + content digests. Snapshots (.s2c or compact .json) report\n\ + their state digest — the digest a delta's base digest is\n\ + matched against. Deltas report their base and result\n\ + digests without needing the base present.\n\ + \n\ + With --find-base, every snapshot file under a directory is\n\ + digested once and each delta input reports which of them it\n\ + applies to cleanly (state digest = the delta's base digest)\n\ + and which already hold its result. A delta with no base\n\ + match fails the command, so the verb scripts as a check.\n\ + \n\ + Every mode of this verb works at payload identity: files\n\ + are read exactly as their producer wrote them — no model\n\ + lift, no id re-derivation, no rebase. --delta-from diffs\n\ + two snapshots by element @id (a store whose ids are\n\ + authoritative diffs its own states losslessly; contrast\n\ + `convert --delta-base`, which re-derives and rebases ids\n\ + for freshly parsed inputs). --apply-to applies a delta and\n\ + reports what happened. --ids prints a snapshot's\n\ + delta-canonical element id sequence — the index space\n\ + strict deltas address their base through.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 payload model.s2c\n\ + \x20 sysmlv2 payload edit.s2c --find-base exports/\n\ + \x20 sysmlv2 payload base.s2c edit.s2c # digests to match by hand\n\ + \x20 sysmlv2 payload new.json --delta-from old.json -o commit.s2c\n\ + \x20 sysmlv2 payload commit.s2c --apply-to old.json -o new.json\n\ + \x20 sysmlv2 payload model.s2c --ids" + )] + Payload { + /// Payload files: .s2c (snapshot or delta) or compact + /// interchange .json + inputs: Vec, + /// Directory to scan (recursively) for snapshot files whose + /// state digest matches each delta's base or result digest + #[arg(long = "find-base", value_name = "DIR")] + find_base: Option, + /// Standard-library directory — lets id-elided snapshots with + /// library-typed elements re-derive their ids for digesting + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Emit a delta from BASE to the single snapshot input, pairing + /// elements by @id — producer ids are authoritative on both + /// sides. Strict (indexed) unless --portable + #[arg(long = "delta-from", value_name = "BASE", + conflicts_with_all = ["find_base", "apply_to", "ids"])] + delta_from: Option, + /// With --delta-from: id-keyed delta identities, applicable + /// best-effort to a divergent base + #[arg(long, requires = "delta_from")] + portable: bool, + /// With --delta-from: claim key 0 — the project the delta + /// belongs to (routing hint; the digest is the proof) + #[arg(long = "claim-project", value_name = "UUID", requires = "delta_from")] + claim_project: Option, + /// With --delta-from: claim key 1 — the commit the base names + #[arg(long = "claim-commit", value_name = "UUID", requires = "delta_from")] + claim_commit: Option, + /// With --delta-from: claim key 2 — the emitting service + #[arg(long = "claim-service", value_name = "URI", requires = "delta_from")] + claim_service: Option, + /// Apply the single delta input to the snapshot BASE; the + /// applied compact JSON goes to --output, the apply report + /// (JSON) to stdout + #[arg(long = "apply-to", value_name = "BASE", + conflicts_with_all = ["find_base", "ids"])] + apply_to: Option, + /// With --apply-to: portable deltas apply best-effort to a + /// divergent base; the report counts the divergences + #[arg(long, requires = "apply_to")] + lenient: bool, + /// Print each snapshot input's delta-canonical element id + /// sequence with its state digest + #[arg(long, conflicts_with = "find_base")] + ids: bool, + /// Print the codec tables as versioned JSON — the artifact a + /// consumer vendors to label payload structure without this + /// toolkit: metaclass wire codes with per-ordinal field tables + /// (property, kind, enum table, presence default), both the + /// compact and full ordinal spaces, the enum vocabularies, and + /// the header version axes and flags. Takes no payload inputs + #[arg(long, conflicts_with_all = ["find_base", "delta_from", "apply_to", "ids"])] + tables: bool, + /// Encode the single compact-JSON snapshot input to `.s2c` at + /// payload identity — no lift, no id re-derivation (contrast + /// `convert`, which parses its input as a model and re-derives + /// ids). The store-side inverse of a snapshot decode + #[arg(long, conflicts_with_all = ["find_base", "delta_from", "apply_to", "ids", "tables"])] + encode: bool, + /// Output file: the delta payload (--delta-from) or the applied + /// compact JSON (--apply-to) + #[arg(short, long)] + output: Option, + }, + /// Format .sysml / .kerml files in place (canonical style) + #[command( + long_about = "Format textual models to the canonical style: four-space\n\ + indentation, one member per line, symbolic specialization\n\ + operators. Notes (// …) and blank lines are preserved.\n\ + Files with parse errors are left untouched and reported.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 fmt model.sysml # rewrite in place\n\ + \x20 sysmlv2 fmt a.sysml b.kerml # several files\n\ + \x20 sysmlv2 fmt --check model.sysml # exit 1 if not formatted\n\ + \x20 sysmlv2 fmt --stdout model.sysml # print instead of rewriting\n\ + \x20 cat model.sysml | sysmlv2 fmt --stdout - # format stdin" + )] + Fmt { + /// Files to format; `-` reads stdin (requires --stdout or + /// --check); with --check, optional when SYSMLV2_MODEL_DIR is set + files: Vec, + /// Verify formatting without writing; exit 1 if any file differs + #[arg(long)] + check: bool, + /// Print the formatted output instead of rewriting the file + #[arg(long)] + stdout: bool, + /// Indentation for formatted output: `tabs` or a space count + /// (default 4) + #[arg(long, value_parser = parse_indent_arg, default_value = "4")] + indent: Indent, + }, + /// Parse and validate files (syntax + body-context legality; exit 1 on + /// any error). With --lib, also runs referential checks as warnings. + #[command(after_help = "Checks run in stages: parse diagnostics, then\n\ + body-context validation (members that the grammar\n\ + does not allow in their surrounding body, e.g. a\n\ + `transition` inside a plain `part` body, or a\n\ + `variant` member outside a `variation`).\n\ + With --lib, all files form one model resolved\n\ + against the library; referential findings are\n\ + warnings (unresolved references, alias targets,\n\ + circular imports), and semantic constraints are\n\ + checked (multiplicity bounds, self/circular\n\ + specialization — errors; duplicate\n\ + specializations — warnings). Private imports\n\ + that provably feed nothing in their unit warn\n\ + as `unused private import`.\n\ + Warnings never fail the run unless --strict is\n\ + given, which exits 1 on any finding at all.\n\ + --format json writes one JSON document to stdout\n\ + instead of text on stderr: findings with stage\n\ + (parse, context, referential, semantic), severity,\n\ + unit name and 1-based positions, plus a summary —\n\ + the same item shape `lint --format json` emits.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 check model.sysml\n\ + \x20 sysmlv2 check --format json model.sysml\n\ + \x20 sysmlv2 check src/*.sysml lib/*.kerml\n\ + \x20 sysmlv2 check model.sysml --lib spec-refs/SysML-v2-Release/sysml.library\n\ + \x20 sysmlv2 check --strict --lib sysml.library/ model.sysml\n\ + \x20 cat model.sysml | sysmlv2 check -")] + Check { + /// Files to check; `-` reads stdin; optional when + /// SYSMLV2_MODEL_DIR is set + files: Vec, + /// Standard-library directory; enables referential checks + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Treat warnings as failures: exit 1 on any finding (for + /// pipelines that must refuse incomplete models, e.g. gating a + /// Flexo commit) + #[arg(long)] + strict: bool, + /// Report format: text on stderr, or one JSON document on stdout + #[arg(long, value_enum, default_value_t = ReportFormat::Text)] + format: ReportFormat, + }, + /// Lint the model against configurable project-policy rules + #[command(after_help = "Rules are policy, not language law: lint runs\n\ + beside `check` and never changes its verdicts.\n\ + Config JSON: { \"rules\": { \"\": \"off\" |\n\ + \"hint\" | \"info\" | \"warn\" | \"error\" |\n\ + { \"severity\": …, \"scopes\": { \"\":\n\ + … }, …options } } } — default sysmlint.json\n\ + beside the first input. Defaults: the policy\n\ + rules (undocumented-element, untyped-usage,\n\ + unused-definition, unused-parameter,\n\ + unit-spelling, qualified-names,\n\ + multiline-conditions, indentation) are off —\n\ + opt in per rule or per stereotype scope;\n\ + naming-convention is info (a casing nudge —\n\ + tighten or disable per project);\n\ + dimensional-consistency, unqualified-enum-literal\n\ + and visibility-blocked-reference warn;\n\ + import-visibility, usage-kind-mismatch and\n\ + port-member-referential are info findings that\n\ + carry the fix for an error `check` already\n\ + reports; the generated-provenance rules audit\n\ + transformer-owned members (invalid = error,\n\ + modified = warn, baseline-outdated = info).\n\ + --fix applies safe fixes; fixes that DELETE model\n\ + text (e.g. removing an unused parameter) are\n\ + guarded behind --fix-deletes so information is\n\ + never lost without explicit approval.\n\n\ + --format json writes one JSON document to stdout\n\ + instead of text on stderr: findings with rule,\n\ + severity, unit name, 1-based positions, element and\n\ + fix edits (byte offsets), plus a summary.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 lint model.sysml\n\ + \x20 sysmlv2 lint --format json model.sysml\n\ + \x20 sysmlv2 lint --config sysmlint.json src/*.sysml\n\ + \x20 sysmlv2 lint --rule unused-definition=warn model.sysml\n\ + \x20 sysmlv2 lint --fix --fix-deletes model.sysml\n\ + \x20 sysmlv2 lint --strict model.sysml")] + Lint { + /// Files to lint; `-` reads stdin; optional when + /// SYSMLV2_MODEL_DIR is set + files: Vec, + /// Standard-library directory (resolution context only; library + /// elements are never linted) + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Lint config JSON; defaults to sysmlint.json beside the first + /// input when present + #[arg(long)] + config: Option, + /// Override one rule's severity, e.g. unused-definition=warn + /// (repeatable; wins over the config file) + #[arg(long = "rule", value_name = "ID=LEVEL")] + rule: Vec, + /// Apply available auto-fixes that do not delete model text + #[arg(long)] + fix: bool, + /// With --fix: also apply fixes that DELETE model text (an + /// unused parameter's fix removes its declaration — deliberate + /// extra consent, deletions lose information) + #[arg(long, requires = "fix")] + fix_deletes: bool, + /// With --fix: also apply fixes that change what a declaration + /// means (a usage keyword, a member's visibility) rather than + /// how it is spelled + #[arg(long, requires = "fix")] + fix_semantic: bool, + /// Exit 1 on any finding at all (warnings, infos and hints + /// included), not only errors + #[arg(long)] + strict: bool, + /// Report format: text on stderr, or one JSON document on stdout + #[arg(long, value_enum, default_value_t = ReportFormat::Text)] + format: ReportFormat, + }, + /// Check constraint/requirement bodies to verdicts + #[cfg(feature = "solve")] + #[command(after_help = "Evaluates every constraint, requirement, and\n\ + invariant body that carries its own trailing\n\ + result expression: satisfied / violated /\n\ + undecided (with the reason — unbound features,\n\ + unsupported constructs). Exit 1 if any\n\ + constraint is violated.\n\n\ + With --ranges, interval propagation narrows every\n\ + unbound feature to a finite range and upgrades\n\ + verdicts (satisfied/VIOLATED/unsatisfiable) with\n\ + no external solver.\n\n\ + With --solve, propagation runs first and Z3 (the\n\ + `z3` binary; see --z3) then handles only what it\n\ + left undecided: proved to hold for all values of\n\ + the unbound features (satisfied), proved\n\ + unsatisfiable (VIOLATED), or satisfiable with a\n\ + witness assignment.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 verify model.sysml\n\ + \x20 sysmlv2 verify model.sysml --ranges\n\ + \x20 sysmlv2 verify model.sysml --solve\n\ + \x20 sysmlv2 verify src/*.sysml --lib spec-refs/SysML-v2-Release/sysml.library")] + Verify { + /// Input files (.sysml or .kerml) forming one model; `-` reads + /// stdin; optional when SYSMLV2_MODEL_DIR is set + files: Vec, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Interval-propagate undecided constraints and print narrowed + /// feature ranges (no external solver) + #[arg(long)] + ranges: bool, + /// Run Z3 over undecided constraints (witnesses, proofs); implies + /// propagation first, so Z3 only sees what it left undecided + #[arg(long)] + solve: bool, + /// Path to the z3 binary (default: `z3` on PATH) + #[arg(long, value_name = "PATH")] + z3: Option, + }, + /// Evaluate feature values in a model (expression evaluator) + #[command(after_help = "Evaluates the bound value expression of each named\n\ + feature against the resolved model: literals,\n\ + arithmetic/logical/comparison operators, ranges,\n\ + sequences, feature references (redefinition-aware),\n\ + and Kernel Function Library intrinsics incl.\n\ + collect/select/reduce lambdas. Use --all to list\n\ + every feature with a computed value.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 eval model.sysml Demo::car::mass\n\ + \x20 sysmlv2 eval model.sysml --all --lib spec-refs/SysML-v2-Release/sysml.library\n\ + \x20 sysmlv2 eval a.sysml b.sysml --all\n\ + \x20 sysmlv2 eval model.sysml 'Pkg::totalMass' 'Pkg::cost'")] + Eval { + /// Input file (.sysml or .kerml), or `-` for stdin; optional when + /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a + /// name, not a file) + input: Option, + /// Qualified names to evaluate (e.g. `Pkg::part::attr`); arguments + /// ending in `.sysml`/`.kerml` are further files joining the model + names: Vec, + /// Evaluate every feature that has a value expression + #[arg(long)] + all: bool, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// Query a model with an ad-hoc KerML expression + #[command( + long_about = "Query a model with an ad-hoc KerML expression, evaluated\n\ + against the root namespace — references resolve exactly\n\ + as they would in a model file (qualified names, feature\n\ + chains, select/collect/reduce lambdas, KFL intrinsics).\n\ + \n\ + Two extensions apply only here (never to feature values\n\ + in model files): `istype`/`as` on a model element\n\ + classify the declaration itself, so a miss against a\n\ + user-defined type answers `false` instead of undecided;\n\ + and the reflection functions `ownedMember(x)` /\n\ + `ownedFeature(x)` (the KerML derived properties as\n\ + functions) enumerate an element's owned members.\n\ + \n\ + A sequence result prints one item per line; elements\n\ + print as qualified name and metaclass.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 query model.sysml 'ownedFeature(Vehicle)->select { in p; p istype Wheel }'\n\ + \x20 sysmlv2 query model.sysml 'Demo::car.totalMass + 10'\n\ + \x20 sysmlv2 query a.sysml b.sysml 'size(ownedMember(Demo))'\n\ + \x20 cat model.sysml | sysmlv2 query - 'ownedFeature(Vehicle)'" + )] + Query { + /// Input file (.sysml or .kerml), or `-` for stdin; optional when + /// SYSMLV2_MODEL_DIR is set (the expression alone then suffices) + input: Option, + /// The query expression; arguments ending in `.sysml`/`.kerml` + /// are further files joining the model + args: Vec, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// Render a view's template over its exposed model slice (semantic mode) + #[command( + long_about = "Render the component template a view usage presents over the\n\ + model elements the view exposes (semantic mode): the\n\ + view's rendering definition owns an imported template root whose\n\ + translated expressions evaluate over the exposed slice. Prints the\n\ + rendered tree as JSON, or as HTML with --html. The model is not\n\ + modified.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 render --lib sysml.library model.sysml PackagesView.sysml Site::packagesView\n\ + \x20 sysmlv2 render --lib sysml.library --html app.sysml App::home" + )] + Render { + /// Model files (.sysml/.kerml) followed by the view usage's qualified name + args: Vec, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Print HTML instead of the JSON node tree + #[arg(long)] + html: bool, + }, + /// Describe one element: metaclass, owner, typing, position + #[command( + long_about = "Describe one element of the resolved model: its metaclass,\n\ + owner, declared type, position among its owner's members,\n\ + and declaration site.", + after_help = "EXAMPLES:\n\ + \x20 sysmlv2 describe model.sysml Demo::car\n\ + \x20 sysmlv2 describe a.sysml b.sysml Demo::car::mass\n\ + \x20 sysmlv2 describe Demo::car (SYSMLV2_MODEL_DIR set)" + )] + Describe { + /// Input file (.sysml or .kerml), or `-` for stdin; optional when + /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a + /// name, not a file) + input: Option, + /// The ::-qualified element name; arguments ending in + /// `.sysml`/`.kerml` are further files joining the model + args: Vec, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// List an element's owned members + #[command(after_help = "EXAMPLES:\n\ + \x20 sysmlv2 members model.sysml Demo\n\ + \x20 sysmlv2 members model.sysml Demo::car\n\ + \x20 sysmlv2 members Demo (SYSMLV2_MODEL_DIR set)")] + Members { + /// Input file (.sysml or .kerml), or `-` for stdin; optional when + /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a + /// name, not a file) + input: Option, + /// The ::-qualified element name; arguments ending in + /// `.sysml`/`.kerml` are further files joining the model + args: Vec, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// Parse one file and dump diagnostics (and optionally the AST) + #[command(after_help = "EXAMPLES:\n\ + \x20 sysmlv2 parse model.sysml\n\ + \x20 sysmlv2 parse model.sysml --ast\n\ + \x20 cat model.sysml | sysmlv2 parse -")] + Parse { + /// Input file, or `-` for stdin; optional when SYSMLV2_MODEL_DIR + /// is set (each discovered file parses independently) + input: Option, + /// Pretty-print the syntax tree + #[arg(long)] + ast: bool, + }, + /// Emit a PlantUML diagram + #[cfg(feature = "viz")] + #[command(after_help = "Renders one view of the model as PlantUML text\n\ + (feed it to any PlantUML build to get SVG/PNG):\n\n\ + \x20 tree structure: packages, definitions, and\n\ + \x20 usages with attribute compartments, plus\n\ + \x20 composition/typing/specialization edges\n\ + \x20 interconnection parts as nested blocks with ports;\n\ + \x20 connections, interfaces, bindings, and\n\ + \x20 flows as edges between their ends\n\ + \x20 state state machines: states, transitions\n\ + \x20 (trigger [guard] / effect), entry/do/exit\n\ + \x20 action action flows: actions, control nodes,\n\ + \x20 successions, dashed flow edges\n\ + \x20 sequence lifelines and messages between events,\n\ + \x20 ordered by event successions\n\ + \x20 case use cases: actors, subjects, objectives,\n\ + \x20 «include» edges\n\ + \x20 mixed everything on one canvas: structure,\n\ + \x20 connectors, behaviors, cases, typing\n\n\ + Comment/doc bodies attach as notes (--no-notes to\n\ + omit); --color keys node colors on the metaclass;\n\ + --link-template embeds [[hyperlinks]] carried into\n\ + rendered SVG.\n\n\ + Library elements never render as nodes; with --lib\n\ + their names still appear in labels (attribute\n\ + types, supertypes, definition ports).\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 viz model.sysml\n\ + \x20 sysmlv2 viz model.sysml --view interconnection\n\ + \x20 sysmlv2 viz model.sysml --element Pkg::Part -o part.puml\n\ + \x20 sysmlv2 viz model.sysml --view mixed --color --link-template \"vscode://file/{file}:{line}\"\n\ + \x20 sysmlv2 viz src/*.sysml --lib sysml.library/ | java -jar plantuml.jar -tsvg -p > model.svg")] + Viz { + /// Files to render; `-` reads stdin; optional when + /// SYSMLV2_MODEL_DIR is set + files: Vec, + /// View to render. Default: tree — except when --element + /// targets a view usage, whose own `render` member picks the + /// style + #[arg(long, value_enum)] + view: Option, + /// Root the diagram at this ::-qualified element + #[arg(long)] + element: Option, + /// Standard-library directory (names library references in labels) + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + /// Lay the diagram out left-to-right instead of top-to-bottom + #[arg(long)] + horizontal: bool, + /// Omit `= value` on attribute compartment lines + #[arg(long)] + no_values: bool, + /// Omit comment/doc bodies (attached as notes by default) + #[arg(long)] + no_notes: bool, + /// Hide metadata (annotation stereotypes and metadata nodes) + #[arg(long)] + hide_metadata: bool, + /// Add inherited compartment lines (one explicit hop, ^-marked) + #[arg(long)] + show_inherited: bool, + /// Render referenced standard-library types as marked nodes + #[arg(long)] + show_lib: bool, + /// Draw «import» edges between rendered nodes + #[arg(long)] + show_imported: bool, + /// Edge routing (default: PlantUML splines) + #[arg(long, value_enum)] + line_style: Option, + /// Color nodes by metaclass family + #[arg(long)] + color: bool, + /// Hyperlink template for nodes; placeholders {file} {line} + /// {col} {qname} {id} (e.g. "vscode://file/{file}:{line}") + #[arg(long)] + link_template: Option, + /// Write the PlantUML text here instead of stdout + #[arg(short, long)] + output: Option, + }, + /// Usage↔definition refactorings: extract / inline + #[command( + long_about = "Move between the usage-oriented and definition-oriented\n\ + modeling styles:\n\ + \n\ + extract a usage's inline body becomes a new definition,\n\ + \x20 the usage retyped by it —\n\ + \x20 `part engine : A { … }` becomes\n\ + \x20 `part def Engine :> A { … }` + `part engine : Engine;`\n\ + inline a definition's body merges into its sole typed\n\ + \x20 usage and the definition is deleted\n\ + \n\ + Inlining a definition just produced by extract restores the\n\ + original text byte-for-byte. Both directions are verified\n\ + commits: every carried reference is checked at its new home,\n\ + newly unresolved references or body-context violations roll\n\ + the edit back, and the touched usage's effective members\n\ + must be structurally unchanged. Refusals name their reason\n\ + (ineligible kind, header shape, name collision, outside\n\ + references, …) and leave every file untouched." + )] + Refactor { + #[command(subcommand)] + op: RefactorOp, + }, + /// Run the Language Server Protocol server over stdio + #[cfg(feature = "lsp")] + #[command(after_help = "Speaks LSP over stdio until the client ends the\n\ + session — run it from an editor, not a terminal.\n\ + Serves parse + body-context diagnostics on every\n\ + change and whole-document formatting; position\n\ + encoding negotiates utf-8 when offered (utf-16\n\ + otherwise). Dialect follows the file extension\n\ + (.kerml is KerML, everything else SysML).\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 lsp (as an editor's configured server command)\n\ + \x20 vim.lsp.start { cmd = { 'sysmlv2', 'lsp' } } (Neovim config)")] + Lsp { + /// Standard-library directory: hover/definition/references/rename + /// resolve standard-library names too (cached, ~0.15 s warm) + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, +} + +/// The two refactoring directions. Reads follow the ambient-input +/// convention; in-place writes require explicit file paths — +/// the fmt precedent for destructive verbs — and `--dry-run` prints the +/// would-be changes instead. +#[derive(Subcommand)] +enum RefactorOp { + /// Extract a usage's inline body into a new definition + #[command(after_help = "EXAMPLES:\n\ + \x20 sysmlv2 refactor extract model.sysml Rig::engine\n\ + \x20 sysmlv2 refactor extract model.sysml Rig::engine --name Motor\n\ + \x20 sysmlv2 refactor extract Rig::engine --dry-run (SYSMLV2_MODEL_DIR set)")] + Extract { + /// Input file (.sysml or .kerml); optional when SYSMLV2_MODEL_DIR + /// is set (a leading qualified name is then a name, not a file) + input: Option, + /// The ::-qualified usage name; arguments ending in + /// `.sysml`/`.kerml` are further files joining the model + args: Vec, + /// Definition name (default: UpperCamel of the usage's name) + #[arg(long)] + name: Option, + /// Print the would-be changes as a diff; write nothing + #[arg(long)] + dry_run: bool, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// Split a package into one file per nested package, under a + /// directory named after it; the package re-exports each of them, + /// so every qualified reference keeps resolving + #[command( + after_help = "The root package keeps its file; each nested package moves\n\ + to /.sysml (dir = the root file's name without\n\ + its extension, or --dir), dedented, with references to\n\ + anything outside it spelled in full. The root gains\n\ + `public import ;` per moved package, or a public\n\ + alias when the package had to be renamed to avoid a\n\ + root-level name collision. Run again on a moved file to\n\ + split deeper.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 refactor split model.sysml TMT --dry-run\n\ + \x20 sysmlv2 refactor split model.sysml TMT --slug" + )] + Split { + /// Input file (.sysml or .kerml); optional when SYSMLV2_MODEL_DIR + /// is set (a leading qualified name is then a name, not a file) + input: Option, + /// The ::-qualified package name; arguments ending in + /// `.sysml`/`.kerml` are further files joining the model + args: Vec, + /// Print the plan and the resulting texts; write nothing + #[arg(long)] + dry_run: bool, + /// Name files with letters, digits, `.`, `_` and `-` only + #[arg(long)] + slug: bool, + /// Directory for the new files, taken as given relative to the + /// working directory (default: the root file's path without its + /// extension) + #[arg(long)] + dir: Option, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, + /// Inline a definition into its sole typed usage and delete it + #[command(after_help = "Imports the deletion leaves unused are reported as\n\ + `note:` lines, never removed.\n\n\ + EXAMPLES:\n\ + \x20 sysmlv2 refactor inline model.sysml Rig::Engine\n\ + \x20 sysmlv2 refactor inline Rig::Engine --dry-run (SYSMLV2_MODEL_DIR set)")] + Inline { + /// Input file (.sysml or .kerml); optional when SYSMLV2_MODEL_DIR + /// is set (a leading qualified name is then a name, not a file) + input: Option, + /// The ::-qualified definition name; arguments ending in + /// `.sysml`/`.kerml` are further files joining the model + args: Vec, + /// Print the would-be changes as a diff; write nothing + #[arg(long)] + dry_run: bool, + /// Standard-library directory for reference resolution + #[arg(long, env = "SYSMLV2_LIB_DIR")] + lib: Option, + }, +} + +/// Render one query-result value: elements as `qualified::name (Metaclass)` +/// (anonymous elements keep just the metaclass), everything else through +/// the evaluator's own display. +fn render_query_value( + resolved: &mut sysmlv2_parser::json::ResolvedModel, + v: &sysmlv2_parser::eval::Value, +) -> String { + if let sysmlv2_parser::eval::Value::Element(e) + | sysmlv2_parser::eval::Value::Unbound(e) + | sysmlv2_parser::eval::Value::UnboundMember(e) = v + { + let ty = resolved.element_type(*e); + return match resolved.element_qualified_name(*e) { + Some(qn) => format!("{qn} ({ty})"), + None => format!(" ({ty})"), + }; + } + v.to_string() +} + +/// `--indent` values: `tabs`, or a space count 1–16. +fn parse_indent_arg(s: &str) -> Result { + if s == "tabs" { + return Ok(Indent::Tabs); + } + s.parse::() + .ok() + .filter(|n| (1..=16).contains(n)) + .map(Indent::Spaces) + .ok_or_else(|| "expected `tabs` or a space count 1-16".to_string()) +} + +fn dialect_of(path: &Path) -> Dialect { + if has_extension(path, "kerml") { + Dialect::Kerml + } else { + Dialect::Sysml + } +} + +fn parse_file(path: &Path, src: &str) -> Parse { + match dialect_of(path) { + Dialect::Kerml => parse_kerml_source(src), + Dialect::Sysml => parse_source(src), + } +} + +fn report(path: &Path, src: &str, diags: &[Diagnostic]) { + let reporter = Reporter::new(path, src); + for d in diags { + reporter.report(d); + } +} + +/// Diagnostics for one source, rendered against a line index built once. +/// Loops that emit findings one at a time across several files keep one +/// `Reporter` per file: rebuilding the index per finding made `check` and +/// `lint` quadratic in file size times finding count. +struct Reporter<'a> { + path: &'a Path, + src: &'a str, + index: LineIndex, +} + +impl<'a> Reporter<'a> { + fn new(path: &'a Path, src: &'a str) -> Self { + Reporter { + path, + src, + index: LineIndex::new(src), + } + } + + fn report(&self, d: &Diagnostic) { + let severity = match d.severity { + sysmlv2_parser::diag::Severity::Error => "error", + sysmlv2_parser::diag::Severity::Warning => "warning", + }; + let pos = self.index.line_col(d.span.start); + // The diagnostic's own line, located from its offset rather than by + // counting lines from the top of the file. + let mut at = (d.span.start as usize).min(self.src.len()); + while !self.src.is_char_boundary(at) { + at -= 1; + } + let (before, after) = self.src.split_at(at); + let start = before.rfind('\n').map_or(0, |i| i + 1); + let end = at + after.find('\n').unwrap_or(after.len()); + let line = &self.src[start..end]; + eprintln!( + "{severity}: {}\n --> {}:{}:{}\n |\n | {}\n", + d.message, + self.path.display(), + pos.line, + pos.col, + line.trim_end() + ); + } +} + +/// Where `check` and `lint` findings go: rustc-style text on stderr as +/// they arrive, or one JSON document on stdout when the run ends. +/// Findings are located by input-file index: `check` supplies it +/// directly, `lint` translates the engine's unit indexes (library +/// units first) through [`Sink::alias`]. +enum Sink<'a> { + Text(Vec>), + Json { + report: sysmlv2_lint::json::Report, + units: sysmlv2_lint::json::Units<'a>, + }, +} + +impl<'a> Sink<'a> { + fn new(format: ReportFormat, inputs: &'a [(PathBuf, String)]) -> Self { + match format { + ReportFormat::Text => Sink::Text( + inputs + .iter() + .map(|(path, src)| Reporter::new(path, src)) + .collect(), + ), + ReportFormat::Json => { + let mut units = sysmlv2_lint::json::Units::new(); + for (i, (path, src)) in inputs.iter().enumerate() { + units.add(i, path.display().to_string(), src); + } + Sink::Json { + report: sysmlv2_lint::json::Report::new(), + units, + } + } + } + } + + /// Engine unit `engine_unit` is input file `input`. + fn alias(&mut self, engine_unit: usize, input: usize) { + if let Sink::Json { units, .. } = self { + units.alias(engine_unit, input); + } + } + + /// A checker diagnostic from `stage` in input file `input`. + fn diagnostic(&mut self, stage: &str, input: usize, d: &Diagnostic) { + match self { + Sink::Text(reporters) => reporters[input].report(d), + Sink::Json { report, units } => report.push_diagnostic(stage, input, d, units), + } + } + + /// A lint finding; `input` is its unit as an input-file index + /// (`None` for a configuration finding, which has no location). + fn finding(&mut self, f: &sysmlv2_lint::Finding, input: Option) { + match self { + Sink::Text(reporters) => { + let message = format!("{} [{}]", f.message, f.rule); + match (input, f.span) { + (Some(input), Some(span)) => { + let diag = match f.severity { + sysmlv2_lint::Severity::Error => Diagnostic::error(span, message), + _ => Diagnostic::warning(span, message), + }; + reporters[input].report(&diag); + } + _ => eprintln!("warning: {message}"), + } + } + Sink::Json { report, units } => report.push_finding(f, units), + } + } + + /// Text findings already went out; a JSON report is written now. + fn finish(self) -> Result<(), ExitCode> { + let Sink::Json { report, .. } = self else { + return Ok(()); + }; + write_json(None, &report.into_value()) + } +} + +/// The `check`/`lint` exit status from the tallies. The count lines +/// belong to the text report; a JSON report carries its own summary. +fn verdict(errors: usize, warnings: usize, strict: bool, format: ReportFormat) -> ExitCode { + let text = format == ReportFormat::Text; + if warnings > 0 && text { + eprintln!("{warnings} warning(s)"); + } + if errors > 0 { + if text { + eprintln!("{errors} error(s)"); + } + ExitCode::FAILURE + } else if strict && warnings > 0 { + if text { + eprintln!("--strict: warnings are failures"); + } + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } +} + +fn read(path: &Path) -> Result { + if path == Path::new("-") { + let mut src = String::new(); + return std::io::Read::read_to_string(&mut std::io::stdin(), &mut src) + .map(|_| src) + .map_err(|e| { + eprintln!("error: cannot read stdin: {e}"); + ExitCode::FAILURE + }); + } + std::fs::read_to_string(path).map_err(|e| { + eprintln!("error: cannot read {}: {e}", path.display()); + ExitCode::FAILURE + }) +} + +/// Load a delta base: a compact element array from `.json` or `.s2c`. +fn load_base_value(path: &Path) -> Result { + if path.extension().and_then(|e| e.to_str()) == Some("s2c") { + let bytes = std::fs::read(path).map_err(|e| { + eprintln!("error: cannot read {}: {e}", path.display()); + ExitCode::FAILURE + })?; + sysmlv2_cbor::from_cbor(&bytes).map_err(|e| { + eprintln!("error: invalid base payload {}: {e}", path.display()); + ExitCode::FAILURE + }) + } else { + let text = read(path)?; + serde_json::from_str(&text).map_err(|e| { + eprintln!("error: invalid base JSON {}: {e}", path.display()); + ExitCode::FAILURE + }) + } +} + +/// The codec tables as one self-contained versioned JSON document: +/// everything a consumer needs to label s2c payload structure without +/// this toolkit — container magic, header version axes and flags, the +/// field-kind legend, both ordinal spaces (metaclass wire code = +/// array position, field ordinal = table position, both also spelled +/// explicitly), enum vocabularies, and each field's presence default +/// where the kind has one (bool, enum). Semantics live in `CBOR.md`. +fn codec_tables_doc() -> serde_json::Value { + use sysmlv2_cbor::tables; + let space = |set: &[(&str, &[tables::CborField])]| -> Vec { + set.iter() + .enumerate() + .map(|(code, (name, fields))| { + let fields: Vec = fields + .iter() + .enumerate() + .map(|(ordinal, (prop, kind, etbl, dflt))| { + let mut f = serde_json::Map::new(); + f.insert("prop".into(), serde_json::json!(prop)); + f.insert("ordinal".into(), serde_json::json!(ordinal)); + f.insert("kind".into(), serde_json::json!(kind)); + if *etbl != 255 { + f.insert("enum".into(), serde_json::json!(etbl)); + } + match *kind { + tables::K_BOOL => { + f.insert("default".into(), serde_json::json!(*dflt == 1)); + } + tables::K_ENUM => { + let value = if *dflt == 255 { + serde_json::Value::Null + } else { + serde_json::json!( + tables::ENUM_TABLES[*etbl as usize][*dflt as usize] + ) + }; + f.insert("default".into(), value); + } + _ => {} + } + serde_json::Value::Object(f) + }) + .collect(); + serde_json::json!({ "name": name, "code": code, "fields": fields }) + }) + .collect() + }; + let enums: Vec = tables::ENUM_NAMES + .iter() + .zip(tables::ENUM_TABLES) + .map(|(name, values)| serde_json::json!({ "name": name, "values": values })) + .collect(); + serde_json::json!({ + "magic": sysmlv2_cbor::MAGIC + .iter() + .map(|b| format!("{b:02x}")) + .collect::(), + "versions": { + "layout": sysmlv2_cbor::LAYOUT_VERSION, + "tables": tables::CBOR_TABLES_VERSION, + "scheme": sysmlv2_cbor::ID_SCHEME_VERSION, + }, + "flags": { + "elideIds": sysmlv2_cbor::FLAG_ELIDE_IDS, + "fullForm": sysmlv2_cbor::FLAG_FULL_FORM, + "delta": sysmlv2_cbor::FLAG_DELTA, + "deltaPortable": sysmlv2_cbor::FLAG_DELTA_PORTABLE, + "unitPaths": sysmlv2_cbor::FLAG_UNIT_PATHS, + "impliedOwners": sysmlv2_cbor::FLAG_IMPLIED_OWNERS, + }, + "kinds": { + "bool": tables::K_BOOL, + "str": tables::K_STR, + "strList": tables::K_STR_LIST, + "ref": tables::K_REF, + "refList": tables::K_REF_LIST, + "enum": tables::K_ENUM, + "literal": tables::K_LITERAL, + "elementId": tables::K_ELEMENT_ID, + }, + "enums": enums, + "metaclasses": space(tables::METACLASS_FIELDS), + "fullMetaclasses": space(tables::FULL_METACLASS_FIELDS), + }) +} + +/// A snapshot payload exactly as the file carries it: `.s2c` decodes +/// (id-elided snapshots re-derive their ids through `names` — a +/// digest-gated recovery, still payload identity), anything else +/// parses as a compact interchange element array. Never lifts — the +/// producer's ids are authoritative. +fn load_snapshot_value( + path: &Path, + names: &HashMap, +) -> Result { + let value = if path.extension().and_then(|e| e.to_str()) == Some("s2c") { + let bytes = std::fs::read(path).map_err(|e| { + eprintln!("error: cannot read {}: {e}", path.display()); + ExitCode::FAILURE + })?; + decode_snapshot(&bytes, names).map_err(|e| { + eprintln!("error: invalid snapshot payload {}: {e}", path.display()); + ExitCode::FAILURE + })? + } else { + let text = read(path)?; + serde_json::from_str(&text).map_err(|e| { + eprintln!("error: invalid snapshot JSON {}: {e}", path.display()); + ExitCode::FAILURE + })? + }; + if !value.is_array() { + eprintln!( + "error: {}: not a snapshot (compact element array)", + path.display() + ); + return Err(ExitCode::FAILURE); + } + Ok(value) +} + +/// Decode snapshot CBOR to its compact element array; id-elided +/// payloads re-derive their ids with library targets named through +/// `names`. +fn decode_snapshot( + bytes: &[u8], + names: &HashMap, +) -> Result { + match sysmlv2_cbor::from_cbor(bytes) { + Err(e) if e.to_string().contains("elided") => { + sysmlv2_cbor::from_cbor_with(bytes, &|s| names.get(s).cloned()) + } + other => other, + } +} + +/// State digest of a snapshot file (compact `.json` or `.s2c`) — +/// `None` when the file is not a snapshot this build decodes (a +/// delta, foreign JSON, another format entirely). +fn snapshot_file_digest(path: &Path, names: &HashMap) -> Option { + let value = if path.extension().and_then(|e| e.to_str()) == Some("s2c") { + decode_snapshot(&std::fs::read(path).ok()?, names).ok()? + } else { + serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()? + }; + if !value.is_array() { + return None; + } + Some(sysmlv2_cbor::state_digest(&value).ok()?.to_string()) +} + +/// Payload-looking files (`.s2c` / `.json`) under `dir`, recursively, +/// in sorted order. +fn payload_files_under(dir: &Path) -> Vec { + let mut out = Vec::new(); + let mut stack = vec![dir.to_path_buf()]; + while let Some(d) = stack.pop() { + let Ok(entries) = std::fs::read_dir(&d) else { + continue; + }; + for entry in entries.flatten() { + let p = entry.path(); + if p.is_dir() { + stack.push(p); + } else if matches!(p.extension().and_then(|e| e.to_str()), Some("s2c" | "json")) { + out.push(p); + } + } + } + out.sort(); + out +} + +/// `elementId → last qualified-name segment` for the standard +/// library at `lib` (empty without one) — the resolver id-derivation +/// surfaces (elision, elided deltas) name external targets with. +fn load_library_id_names( + lib: Option<&Path>, +) -> Result, ExitCode> { + let Some(dir) = lib else { + return Ok(Default::default()); + }; + let mut model = Model::new(); + match load_library(&mut model, dir) { + Ok(cache) => { + let names = library_name_map(&model) + .into_iter() + .filter_map(|(id, segs)| segs.last().cloned().map(|n| (id.to_string(), n))) + .collect(); + save_library_cache(&model, cache); + Ok(names) + } + Err(e) => { + eprintln!("error: cannot load library {}: {e}", dir.display()); + Err(ExitCode::FAILURE) + } + } +} + +/// Re-key a unit-structure table (compact element indices → paths) +/// onto another emission of the same model, matching unit roots by +/// element id. Identity when `target` is the compact array itself. +fn remap_units( + compact: &serde_json::Value, + units: &[(usize, String)], + target: &serde_json::Value, +) -> Vec<(usize, String)> { + let id_of = |arr: &serde_json::Value, i: usize| -> Option { + arr.get(i)?.get("@id")?.as_str().map(str::to_owned) + }; + let by_id: std::collections::HashMap = target + .as_array() + .map(|arr| { + arr.iter() + .enumerate() + .filter_map(|(i, e)| { + e.get("@id") + .and_then(|v| v.as_str()) + .map(|s| (s.to_owned(), i)) + }) + .collect() + }) + .unwrap_or_default(); + let mut out: Vec<(usize, String)> = units + .iter() + .filter_map(|(i, path)| { + by_id + .get(&id_of(compact, *i)?) + .map(|&ti| (ti, path.clone())) + }) + .collect(); + out.sort_by_key(|&(i, _)| i); + out +} + +/// One verb's stdout, locked once for the run. Output into a pipe or a +/// file is fully buffered, so per-line writes cost no system calls; a +/// terminal keeps the standard stream's line buffering, so verdicts and +/// results still appear as they are produced. +fn stdout_writer() -> Box { + let stdout = io::stdout(); + if stdout.is_terminal() { + Box::new(stdout.lock()) + } else { + Box::new(BufWriter::new(stdout.lock())) + } +} + +/// Map the outcome of writing to stdout onto the run: a reader that +/// closed the pipe (`… | head`) wanted no more output, so the run ends +/// quietly and successfully; any other write failure is reported and +/// fails it. Every stdout write, and the final flush, goes through here. +fn stdout_result(written: io::Result<()>) -> Result<(), ExitCode> { + match written { + Ok(()) => Ok(()), + Err(e) if e.kind() == io::ErrorKind::BrokenPipe => Err(ExitCode::SUCCESS), + Err(e) => { + eprintln!("error: cannot write stdout: {e}"); + Err(ExitCode::FAILURE) + } + } +} + +/// The exit status of a run whose last step is `outcome`: the code that +/// ended it early, else success. +fn exit_status(outcome: Result<(), ExitCode>) -> ExitCode { + outcome.err().unwrap_or(ExitCode::SUCCESS) +} + +/// Write one whole output document — CBOR bytes, textual notation, a +/// diagram — to a file or to stdout. +fn write_bytes(output: Option<&Path>, bytes: &[u8]) -> Result<(), ExitCode> { + match output { + Some(out) => std::fs::write(out, bytes).map_err(|e| { + eprintln!("error: cannot write {}: {e}", out.display()); + ExitCode::FAILURE + }), + None => { + let mut out = stdout_writer(); + stdout_result(out.write_all(bytes).and_then(|()| out.flush())) + } + } +} + +/// Write one JSON document, pretty-printed with a trailing newline, to +/// a file or to stdout — serialized straight into the destination, never +/// through an intermediate string of the whole document. +fn write_json(output: Option<&Path>, value: &serde_json::Value) -> Result<(), ExitCode> { + fn emit(w: &mut dyn Write, value: &serde_json::Value) -> io::Result<()> { + serde_json::to_writer_pretty(&mut *w, value)?; + w.write_all(b"\n")?; + w.flush() + } + match output { + Some(path) => std::fs::File::create(path) + .and_then(|file| emit(&mut BufWriter::new(file), value)) + .map_err(|e| { + eprintln!("error: cannot write {}: {e}", path.display()); + ExitCode::FAILURE + }), + None => { + let mut out = stdout_writer(); + stdout_result(emit(out.as_mut(), value)) + } + } +} + +/// The interchange document of a JSON-shaped conversion input: the +/// payload a binary input already decoded to, or `text` parsed once. +fn json_input( + decoded: Option, + text: &str, +) -> Result { + if let Some(value) = decoded { + return Ok(value); + } + serde_json::from_str(text).map_err(|e| { + eprintln!("error: invalid JSON: {e}"); + ExitCode::FAILURE + }) +} + +/// Read command inputs, expanding `.kpar` project archives (KerML 10.3) +/// into their contained textual units. Checksum mismatches against the +/// archive's `.meta.json` warn but do not fail. +fn read_inputs(paths: &[PathBuf]) -> Result, ExitCode> { + let mut out = Vec::new(); + for path in paths { + if path.extension().and_then(|e| e.to_str()) == Some("kpar") { + let bytes = std::fs::read(path).map_err(|e| { + eprintln!("error: cannot read {}: {e}", path.display()); + ExitCode::FAILURE + })?; + let archive = kpar::read(&bytes).map_err(|e| { + eprintln!("error: {}: {e}", path.display()); + ExitCode::FAILURE + })?; + for name in &archive.checksum_mismatches { + eprintln!( + "warning: {}: `{name}` does not match its .meta.json checksum", + path.display() + ); + } + for unit in archive.units { + out.push((path.join(&unit.file_name), unit.source)); + } + } else { + out.push((path.clone(), read(path)?)); + } + } + Ok(out) +} + +/// The ambient model context: when a verb's file +/// inputs are omitted and this variable names a directory, the +/// directory's `.sysml`/`.kerml` files form the model. Explicit inputs +/// always win — the variable only fills an absence. +const MODEL_DIR_VAR: &str = "SYSMLV2_MODEL_DIR"; + +/// Collect the model files under `dir`, depth-first with siblings in +/// name order, so unit order (and everything downstream of it) is +/// deterministic. Hidden entries are skipped; directory symlinks are +/// not followed (files reached through a symlinked name still count). +fn discover_model_files(dir: &Path) -> std::io::Result> { + fn walk(dir: &Path, out: &mut Vec) -> std::io::Result<()> { + let mut entries: Vec<_> = std::fs::read_dir(dir)?.collect::>()?; + entries.sort_by_key(|e| e.file_name()); + for entry in entries { + if entry.file_name().to_string_lossy().starts_with('.') { + continue; + } + let path = entry.path(); + if entry.file_type()?.is_dir() { + walk(&path, out)?; + } else if matches!( + path.extension().and_then(|e| e.to_str()), + Some("sysml" | "kerml") + ) { + out.push(path); + } + } + Ok(()) + } + let mut out = Vec::new(); + walk(dir, &mut out)?; + Ok(out) +} + +/// Resolve a verb's input files: explicit paths pass through untouched; +/// an empty list falls back to the ambient model directory (with a +/// provenance note on stderr, suppressed by --quiet, so output never +/// silently depends on ambient state); with neither, the error names +/// both remedies. +fn resolve_inputs(explicit: Vec, quiet: bool) -> Result, ExitCode> { + if !explicit.is_empty() { + return Ok(explicit); + } + let Some(dir) = std::env::var_os(MODEL_DIR_VAR).filter(|v| !v.is_empty()) else { + eprintln!( + "error: no input files — provide input files, or set \ + {MODEL_DIR_VAR} to a model directory" + ); + return Err(ExitCode::FAILURE); + }; + let dir = PathBuf::from(dir); + let files = discover_model_files(&dir).map_err(|e| { + eprintln!( + "error: cannot read {MODEL_DIR_VAR} directory {}: {e}", + dir.display() + ); + ExitCode::FAILURE + })?; + if files.is_empty() { + eprintln!( + "error: no .sysml/.kerml files under {} ({MODEL_DIR_VAR})", + dir.display() + ); + return Err(ExitCode::FAILURE); + } + if !quiet { + eprintln!( + "sysmlv2: model = {} file{} from {} ({MODEL_DIR_VAR})", + files.len(), + if files.len() == 1 { "" } else { "s" }, + dir.display() + ); + } + Ok(files) +} + +/// Shared front half of the inspection verbs (describe/members): the +/// eval/query positional convention — arguments ending in a model +/// extension are files, the leading positional joins that +/// classification (an existing *file* path counts as a file — a +/// directory or case-folded match does not), exactly one +/// non-file argument remains as the qualified name — then ambient +/// fallback, library load, parse gate, and model resolution. +/// Split a verb's positional arguments into model files and whatever +/// else it takes — names, a query expression. An argument spelled with +/// a model extension (or `-`) is a file; so is the leading positional +/// when it names an existing file, which is what lets +/// `sysmlv2 eval Demo::mass` be all names under an ambient model +/// directory. +pub fn split_files_and_names( + input: Option, + args: Vec, +) -> (Vec, Vec) { + let is_file = |s: &str| is_model_source(s) || s == "-"; + let (extra_files, mut rest): (Vec, Vec) = + args.into_iter().partition(|a| is_file(a)); + let mut files: Vec = Vec::new(); + if let Some(input) = input { + let s = input.display().to_string(); + if is_file(&s) || input.is_file() { + files.push(input); + } else { + rest.insert(0, s); + } + } + files.extend(extra_files.iter().map(PathBuf::from)); + (files, rest) +} + +/// A model as the command line named it: the files it was read from +/// with their text (project archives expanded into their units), the +/// model they parsed into, and where the standard library ends in its +/// unit order. +pub struct LoadedModel { + pub model: Model, + /// Each input as it was read, project archives expanded into their + /// units — the text a diagnostic is located in. + pub sources: Vec<(PathBuf, String)>, + /// Units before this index belong to the standard library. + pub boundary: usize, + lib_cache: Option, +} + +impl LoadedModel { + /// The resolved view every name-resolving verb works through, and + /// the library-cache write that ends the prologue. + pub fn into_resolved(self) -> sysmlv2_parser::json::ResolvedModel { + let resolved = sysmlv2_parser::json::ResolvedModel::build(&self.model); + save_library_cache(&self.model, self.lib_cache); + resolved + } +} + +/// The prologue every model verb shares: settle the input files (an +/// ambient model directory fills an absence), load the standard library +/// when one was named, and parse every input into one model. Parse +/// diagnostics are reported against their own file and end the run. +pub fn load_model( + files: Vec, + lib: Option<&Path>, + quiet: bool, +) -> Result { + let files = resolve_inputs(files, quiet)?; + let mut model = Model::new(); + let mut lib_cache = None; + if let Some(lib) = lib { + lib_cache = load_library(&mut model, lib) + .map_err(|e| fail(format!("cannot load library {}: {e}", lib.display())))?; + } + // Unit indices: the library's units first, then the inputs in order. + let boundary = model.unit_count(); + let sources = read_inputs(&files)?; + let mut ill_formed = false; + for (path, src) in &sources { + let unit = model.add_source(path.display().to_string(), src); + if !unit.diagnostics.is_empty() { + let diags = unit.diagnostics.clone(); + report(path, src, &diags); + ill_formed = true; + } + } + if ill_formed { + return Err(CliError::Reported(ExitCode::FAILURE)); + } + Ok(LoadedModel { + model, + sources, + boundary, + lib_cache, + }) +} + +fn resolve_model_and_name( + input: Option, + args: Vec, + lib: Option<&Path>, + quiet: bool, +) -> Result<(sysmlv2_parser::json::ResolvedModel, String), CliError> { + let (files, names) = split_files_and_names(input, args); + let [qname] = names.as_slice() else { + return Err(fail(format!( + "expected exactly one qualified name, got {}", + names.len() + ))); + }; + let qname = qname.clone(); + Ok((load_model(files, lib, quiet)?.into_resolved(), qname)) +} + +/// `refactor split`: plan, then either print the plan and the resulting +/// texts (dry run) or commit and write the changed root file and the new +/// files, refusing to overwrite a file that already exists. +fn run_split( + input: Option, + args: Vec, + dry_run: bool, + slug: bool, + dir: Option, + lib: Option<&Path>, + quiet: bool, +) -> ExitCode { + let (mut session, qname) = match refactor_session(input, args, lib, dry_run, quiet) { + Ok(v) => v, + Err(code) => return code, + }; + let Some(root) = session.resolved().resolve_qualified(&qname) else { + eprintln!("error: cannot resolve `{qname}`"); + return ExitCode::FAILURE; + }; + let options = sysmlv2_transform::SplitOptions { + naming: if slug { + sysmlv2_transform::SplitNaming::Slug + } else { + sysmlv2_transform::SplitNaming::Keep + }, + directory: dir, + uri_units: false, + }; + let plan = match session.split_plan(root, &options) { + Ok(p) => p, + Err(e) => { + eprintln!("error: {e}"); + return ExitCode::FAILURE; + } + }; + if !quiet || dry_run { + for entry in &plan.entries { + let renamed = entry + .new_name + .as_deref() + .map(|n| format!(" (renamed to `{n}`, aliased in `{qname}`)")) + .unwrap_or_default(); + eprintln!( + "{}: `{}` ({} bytes){renamed}", + entry.unit, entry.qualified, entry.bytes + ); + } + } + for path in plan.entries.iter().map(|e| Path::new(&e.unit)) { + if !dry_run && path.exists() { + eprintln!("error: {} already exists — not overwriting", path.display()); + return ExitCode::FAILURE; + } + } + let before: Vec<(String, String)> = session + .units() + .map(|(_, n, s)| (n.to_string(), s.to_string())) + .collect(); + let mut edit = session.edit(); + edit.split(&plan); + let result = if dry_run { edit.check() } else { edit.commit() }; + let report = match result { + Ok(r) => r, + Err(e) => { + eprintln!("error: {e}"); + return ExitCode::FAILURE; + } + }; + for f in &report.findings { + eprintln!("note: {f}"); + } + if dry_run { + let mut out = stdout_writer(); + let written = (|| -> io::Result<()> { + for entry in &plan.entries { + let text: String = report + .splices + .iter() + .filter(|s| s.unit == entry.unit) + .map(|s| s.text.as_str()) + .collect(); + writeln!(out, "--- {} (new)\n{text}", entry.unit)?; + } + for (unit_name, old) in &before { + let mut spl: Vec<_> = report + .splices + .iter() + .filter(|s| s.unit == *unit_name) + .collect(); + if spl.is_empty() { + continue; + } + spl.sort_by_key(|s| s.start); + let mut new = String::with_capacity(old.len()); + let mut cursor = 0usize; + for s in &spl { + new.push_str(&old[cursor..s.start as usize]); + new.push_str(&s.text); + cursor = s.end as usize; + } + new.push_str(&old[cursor..]); + write_unit_diff(out.as_mut(), unit_name, old, &new)?; + } + out.flush() + })(); + return exit_status(stdout_result(written)); + } + // New files first — a failure here leaves the root untouched, and + // the files this run already created are removed again so the tree + // never holds a package twice. + let mut created: Vec = Vec::new(); + let mut made_dirs: Vec = Vec::new(); + fn undo(created: &[PathBuf], made_dirs: &[PathBuf]) { + for path in created { + if std::fs::remove_file(path).is_ok() { + eprintln!("removed {}", path.display()); + } + } + // Directories this run made, deepest first; a non-empty one stays. + for dir in made_dirs.iter().rev() { + let _ = std::fs::remove_dir(dir); + } + } + for (unit, text) in session + .units() + .filter(|(_, n, _)| plan.entries.iter().any(|e| e.unit == *n)) + .map(|(_, n, s)| (n.to_string(), s.to_string())) + { + let path = PathBuf::from(&unit); + if let Some(parent) = path.parent() { + // Every ancestor `create_dir_all` is about to make. They + // arrive deepest first and are recorded shallowest first, + // which is the order the undo above unwinds. + let from = made_dirs.len(); + made_dirs.extend( + parent + .ancestors() + .take_while(|a| !a.as_os_str().is_empty() && !a.exists()) + .map(Path::to_path_buf), + ); + made_dirs[from..].reverse(); + if let Err(e) = std::fs::create_dir_all(parent) { + eprintln!("error: cannot create {}: {e}", parent.display()); + undo(&created, &made_dirs); + return ExitCode::FAILURE; + } + } + let mut file = match OpenOptions::new().write(true).create_new(true).open(&path) { + Ok(f) => f, + Err(e) => { + eprintln!("error: cannot create {}: {e}", path.display()); + undo(&created, &made_dirs); + return ExitCode::FAILURE; + } + }; + // Ours from here on: a failed write must not leave a stub behind. + created.push(path.clone()); + if let Err(e) = file.write_all(text.as_bytes()) { + eprintln!("error: cannot write {}: {e}", path.display()); + undo(&created, &made_dirs); + return ExitCode::FAILURE; + } + if !quiet { + eprintln!("created {}", path.display()); + } + } + let changes: Vec = before + .iter() + .filter_map(|(unit_name, old)| { + let (_, _, new) = session.units().find(|(_, n, _)| *n == unit_name)?; + (old != new).then(|| RefactorFileChange { + path: PathBuf::from(unit_name), + old: old.clone(), + new: new.to_string(), + }) + }) + .collect(); + match persist_refactor_changes(&changes) { + Ok(warnings) => { + for warning in warnings { + eprintln!("warning: {warning}"); + } + } + Err(e) => { + eprintln!("error: the root file was not rewritten: {e}"); + undo(&created, &made_dirs); + return ExitCode::FAILURE; + } + } + if !quiet { + for change in &changes { + eprintln!("split `{qname}` — rewrote {}", change.path.display()); + } + } + ExitCode::SUCCESS +} + +/// The refactor verbs' front half: the describe/members positional +/// convention (files + exactly one qualified name), the fmt write +/// discipline (ambient inputs drive `--dry-run` only; stdin never), +/// then a transform `Session` over the files with the library loaded. +fn refactor_session( + input: Option, + args: Vec, + lib: Option<&Path>, + dry_run: bool, + quiet: bool, +) -> Result<(sysmlv2_transform::Session, String), ExitCode> { + let is_file = |s: &str| is_model_source(s) || s == "-"; + let (extra_files, mut names): (Vec, Vec) = + args.into_iter().partition(|a| is_file(a)); + let mut files: Vec = Vec::new(); + if let Some(input) = input { + let s = input.display().to_string(); + if is_file(&s) || input.is_file() { + files.push(input); + } else { + names.insert(0, s); + } + } + files.extend(extra_files.iter().map(PathBuf::from)); + let [qname] = names.as_slice() else { + eprintln!( + "error: expected exactly one qualified name, got {}", + names.len() + ); + return Err(ExitCode::FAILURE); + }; + let qname = qname.clone(); + if files.iter().any(|f| f == Path::new("-")) { + eprintln!("error: stdin (`-`) cannot be rewritten in place; pass file paths"); + return Err(ExitCode::FAILURE); + } + if files.is_empty() && !dry_run { + eprintln!( + "error: no input files — refactor rewrites files in place, so ambient \ + {MODEL_DIR_VAR} inputs apply to --dry-run only; pass explicit paths" + ); + return Err(ExitCode::FAILURE); + } + let files = resolve_inputs(files, quiet)?; + let mut sources = Vec::new(); + for path in &files { + let src = read(path)?; + sources.push((path.display().to_string(), src)); + } + let mut session = match sysmlv2_transform::Session::from_sources(sources.clone()) { + Ok(s) => s, + Err(sysmlv2_transform::SessionError::Parse { unit, diagnostics }) => { + match sources.iter().find(|(n, _)| *n == unit) { + Some((_, src)) => report(Path::new(&unit), src, &diagnostics), + None => eprintln!("error: {unit} does not parse"), + } + return Err(ExitCode::FAILURE); + } + Err(e) => { + eprintln!("error: {e}"); + return Err(ExitCode::FAILURE); + } + }; + if let Some(lib) = lib { + if let Err(e) = session.load_library(lib) { + eprintln!("error: cannot load library {}: {e}", lib.display()); + return Err(ExitCode::FAILURE); + } + } + Ok((session, qname)) +} + +/// Execute one refactor direction: resolve the name, run the verified +/// edit (dry runs go through the same pipeline against copies), print +/// findings as `note:` lines, then either print the would-be diff or +/// write every changed unit back in place. +fn run_refactor(op: RefactorOp, quiet: bool) -> ExitCode { + let (input, args, name, dry_run, lib, is_extract) = match op { + RefactorOp::Split { + input, + args, + dry_run, + slug, + dir, + lib, + } => return run_split(input, args, dry_run, slug, dir, lib.as_deref(), quiet), + RefactorOp::Extract { + input, + args, + name, + dry_run, + lib, + } => (input, args, name, dry_run, lib, true), + RefactorOp::Inline { + input, + args, + dry_run, + lib, + } => (input, args, None, dry_run, lib, false), + }; + let (mut session, qname) = match refactor_session(input, args, lib.as_deref(), dry_run, quiet) { + Ok(v) => v, + Err(code) => return code, + }; + let Some(target) = session.resolved().resolve_qualified(&qname) else { + eprintln!("error: cannot resolve `{qname}`"); + return ExitCode::FAILURE; + }; + // Summary facts read before the edit — a commit advances the session. + let summary = if is_extract { + let def_name = match &name { + Some(n) => n.clone(), + None => session + .resolved() + .element_name(target) + .map(sysmlv2_transform::synthesized_definition_name) + .unwrap_or_default(), + }; + format!( + "extracted '{}' from `{qname}`", + sysmlv2_transform::spell_name(&def_name) + ) + } else { + format!("inlined `{qname}`") + }; + let before: Vec<(String, String)> = session + .units() + .map(|(_, n, s)| (n.to_string(), s.to_string())) + .collect(); + let mut edit = session.edit(); + if is_extract { + edit.extract_definition(target, name.as_deref()); + } else { + edit.inline_definition(target); + } + let result = if dry_run { edit.check() } else { edit.commit() }; + let report = match result { + Ok(r) => r, + Err(e) => { + eprintln!("error: {e}"); + return ExitCode::FAILURE; + } + }; + if dry_run { + for f in &report.findings { + eprintln!("note: {f}"); + } + let mut out = stdout_writer(); + let written = (|| -> io::Result<()> { + for (unit_name, old) in &before { + let mut spl: Vec<_> = report + .splices + .iter() + .filter(|s| s.unit == *unit_name) + .collect(); + if spl.is_empty() { + continue; + } + spl.sort_by_key(|s| s.start); + let mut new = String::with_capacity(old.len()); + let mut cursor = 0usize; + for s in &spl { + new.push_str(&old[cursor..s.start as usize]); + new.push_str(&s.text); + cursor = s.end as usize; + } + new.push_str(&old[cursor..]); + write_unit_diff(out.as_mut(), unit_name, old, &new)?; + } + out.flush() + })(); + return exit_status(stdout_result(written)); + } + let after: Vec<(String, String)> = session + .units() + .map(|(_, n, s)| (n.to_string(), s.to_string())) + .collect(); + if before.len() != after.len() + || before + .iter() + .zip(&after) + .any(|((before_name, _), (after_name, _))| before_name != after_name) + { + eprintln!("error: internal refactor failure: session unit order changed"); + return ExitCode::FAILURE; + } + let changes: Vec = before + .iter() + .zip(&after) + .filter(|((_, old), (_, new))| old != new) + .map(|((unit_name, old), (_, new))| RefactorFileChange { + path: PathBuf::from(unit_name), + old: old.clone(), + new: new.clone(), + }) + .collect(); + let cleanup_warnings = match persist_refactor_changes(&changes) { + Ok(warnings) => warnings, + Err(e) => { + eprintln!("error: refactor was not written: {e}"); + return ExitCode::FAILURE; + } + }; + for f in &report.findings { + eprintln!("note: {f}"); + } + for warning in cleanup_warnings { + eprintln!("warning: {warning}"); + } + if !quiet { + for change in &changes { + eprintln!("{summary} — rewrote {}", change.path.display()); + } + } + ExitCode::SUCCESS +} + +/// One changed user unit waiting to be persisted after the transform +/// engine has committed and verified the whole model in memory. +#[derive(Debug)] +struct RefactorFileChange { + path: PathBuf, + old: String, + new: String, +} + +#[derive(Debug)] +struct StagedRefactorFile { + display_path: PathBuf, + target: PathBuf, + new_path: PathBuf, + backup_path: PathBuf, +} + +#[derive(Debug)] +struct RefactorFileMetadata { + permissions: Permissions, + #[cfg(all(unix, not(target_os = "wasi")))] + uid: u32, + #[cfg(all(unix, not(target_os = "wasi")))] + gid: u32, + #[cfg(all(unix, not(target_os = "wasi")))] + xattrs: Vec<(std::ffi::OsString, Vec)>, +} + +/// Persist a verified multi-file refactor as one recoverable operation: +/// preflight every target, stage both new text and rollback copies beside +/// their files, recheck for concurrent changes, then replace. A failed +/// replacement restores unchanged earlier targets and retains a recovery +/// copy rather than knowingly overwriting a later external edit. +fn persist_refactor_changes(changes: &[RefactorFileChange]) -> Result, String> { + persist_refactor_changes_with(changes, |from, to| std::fs::rename(from, to)) +} + +fn persist_refactor_changes_with( + changes: &[RefactorFileChange], + mut replace: impl FnMut(&Path, &Path) -> std::io::Result<()>, +) -> Result, String> { + let mut prepared = Vec::with_capacity(changes.len()); + let mut write_guards = Vec::with_capacity(changes.len()); + let mut targets = HashSet::with_capacity(changes.len()); + for change in changes { + let target = refactor_target_path(&change.path).map_err(|e| { + format!( + "cannot resolve {} before writing: {e}", + change.path.display() + ) + })?; + if !targets.insert(target.clone()) { + return Err(format!( + "{} names the same file more than once", + change.path.display() + )); + } + let current = std::fs::read(&target).map_err(|e| { + format!( + "cannot reread {} before writing: {e}", + change.path.display() + ) + })?; + if current != change.old.as_bytes() { + return Err(format!( + "{} changed on disk while the refactor was running", + change.path.display() + )); + } + let guard = OpenOptions::new() + .write(true) + .open(&target) + .map_err(|e| format!("cannot open {} for writing: {e}", change.path.display()))?; + let metadata = refactor_file_metadata(&guard) + .map_err(|e| format!("cannot inspect {}: {e}", change.path.display()))?; + prepared.push((target, metadata)); + write_guards.push(guard); + } + + let mut staged = Vec::with_capacity(changes.len()); + for (change, (target, metadata)) in changes.iter().zip(&prepared) { + let new_path = match write_refactor_sidecar(target, "new", &change.new, metadata) { + Ok(path) => path, + Err(e) => { + cleanup_refactor_sidecars(&staged, &HashSet::new()); + return Err(format!( + "cannot stage {} before writing: {e}", + change.path.display() + )); + } + }; + let backup_path = match write_refactor_sidecar(target, "old", &change.old, metadata) { + Ok(path) => path, + Err(e) => { + let _ = std::fs::remove_file(&new_path); + cleanup_refactor_sidecars(&staged, &HashSet::new()); + return Err(format!( + "cannot stage rollback copy for {}: {e}", + change.path.display() + )); + } + }; + staged.push(StagedRefactorFile { + display_path: change.path.clone(), + target: target.clone(), + new_path, + backup_path, + }); + } + drop(write_guards); + + // Staging may take time: refuse to overwrite an editor or process + // that changed a source after the first preflight read. + for (change, entry) in changes.iter().zip(&staged) { + match std::fs::read(&entry.target) { + Ok(current) if current == change.old.as_bytes() => {} + Ok(_) => { + cleanup_refactor_sidecars(&staged, &HashSet::new()); + return Err(format!( + "{} changed on disk while the refactor was being staged", + entry.display_path.display() + )); + } + Err(e) => { + cleanup_refactor_sidecars(&staged, &HashSet::new()); + return Err(format!( + "cannot recheck {} before writing: {e}", + entry.display_path.display() + )); + } + } + } + + for (applied, (change, entry)) in changes.iter().zip(&staged).enumerate() { + // Check each target again immediately before its replacement. This + // catches an editor save that races the earlier all-file recheck; + // previously replaced files still roll back, while the external + // edit remains untouched. + let write_error = match std::fs::read(&entry.target) { + Ok(current) if current != change.old.as_bytes() => Some(format!( + "{} changed on disk before it could be replaced", + entry.display_path.display() + )), + Err(e) => Some(format!( + "cannot recheck {} before replacement: {e}", + entry.display_path.display() + )), + Ok(_) => replace(&entry.new_path, &entry.target) + .err() + .map(|e| format!("cannot replace {}: {e}", entry.display_path.display())), + }; + if let Some(write_error) = write_error { + let mut retained_backups = HashSet::new(); + let mut rollback_errors = Vec::new(); + for previous_index in (0..applied).rev() { + let previous = &staged[previous_index]; + let rollback_error = match std::fs::read(&previous.target) { + Ok(current) if current != changes[previous_index].new.as_bytes() => Some( + "changed after the refactor replaced it; external edit was preserved" + .to_string(), + ), + Err(e) => Some(format!("cannot recheck before rollback: {e}")), + Ok(_) => replace(&previous.backup_path, &previous.target) + .err() + .map(|e| e.to_string()), + }; + if let Some(e) = rollback_error { + retained_backups.insert(previous.backup_path.clone()); + rollback_errors.push(format!( + "{} ({e}; recovery copy: {})", + previous.display_path.display(), + previous.backup_path.display() + )); + } + } + cleanup_refactor_sidecars(&staged, &retained_backups); + let mut message = write_error; + if rollback_errors.is_empty() { + use std::fmt::Write as _; + let _ = write!(message, "; rolled back {applied} earlier file(s)"); + } else { + message.push_str("; rollback incomplete for "); + message.push_str(&rollback_errors.join(", ")); + } + return Err(message); + } + } + + let mut warnings = Vec::new(); + for entry in &staged { + if let Err(e) = std::fs::remove_file(&entry.backup_path) { + warnings.push(format!( + "could not remove rollback copy {}: {e}", + entry.backup_path.display() + )); + } + } + Ok(warnings) +} + +#[cfg(not(target_os = "wasi"))] +fn refactor_target_path(path: &Path) -> std::io::Result { + // Follow symlinks before replacing the file so an in-place refactor + // retains the link instead of replacing the directory entry itself. + std::fs::canonicalize(path) +} + +#[cfg(target_os = "wasi")] +fn refactor_target_path(path: &Path) -> std::io::Result { + // WASI preview1 preopen paths are already capability-resolved and + // canonicalize is unsupported by Node's WASI filesystem adapter. + Ok(path.to_path_buf()) +} + +fn write_refactor_sidecar( + target: &Path, + kind: &str, + text: &str, + metadata: &RefactorFileMetadata, +) -> std::io::Result { + let parent = target.parent().unwrap_or_else(|| Path::new(".")); + let file_name = target.file_name().ok_or_else(|| { + std::io::Error::new(std::io::ErrorKind::InvalidInput, "target has no file name") + })?; + for _ in 0..16 { + let mut sidecar_name = std::ffi::OsString::from("."); + sidecar_name.push(file_name); + sidecar_name.push(format!(".sysmlv2-{kind}-{}", uuid::Uuid::new_v4())); + let path = parent.join(sidecar_name); + let mut options = OpenOptions::new(); + options.write(true).create_new(true); + #[cfg(unix)] + { + use std::os::unix::fs::OpenOptionsExt; + options.mode(0o600); + } + match options.open(&path) { + Ok(mut file) => { + let result = (|| { + file.write_all(text.as_bytes())?; + set_refactor_sidecar_metadata(&file, metadata)?; + file.sync_all() + })(); + if let Err(e) = result { + drop(file); + let _ = std::fs::remove_file(&path); + return Err(e); + } + return Ok(path); + } + Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => continue, + Err(e) => return Err(e), + } + } + Err(std::io::Error::new( + std::io::ErrorKind::AlreadyExists, + "could not allocate a unique sidecar name", + )) +} + +fn refactor_file_metadata(file: &std::fs::File) -> std::io::Result { + let metadata = file.metadata()?; + #[cfg(all(unix, not(target_os = "wasi")))] + { + use std::os::unix::fs::MetadataExt; + use xattr::FileExt; + + if metadata.nlink() != 1 { + return Err(std::io::Error::other(format!( + "has {} hard links; refusing to split linked paths during atomic replacement", + metadata.nlink() + ))); + } + let mut xattrs = Vec::new(); + match file.list_xattr() { + Ok(names) => { + for name in names { + if let Some(value) = file.get_xattr(&name)? { + xattrs.push((name, value)); + } + } + } + Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {} + Err(e) => return Err(e), + } + Ok(RefactorFileMetadata { + permissions: metadata.permissions(), + uid: metadata.uid(), + gid: metadata.gid(), + xattrs, + }) + } + #[cfg(not(all(unix, not(target_os = "wasi"))))] + Ok(RefactorFileMetadata { + permissions: metadata.permissions(), + }) +} + +#[cfg(all(unix, not(target_os = "wasi")))] +fn set_refactor_sidecar_metadata( + file: &std::fs::File, + metadata: &RefactorFileMetadata, +) -> std::io::Result<()> { + use std::os::unix::fs::fchown; + use xattr::FileExt; + + fchown(file, Some(metadata.uid), Some(metadata.gid))?; + for (name, value) in &metadata.xattrs { + file.set_xattr(name, value)?; + } + file.set_permissions(metadata.permissions.clone()) +} + +#[cfg(all(not(unix), not(target_os = "wasi")))] +fn set_refactor_sidecar_metadata( + file: &std::fs::File, + metadata: &RefactorFileMetadata, +) -> std::io::Result<()> { + file.set_permissions(metadata.permissions.clone()) +} + +#[cfg(target_os = "wasi")] +fn set_refactor_sidecar_metadata( + _file: &std::fs::File, + _metadata: &RefactorFileMetadata, +) -> std::io::Result<()> { + // WASI preview1 has no chmod-equivalent. Files created through a + // preopen inherit the host adapter's normal creation permissions. + Ok(()) +} + +fn cleanup_refactor_sidecars(staged: &[StagedRefactorFile], retain: &HashSet) { + for entry in staged { + let _ = std::fs::remove_file(&entry.new_path); + if !retain.contains(&entry.backup_path) { + let _ = std::fs::remove_file(&entry.backup_path); + } + } +} + +/// One trimmed hunk per changed unit: common prefix/suffix lines are +/// elided, the middle prints as `-`/`+` lines (1-based line numbers, +/// unified-style header). Both refactor ops touch one contiguous region per +/// unit, so a single hunk is exact. +fn write_unit_diff(out: &mut dyn Write, unit: &str, old: &str, new: &str) -> io::Result<()> { + let o: Vec<&str> = old.split_inclusive('\n').collect(); + let n: Vec<&str> = new.split_inclusive('\n').collect(); + let mut p = 0; + while p < o.len() && p < n.len() && o[p] == n[p] { + p += 1; + } + let mut s = 0; + while s < o.len() - p && s < n.len() - p && o[o.len() - 1 - s] == n[n.len() - 1 - s] { + s += 1; + } + writeln!(out, "--- {unit}")?; + writeln!( + out, + "@@ -{},{} +{},{} @@", + p + 1, + o.len() - p - s, + p + 1, + n.len() - p - s + )?; + for l in &o[p..o.len() - s] { + write!(out, "-{l}")?; + if !l.ends_with('\n') { + writeln!(out)?; + } + } + for l in &n[p..n.len() - s] { + write!(out, "+{l}")?; + if !l.ends_with('\n') { + writeln!(out)?; + } + } + Ok(()) +} + +/// Help echoes the active ambient context: with +/// SYSMLV2_MODEL_DIR set, the top level and every verb that honors +/// ambient inputs get a trailing `model context:` line appended to +/// their help footer, so `--help` confirms what a bare invocation +/// would run on. Without the variable, help is untouched. +fn ambient_help(mut cmd: clap::Command) -> clap::Command { + let Some(dir) = std::env::var_os(MODEL_DIR_VAR).filter(|v| !v.is_empty()) else { + return cmd; + }; + let dir = PathBuf::from(dir); + let count = match discover_model_files(&dir) { + Ok(files) => match files.len() { + 0 => "no model files".to_string(), + 1 => "1 model file".to_string(), + n => format!("{n} model files"), + }, + Err(e) => format!("unreadable: {e}"), + }; + let note = format!( + "model context: {} ({MODEL_DIR_VAR} — {count}); file inputs may be omitted", + dir.display() + ); + fn append(cmd: clap::Command, note: &str) -> clap::Command { + let text = match cmd.get_after_help() { + Some(existing) => format!("{existing}\n\n{note}"), + None => note.to_string(), + }; + cmd.after_help(text) + } + // Feature gates decide which verbs exist, so collect the present + // ones rather than naming a fixed list into mut_subcommand (which + // panics on absent names). + let verbs: Vec = cmd + .get_subcommands() + .map(|s| s.get_name().to_string()) + .filter(|n| { + matches!( + n.as_str(), + "convert" + | "fmt" + | "check" + | "verify" + | "eval" + | "query" + | "describe" + | "members" + | "parse" + | "viz" + | "refactor" + ) + }) + .collect(); + cmd = append(cmd, ¬e); + for name in verbs { + let note = if name == "fmt" { + format!("{note} (--check only)") + } else if name == "refactor" { + format!("{note} (--dry-run only)") + } else { + note.clone() + }; + cmd = cmd.mut_subcommand(name, |sub| append(sub, ¬e)); + } + cmd +} + +/// The tallying bucket a constraint's verdict falls in. +#[cfg(feature = "solve")] +enum VerdictCat { + Sat, + Vio, + Und, +} + +/// Render one constraint's combined verdict (evaluation, then propagation, +/// then Z3) into a display string and its tally bucket. Mirrors the +/// precedence in [`sysmlv2_solve::verify_constraints`]: a definitive +/// propagation conclusion pre-empts the solver, which only reports what +/// propagation left open. +#[cfg(feature = "solve")] +fn verdict_line( + verdict: &sysmlv2_parser::check::ConstraintVerdict, + propagate: Option<&sysmlv2_solve::PropagateOutcome>, + solve: Option<&sysmlv2_solve::SolveOutcome>, +) -> (String, VerdictCat) { + use sysmlv2_parser::check::ConstraintVerdict; + use sysmlv2_solve::{PropagateOutcome, SolveOutcome}; + match verdict { + ConstraintVerdict::Satisfied => ("satisfied".to_string(), VerdictCat::Sat), + ConstraintVerdict::Violated => ("VIOLATED".to_string(), VerdictCat::Vio), + ConstraintVerdict::Undecided(why) => match propagate { + Some(PropagateOutcome::Satisfied) => ( + "satisfied (propagation: holds for all values in the narrowed ranges)".to_string(), + VerdictCat::Sat, + ), + Some(PropagateOutcome::Violated) => ( + "VIOLATED (propagation: false for all values in the narrowed ranges)".to_string(), + VerdictCat::Vio, + ), + Some(PropagateOutcome::Unsatisfiable) => ( + "VIOLATED (propagation: domains contract to empty — unsatisfiable)".to_string(), + VerdictCat::Vio, + ), + _ => match solve { + Some(SolveOutcome::Valid) => ( + "satisfied (z3: holds for all values of unbound features)".to_string(), + VerdictCat::Sat, + ), + Some(SolveOutcome::Unsatisfiable) => ( + "VIOLATED (z3: unsatisfiable — no assignment can make this hold)".to_string(), + VerdictCat::Vio, + ), + Some(SolveOutcome::Satisfiable(w)) => { + let vals: Vec = w.iter().map(|(n, v)| format!("{n} = {v}")).collect(); + ( + format!( + "undecided ({why}) — z3: satisfiable, e.g. {}", + vals.join(", ") + ), + VerdictCat::Und, + ) + } + Some(SolveOutcome::Unknown(m)) => { + (format!("undecided ({why}; z3: {m})"), VerdictCat::Und) + } + None => match propagate { + Some(PropagateOutcome::Unsupported(m)) => ( + format!("undecided ({why}; propagation: {m})"), + VerdictCat::Und, + ), + _ => (format!("undecided ({why})"), VerdictCat::Und), + }, + // A conclusion this build does not recognize stays + // undecided. + Some(_) => (format!("undecided ({why})"), VerdictCat::Und), + }, + }, + } +} + +/// Append the evaluated feature values to a violated verdict line — +/// `VIOLATED (with reserveKg = 0.10)` — so the reader sees *why* +/// without re-deriving the bindings. Only bound references contribute; +/// non-violated lines pass through untouched. +#[cfg(feature = "solve")] +fn with_bindings( + line: String, + cat: &VerdictCat, + bindings: &[sysmlv2_parser::check::ConstraintBinding], +) -> String { + if !matches!(cat, VerdictCat::Vio) { + return line; + } + let vals: Vec = bindings + .iter() + .filter_map(|b| b.value.as_ref().map(|v| format!("{} = {v}", b.feature))) + .collect(); + if vals.is_empty() { + line + } else { + format!("{line} (with {})", vals.join(", ")) + } +} + +/// Run the requested verification stage over `model` and write per- +/// constraint verdicts (plus narrowed ranges under `--ranges`) to `out`. +/// `Ok` carries the verdict — `true` iff some constraint is violated; +/// `Err` is the status of a run that stopped early. +#[cfg(feature = "solve")] +fn verify_and_report( + out: &mut dyn Write, + model: &Model, + boundary: usize, + sources: &[(PathBuf, String)], + ranges: bool, + solve: bool, + z3: Option, +) -> Result { + use sysmlv2_solve::{PropagateConfig, SolverConfig}; + let indexes: Vec = sources.iter().map(|(_, src)| LineIndex::new(src)).collect(); + let (mut sat, mut vio, mut und) = (0usize, 0usize, 0usize); + + let mut print_one = |unit: usize, + start: u32, + name: &Option, + etype: &str, + context: Option<&str>, + line: String, + cat: VerdictCat| + -> Result<(), ExitCode> { + match cat { + VerdictCat::Sat => sat += 1, + VerdictCat::Vio => vio += 1, + VerdictCat::Und => und += 1, + } + let (path, _) = &sources[unit - boundary]; + let pos = indexes[unit - boundary].line_col(start); + let ctx = context + .map(|c| format!(", satisfies {c}")) + .unwrap_or_default(); + stdout_result(writeln!( + out, + "{}:{}:{} {} ({}{}): {}", + path.display(), + pos.line, + pos.col, + name.as_deref().unwrap_or(""), + etype, + ctx, + line + )) + }; + + // Ranges to print once the verdicts are out (only under --ranges). + let mut narrowed: Vec = Vec::new(); + + if !ranges && !solve { + // Plain evaluation stage — no propagation, no solver. + for c in sysmlv2_parser::check::check_constraints(model) { + let (line, cat) = verdict_line(&c.verdict, None, None); + let line = with_bindings(line, &cat, &c.bindings); + print_one( + c.unit, + c.span.start, + &c.name, + c.element_type, + c.context.as_deref(), + line, + cat, + )?; + } + } else { + let cfg = SolverConfig { + z3_path: z3, + ..Default::default() + }; + let report = match sysmlv2_solve::verify_constraints( + model, + solve.then_some(&cfg), + &PropagateConfig::default(), + ) { + Ok(r) => r, + Err(e) => { + eprintln!("error: {e}"); + return Err(ExitCode::FAILURE); + } + }; + for c in &report.constraints { + let (line, cat) = verdict_line(&c.verdict, c.propagate.as_ref(), c.solve.as_ref()); + let line = with_bindings(line, &cat, &c.bindings); + print_one( + c.unit, + c.span.start, + &c.name, + c.element_type, + None, + line, + cat, + )?; + } + // Satisfaction claims expand to subject-bound verdicts at the + // evaluation tier (propagation/solving see the unbound + // originals above). + let mut rm = sysmlv2_parser::json::ResolvedModel::build(model); + for c in sysmlv2_parser::check::satisfaction_checks(model, &mut rm) { + let (line, cat) = verdict_line(&c.verdict, None, None); + print_one( + c.unit, + c.span.start, + &c.name, + c.element_type, + c.context.as_deref(), + line, + cat, + )?; + } + if ranges { + narrowed = report.ranges.into_iter().filter(|r| r.narrowed).collect(); + } + } + + stdout_result(writeln!( + out, + "{sat} satisfied, {vio} violated, {und} undecided" + ))?; + if !narrowed.is_empty() { + stdout_result(writeln!(out, "\nnarrowed ranges:"))?; + for r in &narrowed { + stdout_result(match &r.unit { + Some(u) => writeln!(out, " {} ∈ {} [{u}]", r.feature, r.range), + None => writeln!(out, " {} ∈ {}", r.feature, r.range), + })?; + } + } + Ok(vio > 0) +} + +/// What `convert` was asked for: the conversion this run performs, +/// and every flag that shapes it. +struct ConvertArgs { + inputs: Vec, + to: Target, + output: Option, + lib: Option, + flexo: bool, + min_qual: bool, + elide_ids: bool, + delta_base: Option, + delta_portable: bool, + indent: Indent, + library: bool, +} + +/// `convert`: move a model between the textual notation and the +/// interchange forms, in either direction. +fn run_convert(args: ConvertArgs, quiet: bool) -> ExitCode { + let ConvertArgs { + inputs, + to, + output, + lib, + flexo, + min_qual, + elide_ids, + delta_base, + delta_portable, + indent, + library, + } = args; + if library { + if !inputs.is_empty() { + eprintln!("error: --library takes no inputs (the --lib directory is the input)"); + return ExitCode::FAILURE; + } + if !matches!(to, Target::CompactJson | Target::CompactCbor) { + eprintln!("error: --library targets compact-json or compact-cbor"); + return ExitCode::FAILURE; + } + // Which flags --library composes with, and that it needs + // --lib, are declared on the arguments themselves. + let dir = lib.as_ref().expect("--library requires --lib"); + let mut model = Model::new(); + let lib_cache_path = match load_library(&mut model, dir) { + Ok(p) => p, + Err(e) => { + eprintln!("error: cannot load library {}: {e}", dir.display()); + return ExitCode::FAILURE; + } + }; + save_library_cache(&model, lib_cache_path); + let (json, units) = sysmlv2_parser::json::library_to_compact_json_with_units(&model); + if matches!(to, Target::CompactCbor) { + return match sysmlv2_cbor::to_compact_cbor_with_units(&json, &units) { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode CBOR: {e}"); + ExitCode::FAILURE + } + }; + } + return exit_status(write_json(output.as_deref(), &json)); + } + let inputs = match resolve_inputs(inputs, quiet) { + Ok(files) => files, + Err(code) => return code, + }; + if flexo && matches!(to, Target::CompactCbor | Target::FullCbor) { + eprintln!( + "error: --flexo wraps JSON change records; CBOR carries \ + the bare element array" + ); + return ExitCode::FAILURE; + } + if elide_ids && !matches!(to, Target::CompactCbor) { + eprintln!("error: --elide-ids applies to --to compact-cbor"); + return ExitCode::FAILURE; + } + // --delta-portable needing --delta-base is declared on the + // argument itself. + if elide_ids && delta_portable { + eprintln!( + "error: --elide-ids applies to strict deltas only \ + (portable identities are explicit ids by design)" + ); + return ExitCode::FAILURE; + } + // An .s2c input decodes to the compact element array up + // front and then flows through every JSON-input path as the + // document itself: re-serializing it so those paths could + // parse it back again held a second copy of the whole + // payload. Its text slot below stays empty — a binary input + // has no text, and nothing but the JSON paths (which take + // the decoded document) can be reached with one. + let mut decoded = None; + let is_s2c_path = |p: &PathBuf| p.extension().and_then(|e| e.to_str()) == Some("s2c"); + let sources: Vec<(PathBuf, String)> = if inputs.len() == 1 && is_s2c_path(&inputs[0]) { + let bytes = match std::fs::read(&inputs[0]) { + Ok(b) => b, + Err(e) => { + eprintln!("error: cannot read {}: {e}", inputs[0].display()); + return ExitCode::FAILURE; + } + }; + // Id-elided payloads recompute their ids; the library + // (when given) names the effective-name targets. Delta + // payloads apply to --delta-base first. + let payload = match sysmlv2_cbor::from_cbor(&bytes) { + Err(e) if e.to_string().contains("delta payload") => { + let Some(base_path) = &delta_base else { + eprintln!( + "error: input is a delta payload; pass \ + --delta-base to apply it" + ); + return ExitCode::FAILURE; + }; + let base = match load_base_value(base_path) { + Ok(v) => v, + Err(code) => return code, + }; + // Id-elided deltas re-derive their created ids + // through the library resolver (empty is fine + // for hermetic models; explicit-id deltas + // never consult it). + let names = match load_library_id_names(lib.as_deref()) { + Ok(n) => n, + Err(code) => return code, + }; + sysmlv2_cbor::apply_delta_cbor_with(&bytes, &base, &|s| names.get(s).cloned()) + } + Err(e) if e.to_string().contains("elided") => { + let names = match load_library_id_names(lib.as_deref()) { + Ok(n) => n, + Err(code) => return code, + }; + sysmlv2_cbor::from_cbor_with(&bytes, &|s| names.get(s).cloned()) + } + other => other, + }; + match payload { + Ok(v) => { + decoded = Some(v); + vec![(inputs[0].clone(), String::new())] + } + Err(e) => { + eprintln!("error: invalid CBOR payload: {e}"); + return ExitCode::FAILURE; + } + } + } else if inputs.iter().any(is_s2c_path) { + eprintln!("error: convert accepts one .s2c input on its own"); + return ExitCode::FAILURE; + } else { + match read_inputs(&inputs) { + Ok(s) => s, + Err(code) => return code, + } + }; + let looks_json = |p: &Path, s: &str| { + matches!(p.extension().and_then(|e| e.to_str()), Some("json" | "s2c")) + || s.trim_start().starts_with('[') + }; + let is_json_input = looks_json(&sources[0].0, &sources[0].1); + if sources.len() > 1 && sources.iter().any(|(p, s)| looks_json(p, s)) { + eprintln!("error: convert accepts several textual inputs or one JSON input"); + return ExitCode::FAILURE; + } + if min_qual && (!matches!(to, Target::Text) || !is_json_input) { + eprintln!("error: --min-qual applies to JSON \u{2192} text conversion"); + return ExitCode::FAILURE; + } + match to { + Target::Text => { + if !is_json_input { + eprintln!( + "error: the input is already textual notation; use \ + `sysmlv2 fmt` to reformat it" + ); + return ExitCode::FAILURE; + } + let mut value = match json_input(decoded, &sources[0].1) { + Ok(v) => v, + Err(code) => return code, + }; + if flexo { + value = flexo_unwrap(value); + } + // Minimal-qualification printing: lift through a + // transform session (same split/lift/naming path) and + // run the reparse-verified respelling pass over the + // whole document set, then write its units. + if min_qual { + let mut session = + match sysmlv2_transform::Session::from_interchange_json_with_library( + &value, + lib.as_deref(), + ) { + Ok(s) => s, + Err(e) => { + eprintln!("error: cannot lift JSON: {e}"); + return ExitCode::FAILURE; + } + }; + for w in session.warnings() { + eprintln!("warning: {w}"); + } + if let Err(e) = session.minimize_qualifications() { + eprintln!("error: minimal-qualification pass failed: {e}"); + return ExitCode::FAILURE; + } + let units: Vec<(String, String)> = session + .units() + .map(|(_, n, s)| (n.to_string(), s.to_string())) + .collect(); + if let Some(dir) = output.as_ref().filter(|o| o.is_dir()) { + let mut out = stdout_writer(); + for (name, text) in &units { + let file = dir.join(name); + if let Err(e) = std::fs::write(&file, text) { + eprintln!("error: cannot write {}: {e}", file.display()); + return ExitCode::FAILURE; + } + if let Err(code) = stdout_result(writeln!(out, "{}", file.display())) { + return code; + } + } + return exit_status(stdout_result(out.flush())); + } + let text: String = units.into_iter().map(|(_, t)| t).collect(); + return exit_status(write_bytes(output.as_deref(), text.as_bytes())); + } + let names = match lib { + Some(dir) => { + let mut model = Model::new(); + let lib_cache_path = match load_library(&mut model, &dir) { + Ok(p) => p, + Err(e) => { + eprintln!("error: cannot load library {}: {e}", dir.display()); + return ExitCode::FAILURE; + } + }; + let names = library_name_map(&model); + save_library_cache(&model, lib_cache_path); + names + } + None => Default::default(), + }; + // A multi-document element list splits into one text + // file per root namespace when the output is a + // directory (the Flexo retrieval flow). A directory + // always receives files — one per document, or a + // single document-1.sysml when no split applies. + let split = sysmlv2_parser::lift::split_documents(&value); + if let Some(dir) = output.as_ref().filter(|o| o.is_dir()) { + let docs = split.unwrap_or_else(|| vec![(None, value.clone())]); + // Cross-document references print as $::-rooted + // qualified names via a whole-list name map. + let mut names = names; + names.extend(sysmlv2_parser::lift::document_reference_name_map(&value)); + let mut out = stdout_writer(); + for (i, (name, doc)) in docs.iter().enumerate() { + let lifted = match from_compact_json_with_names(doc, &names) { + Ok(l) => l, + Err(e) => { + eprintln!("error: cannot lift document {i}: {e}"); + return ExitCode::FAILURE; + } + }; + for w in &lifted.errors { + eprintln!("warning: {w}"); + } + let file = dir.join(doc_file_name(name.as_deref(), i)); + if let Err(e) = std::fs::write( + &file, + print_source_opts( + &lifted.unit, + PrintOptions { + indent, + reflow_doc_bodies: true, + ..Default::default() + }, + ), + ) { + eprintln!("error: cannot write {}: {e}", file.display()); + return ExitCode::FAILURE; + } + if let Err(code) = stdout_result(writeln!(out, "{}", file.display())) { + return code; + } + } + return exit_status(stdout_result(out.flush())); + } + if split.is_some() { + eprintln!( + "note: input holds several documents — they are \ + concatenated; pass `-o ` to split \ + into one file per root namespace" + ); + } + let lifted = match from_compact_json_with_names(&value, &names) { + Ok(l) => l, + Err(e) => { + eprintln!("error: cannot lift JSON: {e}"); + return ExitCode::FAILURE; + } + }; + for w in &lifted.errors { + eprintln!("warning: {w}"); + } + let text = print_source_opts( + &lifted.unit, + PrintOptions { + indent, + reflow_doc_bodies: true, + ..Default::default() + }, + ); + exit_status(write_bytes(output.as_deref(), text.as_bytes())) + } + Target::FullJson | Target::FullCbor | Target::CompactJson | Target::CompactCbor + if !is_json_input => + { + let full = matches!(to, Target::FullJson | Target::FullCbor); + // --elide-ids: library element names for the + // effective-name chains (roots-only exception maps); + // filled when a library is loaded below. + let mut elide_names: std::collections::HashMap = Default::default(); + // One no-lib file keeps the single-unit fast path; + // anything else builds a model (one root namespace per + // file, cross-file references resolved). Binary targets + // also carry the unit structure: each unit root's + // element index paired with its source path. + let (json, unit_paths) = if lib.is_some() || sources.len() > 1 { + let mut model = Model::new(); + let lib_cache_path = if let Some(lib) = &lib { + match load_library(&mut model, lib) { + Ok(p) => p, + Err(e) => { + eprintln!("error: cannot load library {}: {e}", lib.display()); + return ExitCode::FAILURE; + } + } + } else { + None + }; + for (path, src) in &sources { + let name = path.to_string_lossy().into_owned(); + let unit = model.add_source(name, src); + if !unit.diagnostics.is_empty() { + let diags = unit.diagnostics.clone(); + report(path, src, &diags); + return ExitCode::FAILURE; + } + } + if full && lib.is_none() { + eprintln!( + "note: no --lib given — implied relationships are omitted \ + (isImpliedIncluded: false); derived properties are included" + ); + } + let (compact, units) = model_to_compact_json_with_units(&model); + let json = if full { + // --flexo commits must survive read-back even + // with unresolved references: emit recovery + // annotations alongside the dangling ids. + // Full interchange is lossless by default: + // unresolved textual references need recovery + // carriers independently of the Flexo envelope. + model_to_full_json_with(&model, true) + } else { + compact.clone() + }; + let unit_paths = remap_units(&compact, &units, &json); + if elide_ids && lib.is_some() { + elide_names = library_name_map(&model) + .into_iter() + .filter_map(|(id, segs)| segs.last().cloned().map(|n| (id.to_string(), n))) + .collect(); + } + save_library_cache(&model, lib_cache_path); + (json, unit_paths) + } else { + let (input, src) = &sources[0]; + let parse = parse_file(input, src); + if !parse.diagnostics.is_empty() { + report(input, src, &parse.diagnostics); + return ExitCode::FAILURE; + } + // The builder emits each unit's root namespace + // first: the single unit's root is element 0 of + // the compact array. + let compact = to_compact_json(&parse.unit); + let units = vec![(0usize, input.to_string_lossy().into_owned())]; + if full { + eprintln!( + "note: no --lib given — implied relationships are omitted \ + (isImpliedIncluded: false); derived properties are included" + ); + let json = to_full_json_with(&parse.unit, true); + let unit_paths = remap_units(&compact, &units, &json); + (json, unit_paths) + } else { + (compact, units) + } + }; + let json = if flexo { + let names: Vec = sources + .iter() + .map(|(p, _)| { + p.file_name() + .map(|n| n.to_string_lossy().into_owned()) + .unwrap_or_else(|| "model.sysml".to_string()) + }) + .collect(); + flexo_payload(json, &names) + } else { + json + }; + if matches!(to, Target::CompactCbor | Target::FullCbor) { + let encoded = if matches!(to, Target::FullCbor) { + sysmlv2_cbor::to_full_cbor_with_units(&json, &unit_paths) + } else if let Some(base_path) = delta_base + .as_ref() + .filter(|_| matches!(to, Target::CompactCbor)) + { + let base = match load_base_value(base_path) { + Ok(v) => v, + Err(code) => return code, + }; + // This parse derived ids afresh; the base carries + // whatever its producer assigned. Rebase so + // unchanged elements coincide by identity. + let json = match sysmlv2_cbor::rebase_ids(&base, &json) { + Ok(v) => v, + Err(e) => { + eprintln!("error: cannot rebase onto the delta base: {e}"); + return ExitCode::FAILURE; + } + }; + // Unit paths ride strict deltas; + // rebase preserves element order, so the + // snapshot-side indices stay valid. + let units = if delta_portable { + Vec::new() + } else { + unit_paths + }; + if elide_ids { + sysmlv2_cbor::delta_compact_cbor_elided( + &base, + &json, + &sysmlv2_cbor::DeltaOptions::new().with_units(units), + &|s| elide_names.get(s).cloned(), + ) + } else { + sysmlv2_cbor::delta_compact_cbor( + &base, + &json, + &sysmlv2_cbor::DeltaOptions::new() + .with_portable(delta_portable) + .with_units(units), + ) + } + } else if elide_ids { + sysmlv2_cbor::to_compact_cbor_elided_with_units( + &json, + &|s| elide_names.get(s).cloned(), + &unit_paths, + ) + } else { + sysmlv2_cbor::to_compact_cbor_with_units(&json, &unit_paths) + }; + return match encoded { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode CBOR: {e}"); + ExitCode::FAILURE + } + }; + } + exit_status(write_json(output.as_deref(), &json)) + } + Target::Kpar => { + if is_json_input { + eprintln!( + "error: a .kpar packs textual units; convert the JSON \ + to text first" + ); + return ExitCode::FAILURE; + } + let Some(out) = output else { + eprintln!("error: --to kpar needs -o "); + return ExitCode::FAILURE; + }; + let mut units: Vec<(String, String, String)> = Vec::new(); + for (path, src) in &sources { + let parse = parse_file(path, src); + if !parse.diagnostics.is_empty() { + report(path, src, &parse.diagnostics); + return ExitCode::FAILURE; + } + // The .meta.json index maps the unit's root + // namespace name to its file; an anonymous root + // falls back to the file stem. + let root = parse + .unit + .members + .iter() + .find_map(|m| match &m.kind { + sysmlv2_parser::ast::MemberKind::Package(pkg) => { + pkg.id.name.as_ref().map(|n| n.value.clone()) + } + _ => None, + }) + .unwrap_or_else(|| { + path.file_stem().map_or_else( + || "model".to_string(), + |st| st.to_string_lossy().into_owned(), + ) + }); + let file_name = path.file_name().map_or_else( + || "model.sysml".to_string(), + |f| f.to_string_lossy().into_owned(), + ); + units.push((file_name, src.clone(), root)); + } + let name = out.file_stem().map_or_else( + || "project".to_string(), + |st| st.to_string_lossy().into_owned(), + ); + let bytes = match kpar::write(&name, "1.0.0", &units) { + Ok(bytes) => bytes, + Err(e) => { + eprintln!("error: cannot build {}: {e}", out.display()); + return ExitCode::FAILURE; + } + }; + if let Err(e) = std::fs::write(&out, bytes) { + eprintln!("error: cannot write {}: {e}", out.display()); + return ExitCode::FAILURE; + } + ExitCode::SUCCESS + } + Target::FullJson | Target::FullCbor => { + // Compact JSON → full JSON re-derivation, **in place**: + // every element keeps its @id (derived properties and + // implied relationships are functions of the compact + // structure), so a stored payload upgrades without + // breaking external references to its elements. + let mut value = match json_input(decoded, &sources[0].1) { + Ok(v) => v, + Err(code) => return code, + }; + if flexo { + value = flexo_unwrap(value); + } + if lib.is_none() { + eprintln!( + "note: no --lib given — implied relationships are omitted \ + (isImpliedIncluded: false); derived properties are included" + ); + } + // Route through the model: the payload is loaded into a + // session (ids preserved, foreign ones included) and the + // full form emitted from it, so this verb and the + // session API cannot disagree. + let library = lib + .as_ref() + .map(|dir| sysmlv2_transform::Library::dir(dir.clone())); + let session = match sysmlv2_transform::Session::from_interchange_json_with( + &value, + library.as_ref(), + ) { + Ok(s) => s, + Err(e) => { + eprintln!("error: cannot load the payload: {e}"); + return ExitCode::FAILURE; + } + }; + for w in session.warnings() { + eprintln!("warning: {w}"); + } + let json = session.to_full_json_with(true); + if matches!(to, Target::FullCbor) { + return match sysmlv2_cbor::to_full_cbor(&json) { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode CBOR: {e}"); + ExitCode::FAILURE + } + }; + } + let json = if flexo { + flexo_payload(json, &[]) + } else { + json + }; + exit_status(write_json(output.as_deref(), &json)) + } + Target::CompactJson | Target::CompactCbor => { + // JSON → compact JSON/CBOR: normalize (drop implied + // relationships / derived properties) by lifting and + // re-emitting. + let value = match json_input(decoded, &sources[0].1) { + Ok(v) => v, + Err(code) => return code, + }; + let lifted = match from_compact_json_with_names(&value, &Default::default()) { + Ok(l) => l, + Err(e) => { + eprintln!("error: cannot lift JSON: {e}"); + return ExitCode::FAILURE; + } + }; + for w in &lifted.errors { + eprintln!("warning: {w}"); + } + let json = to_compact_json(&lifted.unit); + if matches!(to, Target::CompactCbor) { + // Hermetic normalize path: elision without a + // resolver is always safe — library-effective + // names simply ride the exception map. + let encoded = if let Some(base_path) = &delta_base { + let base = match load_base_value(base_path) { + Ok(v) => v, + Err(code) => return code, + }; + // The lift + re-emit derived ids afresh; rebase + // so unchanged elements coincide by identity. + let json = match sysmlv2_cbor::rebase_ids(&base, &json) { + Ok(v) => v, + Err(e) => { + eprintln!("error: cannot rebase onto the delta base: {e}"); + return ExitCode::FAILURE; + } + }; + if elide_ids { + sysmlv2_cbor::delta_compact_cbor_elided( + &base, + &json, + &Default::default(), + &|_| None, + ) + } else { + sysmlv2_cbor::delta_compact_cbor( + &base, + &json, + &sysmlv2_cbor::DeltaOptions::new().with_portable(delta_portable), + ) + } + } else if elide_ids { + sysmlv2_cbor::to_compact_cbor_elided(&json, &|_| None) + } else { + sysmlv2_cbor::to_compact_cbor(&json) + }; + return match encoded { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode CBOR: {e}"); + ExitCode::FAILURE + } + }; + } + let json = if flexo { + flexo_payload(json, &[]) + } else { + json + }; + exit_status(write_json(output.as_deref(), &json)) + } + } +} + +/// What `payload` was asked for: which mode of the verb runs, and the +/// metadata a produced delta carries. +struct PayloadArgs { + inputs: Vec, + find_base: Option, + lib: Option, + delta_from: Option, + portable: bool, + claim_project: Option, + claim_commit: Option, + claim_service: Option, + apply_to: Option, + lenient: bool, + ids: bool, + tables: bool, + encode: bool, + output: Option, +} + +/// `payload`: inspect interchange payload files, or diff and apply them +/// at payload identity. +fn run_payload(args: PayloadArgs) -> ExitCode { + let PayloadArgs { + inputs, + find_base, + lib, + delta_from, + portable, + claim_project, + claim_commit, + claim_service, + apply_to, + lenient, + ids, + tables, + encode, + output, + } = args; + if tables { + if !inputs.is_empty() { + eprintln!("error: --tables takes no payload inputs"); + return ExitCode::FAILURE; + } + return exit_status(write_json(output.as_deref(), &codec_tables_doc())); + } + if inputs.is_empty() { + eprintln!("error: no input payloads"); + return ExitCode::FAILURE; + } + let names = match load_library_id_names(lib.as_deref()) { + Ok(n) => n, + Err(code) => return code, + }; + if let Some(base_path) = &delta_from { + let [target_path] = inputs.as_slice() else { + eprintln!("error: --delta-from takes exactly one target snapshot"); + return ExitCode::FAILURE; + }; + let base = match load_snapshot_value(base_path, &names) { + Ok(v) => v, + Err(code) => return code, + }; + let target = match load_snapshot_value(target_path, &names) { + Ok(v) => v, + Err(code) => return code, + }; + let mut claims: Vec<(u64, sysmlv2_cbor::Claim)> = Vec::new(); + for (key, id) in [(0, &claim_project), (1, &claim_commit)] { + if let Some(s) = id { + match uuid::Uuid::try_parse(s) { + Ok(u) => claims.push((key, sysmlv2_cbor::Claim::Id(u))), + Err(_) => { + eprintln!("error: claim `{s}` is not a UUID"); + return ExitCode::FAILURE; + } + } + } + } + if let Some(s) = &claim_service { + claims.push((2, sysmlv2_cbor::Claim::Text(s.clone()))); + } + let opts = sysmlv2_cbor::DeltaOptions::new() + .with_portable(portable) + .with_claims(claims); + return match sysmlv2_cbor::delta_compact_cbor(&base, &target, &opts) { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode the delta: {e}"); + ExitCode::FAILURE + } + }; + } + if let Some(base_path) = &apply_to { + let [delta_path] = inputs.as_slice() else { + eprintln!("error: --apply-to takes exactly one delta payload"); + return ExitCode::FAILURE; + }; + let Some(out_path) = &output else { + eprintln!("error: --apply-to writes the applied snapshot to --output"); + return ExitCode::FAILURE; + }; + let bytes = match std::fs::read(delta_path) { + Ok(b) => b, + Err(e) => { + eprintln!("error: cannot read {}: {e}", delta_path.display()); + return ExitCode::FAILURE; + } + }; + let base = match load_snapshot_value(base_path, &names) { + Ok(v) => v, + Err(code) => return code, + }; + let applied = if lenient { + sysmlv2_cbor::apply_delta_cbor_lenient(&bytes, &base) + } else { + sysmlv2_cbor::apply_delta_cbor_report_with(&bytes, &base, &|s| names.get(s).cloned()) + }; + let (result, report) = match applied { + Ok(r) => r, + Err(e) => { + eprintln!("error: cannot apply {}: {e}", delta_path.display()); + return ExitCode::FAILURE; + } + }; + let result_digest = match sysmlv2_cbor::state_digest(&result) { + Ok(d) => d.to_string(), + Err(e) => { + eprintln!("error: cannot digest the applied result: {e}"); + return ExitCode::FAILURE; + } + }; + if let Err(code) = write_json(Some(out_path), &result) { + return code; + } + let doc = serde_json::json!({ + "file": delta_path.display().to_string(), + "baseMatched": report.base_matched, + "noopDeletes": report.noop_deletes, + "upsertedUpdates": report.upserted_updates, + "replacedCreates": report.replaced_creates, + "units": report + .units + .iter() + .map(|(index, path)| serde_json::json!({ "index": index, "path": path })) + .collect::>(), + "resultElements": result.as_array().map(Vec::len), + "resultDigest": result_digest, + "output": out_path.display().to_string(), + }); + return exit_status(write_json(None, &doc)); + } + if encode { + let [input] = inputs.as_slice() else { + eprintln!("error: --encode takes exactly one compact-JSON snapshot"); + return ExitCode::FAILURE; + }; + let value = match load_snapshot_value(input, &names) { + Ok(v) => v, + Err(code) => return code, + }; + return match sysmlv2_cbor::to_compact_cbor(&value) { + Ok(bytes) => exit_status(write_bytes(output.as_deref(), &bytes)), + Err(e) => { + eprintln!("error: cannot encode {}: {e}", input.display()); + ExitCode::FAILURE + } + }; + } + if ids { + let mut summaries = Vec::new(); + for path in &inputs { + let value = match load_snapshot_value(path, &names) { + Ok(v) => v, + Err(code) => return code, + }; + let canon = match sysmlv2_cbor::delta_canonical(&value) { + Ok(c) => c, + Err(e) => { + eprintln!("error: {}: cannot canonicalize: {e}", path.display()); + return ExitCode::FAILURE; + } + }; + let digest = match sysmlv2_cbor::state_digest(&value) { + Ok(d) => d.to_string(), + Err(e) => { + eprintln!("error: {}: cannot digest: {e}", path.display()); + return ExitCode::FAILURE; + } + }; + let id_seq: Vec<&str> = canon + .as_array() + .unwrap() + .iter() + .filter_map(|e| e.get("@id").and_then(serde_json::Value::as_str)) + .collect(); + summaries.push(serde_json::json!({ + "file": path.display().to_string(), + "elements": id_seq.len(), + "stateDigest": digest, + "ids": id_seq, + })); + } + let doc = if summaries.len() == 1 { + summaries.pop().unwrap() + } else { + serde_json::Value::Array(summaries) + }; + return exit_status(write_json(None, &doc)); + } + // One scan shared by every delta input: digest each + // snapshot-looking file under the directory once. + let candidates: Option> = find_base.as_ref().map(|dir| { + payload_files_under(dir) + .into_iter() + .filter_map(|p| snapshot_file_digest(&p, &names).map(|d| (p, d))) + .collect() + }); + let mut summaries = Vec::new(); + let mut saw_delta = false; + let mut unmatched = false; + for path in &inputs { + let bytes = match std::fs::read(path) { + Ok(b) => b, + Err(e) => { + eprintln!("error: cannot read {}: {e}", path.display()); + return ExitCode::FAILURE; + } + }; + let mut summary = match sysmlv2_cbor::describe(&bytes) { + Ok(s) => { + let described = s.as_object().unwrap().clone(); + let mut o = serde_json::Map::new(); + o.insert("file".into(), serde_json::json!(path.display().to_string())); + o.insert("encoding".into(), serde_json::json!("cbor")); + o.extend(described); + serde_json::Value::Object(o) + } + // Not s2c — a compact interchange JSON snapshot + // still has a state digest worth printing. + Err(cbor_err) => match serde_json::from_slice::(&bytes) { + Ok(v) if v.is_array() => { + let digest = match sysmlv2_cbor::state_digest(&v) { + Ok(d) => d.to_string(), + Err(e) => { + eprintln!("error: {}: cannot digest: {e}", path.display()); + return ExitCode::FAILURE; + } + }; + serde_json::json!({ + "file": path.display().to_string(), + "encoding": "json", + "form": "compact", + "bytes": bytes.len(), + "elements": v.as_array().unwrap().len(), + "stateDigest": digest, + }) + } + _ => { + eprintln!( + "error: {}: not an interchange payload (s2c or \ + compact JSON element array): {cbor_err}", + path.display() + ); + return ExitCode::FAILURE; + } + }, + }; + if summary["form"] == "delta" { + saw_delta = true; + if let Some(cands) = &candidates { + let matches = |key: &str| -> Vec { + cands + .iter() + .filter(|(_, d)| Some(d.as_str()) == summary["delta"][key].as_str()) + .map(|(p, _)| serde_json::json!(p.display().to_string())) + .collect() + }; + let base_matches = matches("baseDigest"); + let result_matches = matches("resultDigest"); + if base_matches.is_empty() { + eprintln!( + "note: {}: no snapshot under {} matches the delta's \ + base digest", + path.display(), + find_base.as_ref().unwrap().display() + ); + unmatched = true; + } + let d = summary["delta"].as_object_mut().unwrap(); + d.insert("baseMatches".into(), serde_json::json!(base_matches)); + d.insert("resultMatches".into(), serde_json::json!(result_matches)); + } + } else if summary["encoding"] == "cbor" + && summary["form"] == "compact" + && summary["versions"]["supported"] == true + { + // Compact snapshot s2c: the state digest requires a + // decode (elided payloads re-derive their ids + // first). Full-form payloads have no state digest — + // the digest space is compact-form canonical. + match decode_snapshot(&bytes, &names) { + Ok(v) => match sysmlv2_cbor::state_digest(&v) { + Ok(d) => { + summary + .as_object_mut() + .unwrap() + .insert("stateDigest".into(), serde_json::json!(d.to_string())); + } + Err(e) => { + eprintln!("error: {}: cannot digest: {e}", path.display()); + return ExitCode::FAILURE; + } + }, + Err(e) => { + summary + .as_object_mut() + .unwrap() + .insert("stateDigestError".into(), serde_json::json!(e.to_string())); + } + } + } + summaries.push(summary); + } + if candidates.is_some() && !saw_delta { + eprintln!("error: --find-base needs a delta payload input"); + return ExitCode::FAILURE; + } + let doc = if summaries.len() == 1 { + summaries.pop().unwrap() + } else { + serde_json::Value::Array(summaries) + }; + if let Err(code) = write_json(None, &doc) { + return code; + } + if unmatched { + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } +} + +/// `fmt`: rewrite each file in canonical form, or report which files +/// are not in it. +fn run_fmt( + files: Vec, + check: bool, + stdout: bool, + indent: Indent, + quiet: bool, +) -> ExitCode { + // Ambient inputs never drive an in-place rewrite: a whole + // workspace reformatted because an env var happened to be + // set is a footgun. --check is the read-only mode. + let files = if files.is_empty() && !check { + eprintln!( + "error: no input files — fmt rewrites in place, so ambient \ + {MODEL_DIR_VAR} inputs apply to --check only; pass explicit paths" + ); + return ExitCode::FAILURE; + } else { + match resolve_inputs(files, quiet) { + Ok(files) => files, + Err(code) => return code, + } + }; + let mut failed = false; + for path in &files { + if path == Path::new("-") && !stdout && !check { + eprintln!("error: cannot format stdin (`-`) in place; use --stdout or --check"); + failed = true; + continue; + } + let src = match read(path) { + Ok(s) => s, + Err(_) => { + failed = true; + continue; + } + }; + match format_source_with(&src, dialect_of(path), indent) { + Err(diags) => { + report(path, &src, &diags); + failed = true; + } + Ok(formatted) => { + if stdout { + if let Err(code) = write_bytes(None, formatted.as_bytes()) { + return code; + } + } else if check { + if formatted != src { + eprintln!("would reformat: {}", path.display()); + failed = true; + } + } else if formatted != src { + if let Err(e) = std::fs::write(path, &formatted) { + eprintln!("error: cannot write {}: {e}", path.display()); + failed = true; + } + } + } + } + } + if failed { + ExitCode::FAILURE + } else { + ExitCode::SUCCESS + } +} + +/// `check`: parse and validate every input, reporting the findings as +/// diagnostics or as one JSON document. +fn run_check( + files: Vec, + lib: Option<&Path>, + strict: bool, + format: ReportFormat, + quiet: bool, +) -> ExitCode { + let files = match resolve_inputs(files, quiet) { + Ok(files) => files, + Err(code) => return code, + }; + let mut errors = 0usize; + let mut warnings = 0usize; + // `.kpar` archives expand to their contained textual units. + let inputs = match read_inputs(&files) { + Ok(i) => i, + Err(code) => return code, + }; + let mut sink = Sink::new(format, &inputs); + // (input index, path, source) per cleanly-parsed file, for + // the model stage. + let mut sources: Vec<(usize, &PathBuf, &str)> = Vec::new(); + let mut parsed = Vec::new(); + for (i, (path, src)) in inputs.iter().enumerate() { + let parse = sysmlv2_parser::model::ParsedSource::new(path.display().to_string(), src); + if !parse.diagnostics().is_empty() { + for d in parse.diagnostics() { + sink.diagnostic("parse", i, d); + } + errors += parse.diagnostics().len(); + continue; // context checks on a broken parse would mislead + } + let context_diags = sysmlv2_parser::check::validate(parse.unit()); + for d in &context_diags { + sink.diagnostic("context", i, d); + } + errors += context_diags.len(); + sources.push((i, path, src)); + parsed.push(parse); + } + + // Referential and semantic checks always run over all cleanly + // parsed files as one model. A standard library enriches + // resolution, but basic local constraints must not disappear + // merely because `--lib` was omitted. + if !sources.is_empty() { + let mut model = Model::new(); + let lib_cache_path = if let Some(lib) = lib { + match load_library(&mut model, lib) { + Ok(p) => p, + Err(e) => { + eprintln!("error: cannot load library {}: {e}", lib.display()); + return ExitCode::FAILURE; + } + } + } else { + None + }; + // Unit indices: libraries first, then our files in order. + let boundary = model.unit_count(); + for source in parsed { + model.add_parsed_source(source); + } + let mut r = sysmlv2_parser::json::ResolvedModel::build(&model); + save_library_cache(&model, lib_cache_path); + // Checker diagnostics are located by input index here; + // the sink's engine aliases serve lint findings only. + let input_of = |unit: usize| sources[unit - boundary].0; + let mut tally = |d: &Diagnostic| match d.severity { + sysmlv2_parser::diag::Severity::Error => errors += 1, + sysmlv2_parser::diag::Severity::Warning => warnings += 1, + }; + for (unit, d) in sysmlv2_parser::check::validate_model_with(&mut r, &model) { + tally(&d); + sink.diagnostic("referential", input_of(unit), &d); + } + for (unit, d) in sysmlv2_parser::check::validate_semantics_with(&mut r, &model) { + tally(&d); + sink.diagnostic("semantic", input_of(unit), &d); + } + if lib.is_some() { + // Unused private imports: provenance + + // owner-chain + textual conditions, corpus-triaged. + let texts: Vec<(usize, String)> = sources + .iter() + .enumerate() + .map(|(k, (_, _, src))| (boundary + k, src.to_string())) + .collect(); + for (unit, span) in sysmlv2_transform::unused_private_imports_with(&mut r, &texts) { + warnings += 1; + sink.diagnostic( + "referential", + input_of(unit), + &sysmlv2_parser::Diagnostic::warning(span, "unused private import"), + ); + } + } + } + + if let Err(code) = sink.finish() { + return code; + } + verdict(errors, warnings, strict, format) +} + +/// What `lint` was asked for: which rules run, and whether their fixes +/// are applied. +struct LintArgs { + files: Vec, + lib: Option, + config: Option, + rule: Vec, + fix: bool, + fix_deletes: bool, + fix_semantic: bool, + strict: bool, + format: ReportFormat, +} + +/// `lint`: run the rule set over every input and report its findings, +/// applying their fixes under `--fix`. +fn run_lint(args: LintArgs, quiet: bool) -> ExitCode { + let LintArgs { + files, + lib, + config, + rule, + fix, + fix_deletes, + fix_semantic, + strict, + format, + } = args; + let files = match resolve_inputs(files, quiet) { + Ok(files) => files, + Err(code) => return code, + }; + let inputs = match read_inputs(&files) { + Ok(i) => i, + Err(code) => return code, + }; + // Config: --config, else sysmlint.json beside the first input. + let config_path = config.or_else(|| { + let candidate = files + .first() + .and_then(|f| f.parent()) + .map(|d| d.join("sysmlint.json"))?; + candidate.exists().then_some(candidate) + }); + let mut cfg = match &config_path { + Some(p) => match std::fs::read_to_string(p) + .map_err(|e| e.to_string()) + .and_then(|t| sysmlv2_lint::Config::from_json(&t).map_err(|e| e.to_string())) + { + Ok(c) => c, + Err(e) => { + eprintln!("error: cannot read lint config {}: {e}", p.display()); + return ExitCode::FAILURE; + } + }, + None => sysmlv2_lint::Config::default(), + }; + for r in &rule { + let Some((id, level)) = r.split_once('=') else { + eprintln!("error: --rule wants ID=LEVEL, got `{r}`"); + return ExitCode::FAILURE; + }; + let level = match level { + "off" => sysmlv2_lint::Severity::Off, + "hint" => sysmlv2_lint::Severity::Hint, + "info" => sysmlv2_lint::Severity::Info, + "warn" => sysmlv2_lint::Severity::Warn, + "error" => sysmlv2_lint::Severity::Error, + other => { + eprintln!("error: --rule level must be off|hint|info|warn|error, got `{other}`"); + return ExitCode::FAILURE; + } + }; + cfg.set(id, level); + } + + // The model stage wants cleanly-parsed sources only. + let mut errors = 0usize; + let mut warnings = 0usize; + let mut sink = Sink::new(format, &inputs); + // (input index, path, source) per cleanly-parsed file. + let mut sources: Vec<(usize, &PathBuf, &str)> = Vec::new(); + let mut parsed = Vec::new(); + for (i, (path, src)) in inputs.iter().enumerate() { + let parse = sysmlv2_parser::model::ParsedSource::new(path.display().to_string(), src); + if !parse.diagnostics().is_empty() { + for d in parse.diagnostics() { + sink.diagnostic("parse", i, d); + } + errors += parse.diagnostics().len(); + continue; + } + sources.push((i, path, src)); + parsed.push(parse); + } + let mut model = Model::new(); + let mut lib_cache_path = None; + if let Some(lib) = &lib { + lib_cache_path = match load_library(&mut model, lib) { + Ok(p) => Some(p), + Err(e) => { + eprintln!("error: cannot load library {}: {e}", lib.display()); + return ExitCode::FAILURE; + } + }; + } + // Without `--lib`, the ambient libraries still load so + // ordinary content + sidecar invocations resolve their + // provenance record types (with `--lib` they came along). + if lib.is_none() { + sysmlv2_parser::ambient::add_to(&mut model); + } + let boundary = model.unit_count(); + for (k, (source, (i, _, _))) in parsed.into_iter().zip(&sources).enumerate() { + model.add_parsed_source(source); + sink.alias(boundary + k, *i); + } + let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); + if let Some(p) = lib_cache_path { + save_library_cache(&model, p); + } + // The textual tier (`indentation`) reads the units' source + // text; unit indexes start past the library units. Names + // ride along (AA7g): the generated-provenance rules audit + // the sidecar placement contract, which is spelled in unit + // names — with lint_with_sources they were silent in CI. + let names: Vec = sources + .iter() + .map(|(_, path, _)| path.display().to_string()) + .collect(); + let texts: Vec<(usize, &str, &str)> = sources + .iter() + .enumerate() + .map(|(k, (_, _, src))| (boundary + k, names[k].as_str(), *src)) + .collect(); + let findings = sysmlv2_lint::lint_units(&mut resolved, &cfg, &texts); + + for f in &findings { + match f.severity { + sysmlv2_lint::Severity::Error => errors += 1, + _ => warnings += 1, + } + // Lint is closed-world: findings sit in user units, which + // start past the library boundary. + let input = f + .unit + .and_then(|u| u.checked_sub(boundary)) + .and_then(|k| sources.get(k)) + .map(|(i, _, _)| *i); + sink.finding(f, input); + } + + // Fix application: safe fixes under --fix; fixes that delete + // model text additionally need --fix-deletes. Whole-line + // deletions swallow their now-blank line; every rewritten + // source must reparse cleanly before it is written back. + if fix { + let mut skipped_deletes = 0usize; + let mut skipped_semantic = 0usize; + let mut edits_by_unit: HashMap> = HashMap::new(); + for f in &findings { + let Some(fx) = &f.fix else { continue }; + if fx.deletes && !fix_deletes { + skipped_deletes += 1; + continue; + } + if fx.semantic && !fix_semantic { + skipped_semantic += 1; + continue; + } + for e in &fx.edits { + edits_by_unit + .entry(e.unit) + .or_default() + .push((Span::new(e.span.start, e.span.end), e.replacement.clone())); + } + } + let mut units: Vec<_> = edits_by_unit.into_iter().collect(); + units.sort_by_key(|(u, _)| *u); + for (unit, mut edits) in units { + let (_, path, src) = &sources[unit - boundary]; + // Two findings can carry the same edit (each + // import-adding fix restates the insert so it works + // standalone) or overlapping ones (two rules + // rewriting one span) — identical edits collapse, + // and of an overlapping pair only the first + // survives. + edits.sort_by(|a, b| (a.0.start, a.0.end, &a.1).cmp(&(b.0.start, b.0.end, &b.1))); + edits.dedup(); + let mut kept: Vec<(Span, String)> = Vec::new(); + for e in edits { + let overlaps = kept.last().is_some_and(|(prev, _)| e.0.start < prev.end); + if !overlaps { + kept.push(e); + } + } + let mut edits = kept; + edits.sort_by_key(|(s, _)| std::cmp::Reverse(s.start)); + let mut text = src.to_string(); + for (span, replacement) in edits { + let (mut start, mut end) = (span.start as usize, span.end as usize); + if replacement.is_empty() { + // Swallow the whole line when deleting leaves + // it blank. + let line_start = text[..start].rfind('\n').map(|i| i + 1).unwrap_or(0); + let line_end = text[end..] + .find('\n') + .map(|i| end + i + 1) + .unwrap_or(text.len()); + let blank = |s: &str| s.chars().all(char::is_whitespace); + if blank(&text[line_start..start]) + && blank(text[end..line_end.min(text.len())].trim_end_matches('\n')) + { + start = line_start; + end = line_end; + } + } + text.replace_range(start..end, &replacement); + } + let reparse = parse_file(path, &text); + if !reparse.diagnostics.is_empty() { + eprintln!("error: fixes would break {} — not written", path.display()); + errors += 1; + continue; + } + if !path.exists() { + eprintln!( + "note: {} is not a plain file (stdin or archive) — fixed text \ + not written", + path.display() + ); + continue; + } + if let Err(e) = std::fs::write(path, &text) { + eprintln!("error: cannot write {}: {e}", path.display()); + errors += 1; + continue; + } + if !quiet { + eprintln!("fixed: {}", path.display()); + } + } + if skipped_deletes > 0 { + eprintln!( + "{skipped_deletes} deletion fix(es) available but not applied — \ + deleting model text needs --fix --fix-deletes" + ); + } + if skipped_semantic > 0 { + eprintln!( + "{skipped_semantic} rewrite fix(es) available but not applied — \ + changing what a declaration means needs --fix --fix-semantic" + ); + } + } + + if let Err(code) = sink.finish() { + return code; + } + verdict(errors, warnings, strict, format) +} + +/// `verify`: run the verification stage over the model and write one +/// verdict per constraint. A violated constraint fails the run. +#[cfg(feature = "solve")] +pub fn run_verify( + files: Vec, + lib: Option<&Path>, + ranges: bool, + solve: bool, + z3: Option, + quiet: bool, +) -> Result<(), CliError> { + let loaded = load_model(files, lib, quiet)?; + let mut out = stdout_writer(); + let verdict = verify_and_report( + out.as_mut(), + &loaded.model, + loaded.boundary, + &loaded.sources, + ranges, + solve, + z3, + ); + save_library_cache(&loaded.model, loaded.lib_cache); + let violated = verdict?; + stdout_result(out.flush())?; + if violated { + return Err(CliError::Reported(ExitCode::FAILURE)); + } + Ok(()) +} + +/// `eval`: compute the value of each named feature (and, under `--all`, +/// of every feature that has one). A name that will not resolve or will +/// not evaluate fails the run, after the rest have been reported. +pub fn run_eval( + input: Option, + names: Vec, + all: bool, + lib: Option<&Path>, + quiet: bool, +) -> Result<(), CliError> { + let (files, names) = split_files_and_names(input, names); + let mut resolved = load_model(files, lib, quiet)?.into_resolved(); + let mut failed = false; + let mut out = stdout_writer(); + let written = (|| -> io::Result<()> { + if all { + for e in resolved.features_with_values() { + let label = resolved + .element_effective_name(e) + .or_else(|| resolved.element_lookup_name(e)) + .unwrap_or_else(|| "".to_string()); + match resolved.evaluate(e) { + Ok(v) => writeln!(out, "{label} = {v}")?, + Err(err) => writeln!(out, "{label}: {err}")?, + } + } + } + for name in &names { + if resolved.resolve_qualified(name).is_none() { + eprintln!("error: cannot resolve `{name}`"); + failed = true; + continue; + } + // Chain-step semantics: the path prefix establishes the + // featuring context, so `Pkg::part::attr` computes the + // same value as `part.attr`. + match resolved.evaluate_qualified(name) { + Ok(v) => writeln!(out, "{name} = {v}")?, + Err(err) => { + eprintln!("error: {name}: {err}"); + failed = true; + } + } + } + out.flush() + })(); + stdout_result(written)?; + if failed { + return Err(CliError::Reported(ExitCode::FAILURE)); + } + Ok(()) +} + +/// `render`: evaluate one view usage and write the nodes it exposes, +/// as JSON or as an HTML fragment. +pub fn run_render( + args: Vec, + lib: Option<&Path>, + html: bool, + quiet: bool, +) -> Result<(), CliError> { + let (files, names): (Vec, Vec) = + args.into_iter().partition(|a| is_model_source(a)); + let [view_name] = names.as_slice() else { + return Err(fail(format!( + "expected exactly one view usage name, got {}", + names.len() + ))); + }; + let mut resolved = + load_model(files.into_iter().map(PathBuf::from).collect(), lib, quiet)?.into_resolved(); + let Some(view) = resolved.resolve_qualified(view_name) else { + return Err(fail(format!("element not found: {view_name}"))); + }; + let nodes = resolved.render_view(view).map_err(fail)?; + if html { + let html = sysmlv2_parser::render::to_html(&nodes) + "\n"; + write_bytes(None, html.as_bytes())?; + } else { + let json = serde_json::Value::Array(nodes.iter().map(|n| n.to_json()).collect()); + write_json(None, &json)?; + } + Ok(()) +} + +/// `query`: evaluate one expression against the model's root scope and +/// write its value, one line per item of a sequence. +pub fn run_query( + input: Option, + args: Vec, + lib: Option<&Path>, + quiet: bool, +) -> Result<(), CliError> { + let (files, exprs) = split_files_and_names(input, args); + let [expr_src] = exprs.as_slice() else { + return Err(fail(format!( + "expected exactly one query expression, got {}", + exprs.len() + ))); + }; + // The inputs settle before the expression is parsed, so a run with + // nothing to query says so first. + let files = resolve_inputs(files, quiet)?; + let parsed = sysmlv2_parser::parser::parse_expression(expr_src); + if !parsed.diagnostics.is_empty() { + report(Path::new(""), expr_src, &parsed.diagnostics); + return Err(CliError::Reported(ExitCode::FAILURE)); + } + let Some(expr) = parsed.expr else { + return Err(fail("the query is not an expression")); + }; + let mut resolved = load_model(files, lib, quiet)?.into_resolved(); + let root = resolved.root_scope(); + let mut out = stdout_writer(); + let written = match resolved.query(root, &expr) { + Ok(sysmlv2_parser::eval::Value::Sequence(items)) => items + .iter() + .try_for_each(|item| writeln!(out, "{}", render_query_value(&mut resolved, item))), + Ok(v) => writeln!(out, "{}", render_query_value(&mut resolved, &v)), + Err(e) => return Err(fail(e.to_string())), + }; + stdout_result(written.and_then(|()| out.flush()))?; + Ok(()) +} + +/// `describe`: one element's metaclass, owner, type, position among its +/// owner's members, and declaration site. +pub fn run_describe( + input: Option, + args: Vec, + lib: Option<&Path>, + quiet: bool, +) -> Result<(), CliError> { + let (mut resolved, qname) = resolve_model_and_name(input, args, lib, quiet)?; + let Some(e) = resolved.resolve_qualified(&qname) else { + return Err(fail(format!("cannot resolve `{qname}`"))); + }; + let mut out = stdout_writer(); + let written = (|| -> io::Result<()> { + writeln!(out, "{qname}")?; + writeln!(out, " metaclass {}", resolved.element_type(e))?; + let owner = resolved.owner(e); + if let Some(owner) = owner { + if let Some(oq) = resolved.element_qualified_name(owner) { + writeln!(out, " owner {oq}")?; + } + } + if let Some(t) = resolved.typings(e).first().copied() { + let label = resolved + .element_qualified_name(t) + .or_else(|| resolved.element_effective_name(t)) + .or_else(|| resolved.element_lookup_name(t)); + if let Some(label) = label { + writeln!(out, " type {label}")?; + } + } + if let Some(owner) = owner { + let members = resolved.owned_members(owner); + if let Some(idx) = members.iter().position(|m| *m == e) { + writeln!(out, " position {} of {}", idx + 1, members.len())?; + } + } + if let Some((file, line, col)) = resolved.declaration_position(e) { + writeln!(out, " location {file}:{line}:{col}")?; + } + out.flush() + })(); + stdout_result(written)?; + Ok(()) +} + +/// `members`: one element's owned members, name and metaclass per line. +pub fn run_members( + input: Option, + args: Vec, + lib: Option<&Path>, + quiet: bool, +) -> Result<(), CliError> { + let (mut resolved, qname) = resolve_model_and_name(input, args, lib, quiet)?; + let Some(e) = resolved.resolve_qualified(&qname) else { + return Err(fail(format!("cannot resolve `{qname}`"))); + }; + let mut out = stdout_writer(); + let written = (|| -> io::Result<()> { + for m in resolved.owned_members(e) { + // The specification's `name`, else the written one: an + // unnamed feature is listed by its naming feature (`result`, + // `source`, a redefined feature's name — as written when the + // redefinition did not resolve), not as anonymous. + let name = resolved + .element_effective_name(m) + .or_else(|| resolved.element_lookup_name(m)) + .unwrap_or_else(|| "(anonymous)".to_string()); + writeln!(out, "{name:<28} {}", resolved.element_type(m))?; + } + out.flush() + })(); + stdout_result(written)?; + Ok(()) +} + +/// `parse`: a per-file loop — each file parses (and reports) on its +/// own, and any diagnostic anywhere fails the run. +pub fn run_parse(input: Option, ast: bool, quiet: bool) -> Result<(), CliError> { + let files = resolve_inputs(input.into_iter().collect(), quiet)?; + let mut failed = false; + let mut out = stdout_writer(); + for input in &files { + let src = read(input)?; + let parse = parse_file(input, &src); + report(input, &src, &parse.diagnostics); + let written = if ast { + writeln!(out, "{:#?}", parse.unit) + } else { + writeln!( + out, + "{}: {} top-level member(s), {} diagnostic(s)", + input.display(), + parse.unit.members.len(), + parse.diagnostics.len() + ) + }; + stdout_result(written)?; + failed |= !parse.diagnostics.is_empty(); + } + stdout_result(out.flush())?; + if failed { + return Err(CliError::Reported(ExitCode::FAILURE)); + } + Ok(()) +} + +/// What `viz` was asked for. The diagram options outnumber what reads +/// well as a parameter list, and they travel together from the command +/// line to the emitter's own options. +#[cfg(feature = "viz")] +pub struct VizArgs { + pub files: Vec, + pub view: Option, + pub element: Option, + pub lib: Option, + pub horizontal: bool, + pub no_values: bool, + pub no_notes: bool, + pub hide_metadata: bool, + pub show_inherited: bool, + pub show_lib: bool, + pub show_imported: bool, + pub line_style: Option, + pub color: bool, + pub link_template: Option, + pub output: Option, +} + +/// `viz`: emit one view of the model as PlantUML text. +#[cfg(feature = "viz")] +pub fn run_viz(args: VizArgs, quiet: bool) -> Result<(), CliError> { + let view = args.view.map(sysmlv2_viz::View::from); + let line_style = args.line_style.map_or( + sysmlv2_viz::LineStyle::Default, + sysmlv2_viz::LineStyle::from, + ); + let mut resolved = load_model(args.files, args.lib.as_deref(), quiet)?.into_resolved(); + let root = match &args.element { + Some(name) => match resolved.resolve_qualified(name) { + Some(e) => Some(e), + None => return Err(fail(format!("element not found: {name}"))), + }, + None => None, + }; + // A view usage directs its own rendering: the diagram's + // elements are what the view exposes (filter conditions + // applied), and its `render` member picks the style unless + // --view was given explicitly. + let (root, view, roots) = match root { + Some(e) => match sysmlv2_viz::view_directed(&mut resolved, e) { + Some((style, exposed)) => (None, view.or(style), Some(exposed)), + None => (Some(e), view, None), + }, + None => (None, view, None), + }; + let opts = sysmlv2_viz::VizOptions::default() + .with_direction(if args.horizontal { + sysmlv2_viz::Direction::LeftToRight + } else { + sysmlv2_viz::Direction::TopToBottom + }) + .with_show_values(!args.no_values) + .with_view(view.unwrap_or(sysmlv2_viz::View::Tree)) + .with_show_notes(!args.no_notes) + .with_show_metadata(!args.hide_metadata) + .with_show_inherited(args.show_inherited) + .with_show_lib(args.show_lib) + .with_show_imported(args.show_imported) + .with_line_style(line_style) + .with_std_color(args.color) + .with_link_template(args.link_template) + .with_roots(roots); + let text = sysmlv2_viz::plantuml(&mut resolved, root, &opts); + write_bytes(args.output.as_deref(), text.as_bytes())?; + Ok(()) +} + +/// Run one command line to completion and answer with the status the +/// process should end with. An argument list the parser refuses — or +/// one that only asks for help — is answered the way the command line +/// always answers it: the text goes out and the status comes back. +/// +/// Nearly every verb parses, and the parser's nesting bound assumes a +/// stack sized for it, which a process's own thread is not: the work +/// runs on a thread that reserves one +/// ([`sysmlv2_parser::parser::on_parsing_stack`]). +pub fn run(args: I) -> ExitCode +where + I: IntoIterator, + T: Into + Clone, +{ + use clap::CommandFactory; + let cmd = ambient_help(Cli::command()); + let cli = match cmd + .try_get_matches_from(args) + .and_then(|m| ::from_arg_matches(&m)) + { + Ok(cli) => cli, + Err(e) => { + let _ = e.print(); + return ExitCode::from(u8::try_from(e.exit_code()).unwrap_or(2)); + } + }; + let quiet = cli.quiet; + // Spelled power-product unit expansion is on by default; the flag or + // `SYSMLV2_UNIT_SPELLINGS=off` opts out. The switch is process-wide + // and this function is a library entry point, so every run sets it + // from its own arguments rather than only ever turning it off — one + // opted-out run must not decide the setting for the next. + let expand_unit_spellings = !(cli.no_unit_spellings + || std::env::var("SYSMLV2_UNIT_SPELLINGS").is_ok_and(|v| v == "off" || v == "0")); + sysmlv2_parser::eval::set_unit_spelling_expansion(expand_unit_spellings); + sysmlv2_parser::parser::on_parsing_stack("sysmlv2", say_the_stack_was_refused, move || { + dispatch(cli.command, quiet) + }) +} + +/// Say that the stack the parser's bound assumes could not be reserved. +/// +/// The verb runs anyway, on the process's own thread, which holds a +/// fraction of the nesting the parser accepts; input the bound admits can +/// run that stack out, and an overflow ends the process with no +/// diagnostic, no unwind and no status worth reading. This line, on the +/// error stream before the verb starts, is the only thing that says why +/// — so it is said whatever `--quiet` asked for, which silences notes +/// about a run that worked. +fn say_the_stack_was_refused(err: &std::io::Error) { + eprintln!("warning: {}", stack_refusal(err)); +} + +/// What [`say_the_stack_was_refused`] says. +fn stack_refusal(err: &std::io::Error) -> String { + format!( + "could not reserve the stack the parser's nesting bound assumes ({err}); \ + deeply nested input may end this run without a diagnostic" + ) +} + +/// The verb itself, on the stack [`run`] reserved for it. +#[allow(clippy::too_many_lines)] +fn dispatch(command: Command, quiet: bool) -> ExitCode { + match command { + Command::Convert { + inputs, + to, + output, + lib, + flexo, + min_qual, + elide_ids, + delta_base, + delta_portable, + indent, + library, + } => run_convert( + ConvertArgs { + inputs, + to, + output, + lib, + flexo, + min_qual, + elide_ids, + delta_base, + delta_portable, + indent, + library, + }, + quiet, + ), + Command::Payload { + inputs, + find_base, + lib, + delta_from, + portable, + claim_project, + claim_commit, + claim_service, + apply_to, + lenient, + ids, + tables, + encode, + output, + } => run_payload(PayloadArgs { + inputs, + find_base, + lib, + delta_from, + portable, + claim_project, + claim_commit, + claim_service, + apply_to, + lenient, + ids, + tables, + encode, + output, + }), + Command::Fmt { + files, + check, + stdout, + indent, + } => run_fmt(files, check, stdout, indent, quiet), + Command::Check { + files, + lib, + strict, + format, + } => run_check(files, lib.as_deref(), strict, format, quiet), + Command::Lint { + files, + lib, + config, + rule, + fix, + fix_deletes, + fix_semantic, + strict, + format, + } => run_lint( + LintArgs { + files, + lib, + config, + rule, + fix, + fix_deletes, + fix_semantic, + strict, + format, + }, + quiet, + ), + #[cfg(feature = "solve")] + Command::Verify { + files, + lib, + ranges, + solve, + z3, + } => finish(run_verify(files, lib.as_deref(), ranges, solve, z3, quiet)), + + Command::Eval { + input, + names, + all, + lib, + } => finish(run_eval(input, names, all, lib.as_deref(), quiet)), + + Command::Render { args, lib, html } => { + finish(run_render(args, lib.as_deref(), html, quiet)) + } + Command::Query { input, args, lib } => { + finish(run_query(input, args, lib.as_deref(), quiet)) + } + + Command::Describe { input, args, lib } => { + finish(run_describe(input, args, lib.as_deref(), quiet)) + } + + Command::Members { input, args, lib } => { + finish(run_members(input, args, lib.as_deref(), quiet)) + } + + Command::Refactor { op } => run_refactor(op, quiet), + Command::Parse { input, ast } => finish(run_parse(input, ast, quiet)), + #[cfg(feature = "viz")] + Command::Viz { + files, + view, + element, + lib, + horizontal, + no_values, + no_notes, + hide_metadata, + show_inherited, + show_lib, + show_imported, + line_style, + color, + link_template, + output, + } => finish(run_viz( + VizArgs { + files, + view, + element, + lib, + horizontal, + no_values, + no_notes, + hide_metadata, + show_inherited, + show_lib, + show_imported, + line_style, + color, + link_template, + output, + }, + quiet, + )), + + #[cfg(feature = "lsp")] + Command::Lsp { lib } => match sysmlv2_lsp::run_stdio(lib) { + Ok(()) => ExitCode::SUCCESS, + Err(e) => { + eprintln!("error: {e}"); + ExitCode::FAILURE + } + }, + } +} + +#[cfg(test)] +mod refactor_persistence_tests { + use super::*; + + struct TestDir(PathBuf); + + impl TestDir { + fn new() -> Self { + let path = std::env::temp_dir() + .join(format!("sysmlv2-cli-persist-test-{}", uuid::Uuid::new_v4())); + std::fs::create_dir(&path).expect("create test directory"); + Self(path) + } + } + + impl Drop for TestDir { + fn drop(&mut self) { + let _ = std::fs::remove_dir_all(&self.0); + } + } + + #[test] + fn a_later_replace_failure_rolls_back_earlier_files() { + let dir = TestDir::new(); + let a = dir.0.join("a.sysml"); + let b = dir.0.join("b.sysml"); + std::fs::write(&a, "old a\n").unwrap(); + std::fs::write(&b, "old b\n").unwrap(); + let changes = vec![ + RefactorFileChange { + path: a.clone(), + old: "old a\n".into(), + new: "new a\n".into(), + }, + RefactorFileChange { + path: b.clone(), + old: "old b\n".into(), + new: "new b\n".into(), + }, + ]; + let mut promotions = 0; + let error = persist_refactor_changes_with(&changes, |from, to| { + if from + .file_name() + .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")) + { + promotions += 1; + if promotions == 2 { + return Err(std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "simulated second replacement failure", + )); + } + } + std::fs::rename(from, to) + }) + .expect_err("second replacement must fail"); + + assert!(error.contains("simulated second replacement failure")); + assert!(error.contains("rolled back 1 earlier file(s)")); + assert_eq!(std::fs::read_to_string(a).unwrap(), "old a\n"); + assert_eq!(std::fs::read_to_string(b).unwrap(), "old b\n"); + let leftovers: Vec<_> = std::fs::read_dir(&dir.0) + .unwrap() + .map(|e| e.unwrap().file_name()) + .filter(|n| n.to_string_lossy().contains(".sysmlv2-")) + .collect(); + assert!(leftovers.is_empty(), "leftover sidecars: {leftovers:?}"); + } + + #[test] + fn a_concurrent_later_edit_is_preserved_while_earlier_files_roll_back() { + let dir = TestDir::new(); + let a = dir.0.join("a.sysml"); + let b = dir.0.join("b.sysml"); + std::fs::write(&a, "old a\n").unwrap(); + std::fs::write(&b, "old b\n").unwrap(); + let changes = vec![ + RefactorFileChange { + path: a.clone(), + old: "old a\n".into(), + new: "new a\n".into(), + }, + RefactorFileChange { + path: b.clone(), + old: "old b\n".into(), + new: "new b\n".into(), + }, + ]; + let mut promotions = 0; + let error = persist_refactor_changes_with(&changes, |from, to| { + let is_promotion = from + .file_name() + .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")); + let result = std::fs::rename(from, to); + if is_promotion { + promotions += 1; + if promotions == 1 { + std::fs::write(&b, "external b\n").unwrap(); + } + } + result + }) + .expect_err("concurrent second-file edit must refuse"); + + assert!(error.contains("changed on disk before it could be replaced")); + assert!(error.contains("rolled back 1 earlier file(s)")); + assert_eq!(std::fs::read_to_string(a).unwrap(), "old a\n"); + assert_eq!(std::fs::read_to_string(b).unwrap(), "external b\n"); + } + + #[test] + fn a_concurrent_edit_to_an_applied_file_is_not_overwritten_by_rollback() { + let dir = TestDir::new(); + let a = dir.0.join("a.sysml"); + let b = dir.0.join("b.sysml"); + std::fs::write(&a, "old a\n").unwrap(); + std::fs::write(&b, "old b\n").unwrap(); + let changes = vec![ + RefactorFileChange { + path: a.clone(), + old: "old a\n".into(), + new: "new a\n".into(), + }, + RefactorFileChange { + path: b.clone(), + old: "old b\n".into(), + new: "new b\n".into(), + }, + ]; + let mut promotions = 0; + let error = persist_refactor_changes_with(&changes, |from, to| { + let is_promotion = from + .file_name() + .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")); + if is_promotion { + promotions += 1; + if promotions == 2 { + return Err(std::io::Error::new( + std::io::ErrorKind::PermissionDenied, + "simulated second replacement failure", + )); + } + } + let result = std::fs::rename(from, to); + if is_promotion && promotions == 1 { + std::fs::write(&a, "external a\n").unwrap(); + } + result + }) + .expect_err("second replacement must fail"); + + assert!(error.contains("rollback incomplete"), "{error}"); + assert!(error.contains("external edit was preserved"), "{error}"); + assert!(error.contains("recovery copy:"), "{error}"); + assert_eq!(std::fs::read_to_string(&a).unwrap(), "external a\n"); + assert_eq!(std::fs::read_to_string(&b).unwrap(), "old b\n"); + let leftovers: Vec<_> = std::fs::read_dir(&dir.0) + .unwrap() + .map(|e| e.unwrap().path()) + .filter(|p| { + p.file_name() + .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-")) + }) + .collect(); + assert_eq!(leftovers.len(), 1, "retained recovery copy: {leftovers:?}"); + assert_eq!(std::fs::read_to_string(&leftovers[0]).unwrap(), "old a\n"); + } + + #[cfg(all(unix, not(target_os = "wasi")))] + #[test] + fn a_hard_linked_target_is_refused_without_splitting_the_links() { + let dir = TestDir::new(); + let path = dir.0.join("model.sysml"); + let alias = dir.0.join("alias.sysml"); + std::fs::write(&path, "old\n").unwrap(); + std::fs::hard_link(&path, &alias).unwrap(); + let changes = [RefactorFileChange { + path: path.clone(), + old: "old\n".into(), + new: "new\n".into(), + }]; + + let error = persist_refactor_changes(&changes).expect_err("hard link must refuse"); + + assert!(error.contains("has 2 hard links"), "{error}"); + assert_eq!(std::fs::read_to_string(path).unwrap(), "old\n"); + assert_eq!(std::fs::read_to_string(alias).unwrap(), "old\n"); + } + + #[cfg(all(unix, not(target_os = "wasi")))] + #[test] + fn a_successful_replacement_preserves_unix_file_metadata() { + use std::os::unix::fs::{MetadataExt, PermissionsExt}; + + let dir = TestDir::new(); + let path = dir.0.join("model.sysml"); + std::fs::write(&path, "old\n").unwrap(); + std::fs::set_permissions(&path, Permissions::from_mode(0o640)).unwrap(); + let xattr_name = if cfg!(target_os = "macos") { + "com.openmbee.sysmlv2-test" + } else { + "user.sysmlv2-test" + }; + xattr::set(&path, xattr_name, b"retained").unwrap(); + let original_metadata = std::fs::metadata(&path).unwrap(); + let changes = [RefactorFileChange { + path: path.clone(), + old: "old\n".into(), + new: "new\n".into(), + }]; + + persist_refactor_changes(&changes).expect("replacement succeeds"); + + assert_eq!(std::fs::read_to_string(&path).unwrap(), "new\n"); + let replaced_metadata = std::fs::metadata(&path).unwrap(); + assert_eq!(replaced_metadata.permissions().mode() & 0o777, 0o640); + assert_eq!(replaced_metadata.uid(), original_metadata.uid()); + assert_eq!(replaced_metadata.gid(), original_metadata.gid()); + assert_eq!( + xattr::get(path, xattr_name).unwrap().as_deref(), + Some(b"retained".as_slice()) + ); + } +} + +#[cfg(test)] +mod stack_tests { + use super::*; + + /// A run whose thread could not be given the stack the parser's + /// bound assumes used to fall back to the process's own with nothing + /// said — and input nested past that stack ends the process where + /// the descent runs out, with no diagnostic to explain it. The line + /// carries what the system said and what the run risks by it. + #[test] + fn a_run_whose_stack_is_refused_says_so() { + let refused = std::io::Error::new(std::io::ErrorKind::OutOfMemory, "no room for a thread"); + let said = stack_refusal(&refused); + assert!(said.contains("no room for a thread"), "{said}"); + assert!(said.contains("nesting bound"), "{said}"); + assert!(said.contains("without a diagnostic"), "{said}"); + } +} diff --git a/crates/sysmlv2-cli/src/main.rs b/crates/sysmlv2-cli/src/main.rs index fdb9f9e..423a623 100644 --- a/crates/sysmlv2-cli/src/main.rs +++ b/crates/sysmlv2-cli/src/main.rs @@ -1,4532 +1,6 @@ -//! `sysmlv2` — CLI for the sysmlv2-parser library: convert, format, and check -//! SysML v2 / KerML models. +//! The `sysmlv2` command line. Everything it does lives in the library +//! beside it, so the verbs run (and are tested) in process too. -use clap::{Parser, Subcommand, ValueEnum}; -use std::collections::{HashMap, HashSet}; -use std::fs::{OpenOptions, Permissions}; -use std::io::Write; -use std::path::{Path, PathBuf}; -use std::process::ExitCode; -use sysmlv2_parser::Diagnostic; -use sysmlv2_parser::ast::Dialect; -use sysmlv2_parser::full::{model_to_full_json_with, to_full_json_with}; -use sysmlv2_parser::json::{library_name_map, model_to_compact_json_with_units, to_compact_json}; -use sysmlv2_parser::lift::from_compact_json_with_names; -use sysmlv2_parser::model::Model; -use sysmlv2_parser::parser::{Parse, parse_kerml_source, parse_source}; -use sysmlv2_parser::print::{Indent, PrintOptions, format_source_with, print_source_opts}; -use sysmlv2_parser::span::{LineIndex, Span}; - -mod kpar; - -/// Load the standard library into `model` through the resolution cache -/// (`~/.cache/sysmlv2`; override the directory with `SYSMLV2_CACHE_DIR`, -/// disable caching with `SYSMLV2_LIB_CACHE=off`). A cache hit replays the -/// recorded outcomes during the next build; a miss arms recording — pass -/// the returned path to [`save_library_cache`] once the model was built. -fn load_library(model: &mut Model, dir: &Path) -> std::io::Result> { - model.load_library_dir(dir)?; - // The generated ambient libraries (`Web`, `Template`, engine - // overlays, `TransformMeta`) ride along with every library load; - // their content is part of the cache key. - sysmlv2_parser::ambient::add_to(model); - if std::env::var_os("SYSMLV2_LIB_CACHE").is_some_and(|v| v == "off") { - return Ok(None); - } - let Ok(key) = sysmlv2_parser::libcache::hash_library_dir(dir) else { - return Ok(None); - }; - let key = sysmlv2_parser::ambient::mix_key(key); - let Some(path) = sysmlv2_parser::libcache::default_cache_path(key) else { - return Ok(None); - }; - match sysmlv2_parser::libcache::LibraryCache::load(&path) { - Some(cache) => { - model.set_library_cache(cache); - // The path is still returned: a failed snapshot validation - // rebuilds cold and re-records, and the save then overwrites - // the stale file (saves only happen when something recorded). - Ok(Some(path)) - } - None => { - model.record_library_cache(); - Ok(Some(path)) - } - } -} - -/// Inverse of [`flexo_payload`] for Flexo *responses*: unwrap -/// `{payload, identity}` change records when present and normalize the -/// server's empty-string property values back to null, so the element -/// list lifts like ordinary interchange JSON. -fn flexo_unwrap(value: serde_json::Value) -> serde_json::Value { - fn empties_to_null(v: &mut serde_json::Value) { - match v { - serde_json::Value::Object(map) => { - for (_, val) in map.iter_mut() { - if val.as_str() == Some("") { - *val = serde_json::Value::Null; - } else { - empties_to_null(val); - } - } - } - serde_json::Value::Array(items) => items.iter_mut().for_each(empties_to_null), - _ => {} - } - } - let serde_json::Value::Array(items) = value else { - return value; - }; - let wrapped = !items.is_empty() - && items - .iter() - .all(|r| r.get("payload").is_some() && r.get("identity").is_some()); - let mut elements: Vec = if wrapped { - items.into_iter().map(|mut r| r["payload"].take()).collect() - } else { - items - }; - elements.iter_mut().for_each(empties_to_null); - serde_json::Value::Array(elements) -} - -/// Flexo MMS commit conventions: name each root namespace after its source -/// file (Flexo stores the file name in the root's `qualifiedName` and -/// splits documents on it when reading back), then wrap every element as a -/// `{payload, identity}` change record with null property values emptied -/// (matching the Flexo MMS payload shape byte for byte). -fn flexo_payload(mut json: serde_json::Value, input_names: &[String]) -> serde_json::Value { - let serde_json::Value::Array(elements) = &mut json else { - return json; - }; - let mut root_i = 0usize; - for e in elements.iter_mut() { - let is_root = e.get("@type").and_then(|v| v.as_str()) == Some("Namespace") - && e.get("owningRelationship") - .is_none_or(serde_json::Value::is_null); - if is_root { - if let Some(name) = input_names.get(root_i) { - e["qualifiedName"] = serde_json::Value::String(name.clone()); - } - root_i += 1; - } - } - fn nulls_to_empty(v: &mut serde_json::Value) { - match v { - serde_json::Value::Object(map) => { - for (_, val) in map.iter_mut() { - if val.is_null() { - *val = serde_json::Value::String(String::new()); - } else { - nulls_to_empty(val); - } - } - } - serde_json::Value::Array(items) => items.iter_mut().for_each(nulls_to_empty), - _ => {} - } - } - let wrapped = elements - .iter() - .map(|e| { - let id = e.get("@id").cloned().unwrap_or(serde_json::Value::Null); - let mut payload = e.clone(); - nulls_to_empty(&mut payload); - serde_json::json!({ "payload": payload, "identity": { "@id": id } }) - }) - .collect(); - serde_json::Value::Array(wrapped) -} - -/// File name for one split document: the root namespace's recorded name -/// when it is a plain model file name (the Flexo convention), else a -/// numbered fallback. -fn doc_file_name(root_name: Option<&str>, index: usize) -> String { - if let Some(name) = root_name { - let base = Path::new(name) - .file_name() - .map(|n| n.to_string_lossy().into_owned()) - .unwrap_or_default(); - let safe = !base.is_empty() - && base - .chars() - .all(|c| c != ':' && c != '*' && c != '?' && c != '"'); - if safe && (base.ends_with(".sysml") || base.ends_with(".kerml")) { - return base; - } - } - format!("document-{}.sysml", index + 1) -} - -/// Persist the outcomes recorded by the first build after [`load_library`] -/// armed recording. Best-effort: the cache is an accelerator only. -fn save_library_cache(model: &Model, path: Option) { - if let (Some(path), Some(cache)) = (path, model.take_recorded_library_cache()) { - let _ = cache.save(&path); - } -} - -#[derive(Parser)] -#[command( - name = "sysmlv2", - version, - about = "Parse, convert, format, and check SysML v2 / KerML models", - long_about = "Parse, convert, format, and check OMG SysML v2 / KerML textual models.\n\ - \n\ - Conversion matrix (--to):\n\ - \x20 text textual notation (.sysml / .kerml)\n\ - \x20 compact-json KerML 10.4 compact interchange form\n\ - \x20 compact-cbor binary re-encoding of the compact form\n\ - \x20 full-json derived properties + implied relationships (schema-valid)\n\ - \x20 full-cbor binary re-encoding of the full form (emit view)\n\ - \x20 kpar KerML 10.3 project archive (zipped units + manifests)\n\ - \n\ - Inputs may be textual (.sysml / .kerml), interchange JSON (.json),\ - compact CBOR (.s2c), or project archives (.kpar, expanded to\n\ - their textual units);\n\ - full-form JSON input is normalized to compact automatically.\n\ - Pass --lib (e.g. the OMG sysml.library directory) to resolve\n\ - standard-library references to their normative element IDs — and to\n\ - name them again when converting JSON back to text.\n\ - \n\ - Anywhere a file path is accepted, `-` reads from stdin (parsed as\n\ - SysML unless the input is sniffed as JSON).\n\ - \n\ - Standard-library loads are cached automatically: the first run\n\ - against a library records a sealed snapshot (resolutions + element\n\ - ids) under ~/.cache/sysmlv2/, keyed by library content and stamped\n\ - with the exact toolkit build — later runs replay it, and any\n\ - mismatch (including a toolkit rebuilt from changed sources at the\n\ - same version) rebuilds cold and refreshes the file. Set\n\ - SYSMLV2_CACHE_DIR to relocate the cache or SYSMLV2_LIB_CACHE=off\n\ - to disable it (e.g. for benchmarking).\n\ - \n\ - Ambient model context: when SYSMLV2_MODEL_DIR names a directory,\n\ - its .sysml/.kerml files stand in for omitted input files (fmt\n\ - honors this under --check only), and a stderr note records that\n\ - ambient state supplied the inputs (silence it with -q).\n\ - SYSMLV2_LIB_DIR fills --lib the same way wherever it is accepted.\n\ - With the variable set, --help ends with the active context.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 convert model.sysml --to compact-json\n\ - \x20 sysmlv2 convert model.sysml --to compact-json --lib sysml.library/ -o model.json\n\ - \x20 cat model.sysml | sysmlv2 convert - --to compact-json\n\ - \x20 sysmlv2 fmt src/**/*.sysml\n\ - \x20 sysmlv2 fmt --check model.sysml\n\ - \x20 sysmlv2 check model.sysml lib.kerml\n\ - \x20 sysmlv2 parse model.sysml --ast" -)] -struct Cli { - #[command(subcommand)] - command: Command, - /// Suppress informational stderr notes (e.g. the ambient - /// model-context line printed when SYSMLV2_MODEL_DIR supplies the - /// input files) - #[arg(short, long, global = true)] - quiet: bool, - /// Keep quoted power-product unit spellings (`'m³⋅s⁻²'`) opaque - /// instead of expanding them by parsing the name — the evaluator - /// then treats such a unit as its own base dimension, convertible - /// with nothing [env: SYSMLV2_UNIT_SPELLINGS=off] - #[arg(long = "no-unit-spellings", global = true)] - no_unit_spellings: bool, -} - -#[derive(Clone, Copy, PartialEq, ValueEnum)] -enum Target { - /// Textual notation - Text, - /// Compact interchange JSON (KerML 10.4; no implied relationships) - CompactJson, - /// Compact interchange CBOR: the deterministic binary - /// re-encoding of compact JSON (binary output; use -o) - CompactCbor, - /// Full interchange JSON: derived properties + implied relationships - FullJson, - /// Full interchange CBOR: the binary re-encoding of full JSON - /// (emit view only; binary output; use -o) - FullCbor, - /// KerML 10.3 project archive (.kpar): zipped textual units + manifests - Kpar, -} - -#[derive(Subcommand)] -enum Command { - /// Convert a model between textual notation and interchange JSON - #[command( - long_about = "Convert a model between textual notation and interchange JSON/CBOR.\n\ - \n\ - The input format is detected from the file extension:\n\ - .sysml / .kerml parse as textual notation; .json is lifted from\n\ - the interchange form (full-form JSON is normalized to compact —\n\ - implied relationships dropped, derived properties ignored);\n\ - .s2c decodes as compact-form CBOR and then flows like .json.\n\ - With --lib, text→JSON resolves standard-library references to\n\ - their normative KerML 9.1 element IDs, and JSON→text turns those\n\ - IDs back into qualified names.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 convert model.sysml --to compact-json\n\ - \x20 sysmlv2 convert model.json --to text -o model.sysml\n\ - \x20 sysmlv2 convert model.json --to text --min-qual # shortest reference spellings\n\ - \x20 sysmlv2 convert full.json --to compact-json # normalize full → compact\n\ - \x20 sysmlv2 convert model.sysml --to compact-cbor -o model.s2c\n\ - \x20 sysmlv2 convert model.s2c --to text # binary → textual notation\n\ - \x20 sysmlv2 convert model.sysml --to compact-json --lib spec-refs/SysML-v2-Release/sysml.library" - )] - Convert { - /// Input files (.sysml / .kerml — several form one model with one - /// root namespace per file), or a single .json / .s2c; `-` for - /// stdin (text or JSON); optional when SYSMLV2_MODEL_DIR is set - inputs: Vec, - /// Output format - #[arg(long, value_enum)] - to: Target, - /// Output file (defaults to stdout). For `--to text` with a - /// multi-document JSON input, an existing directory splits the - /// output into one file per root namespace - #[arg(short, long)] - output: Option, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Flexo MMS conventions on JSON output: each root namespace's - /// qualifiedName is set to its source file name and every element - /// is wrapped as a `{payload, identity}` change record - #[arg(long)] - flexo: bool, - /// JSON → text only: respell every reference with the shortest - /// spelling that still resolves to the same element (bare name - /// where unambiguous, a qualified suffix where needed), verified - /// by reparse; without it references print as always-correct - /// `$::`-rooted paths - #[arg(long = "min-qual")] - min_qual: bool, - /// --to compact-cbor only: omit graph-derivable element ids - /// (IDS.md) — receivers recompute them, verified by the - /// payload's integrity digest. Composes with --delta-base - /// (strict deltas: created ids elide). Decode/apply against - /// the same --lib version the payload was encoded with - #[arg(long = "elide-ids")] - elide_ids: bool, - /// Delta base (compact .json or .s2c). With --to compact-cbor - /// the output becomes a delta against it; with a - /// delta .s2c input the delta is applied to it first - #[arg(long = "delta-base")] - delta_base: Option, - /// Delta output only: id-keyed identities, applicable - /// best-effort to divergent bases (larger than the strict - /// indexed default) - #[arg(long = "delta-portable")] - delta_portable: bool, - /// Indentation for textual output: `tabs` or a space count - /// (default 4) - #[arg(long, value_parser = parse_indent_arg, default_value = "4")] - indent: Indent, - /// Emit the resolved standard library itself — every element - /// of the --lib units, each under its normative KerML 9.1 id — - /// instead of converting a model. The complement of a normal - /// conversion, whose output holds just the user units' elements - /// while its library references dangle by design. Takes no - /// inputs; targets compact-json and compact-cbor - #[arg(long, requires = "lib")] - library: bool, - }, - /// Inspect payload files, or diff/apply them at payload identity - #[command( - long_about = "Inspect interchange payload files without loading them as a\n\ - model: what each file is (compact/full snapshot or delta),\n\ - its header versions, element and change counts, and its\n\ - content digests. Snapshots (.s2c or compact .json) report\n\ - their state digest — the digest a delta's base digest is\n\ - matched against. Deltas report their base and result\n\ - digests without needing the base present.\n\ - \n\ - With --find-base, every snapshot file under a directory is\n\ - digested once and each delta input reports which of them it\n\ - applies to cleanly (state digest = the delta's base digest)\n\ - and which already hold its result. A delta with no base\n\ - match fails the command, so the verb scripts as a check.\n\ - \n\ - Every mode of this verb works at payload identity: files\n\ - are read exactly as their producer wrote them — no model\n\ - lift, no id re-derivation, no rebase. --delta-from diffs\n\ - two snapshots by element @id (a store whose ids are\n\ - authoritative diffs its own states losslessly; contrast\n\ - `convert --delta-base`, which re-derives and rebases ids\n\ - for freshly parsed inputs). --apply-to applies a delta and\n\ - reports what happened. --ids prints a snapshot's\n\ - delta-canonical element id sequence — the index space\n\ - strict deltas address their base through.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 payload model.s2c\n\ - \x20 sysmlv2 payload edit.s2c --find-base exports/\n\ - \x20 sysmlv2 payload base.s2c edit.s2c # digests to match by hand\n\ - \x20 sysmlv2 payload new.json --delta-from old.json -o commit.s2c\n\ - \x20 sysmlv2 payload commit.s2c --apply-to old.json -o new.json\n\ - \x20 sysmlv2 payload model.s2c --ids" - )] - Payload { - /// Payload files: .s2c (snapshot or delta) or compact - /// interchange .json - inputs: Vec, - /// Directory to scan (recursively) for snapshot files whose - /// state digest matches each delta's base or result digest - #[arg(long = "find-base", value_name = "DIR")] - find_base: Option, - /// Standard-library directory — lets id-elided snapshots with - /// library-typed elements re-derive their ids for digesting - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Emit a delta from BASE to the single snapshot input, pairing - /// elements by @id — producer ids are authoritative on both - /// sides. Strict (indexed) unless --portable - #[arg(long = "delta-from", value_name = "BASE", - conflicts_with_all = ["find_base", "apply_to", "ids"])] - delta_from: Option, - /// With --delta-from: id-keyed delta identities, applicable - /// best-effort to a divergent base - #[arg(long, requires = "delta_from")] - portable: bool, - /// With --delta-from: claim key 0 — the project the delta - /// belongs to (routing hint; the digest is the proof) - #[arg(long = "claim-project", value_name = "UUID", requires = "delta_from")] - claim_project: Option, - /// With --delta-from: claim key 1 — the commit the base names - #[arg(long = "claim-commit", value_name = "UUID", requires = "delta_from")] - claim_commit: Option, - /// With --delta-from: claim key 2 — the emitting service - #[arg(long = "claim-service", value_name = "URI", requires = "delta_from")] - claim_service: Option, - /// Apply the single delta input to the snapshot BASE; the - /// applied compact JSON goes to --output, the apply report - /// (JSON) to stdout - #[arg(long = "apply-to", value_name = "BASE", - conflicts_with_all = ["find_base", "ids"])] - apply_to: Option, - /// With --apply-to: portable deltas apply best-effort to a - /// divergent base; the report counts the divergences - #[arg(long, requires = "apply_to")] - lenient: bool, - /// Print each snapshot input's delta-canonical element id - /// sequence with its state digest - #[arg(long, conflicts_with = "find_base")] - ids: bool, - /// Print the codec tables as versioned JSON — the artifact a - /// consumer vendors to label payload structure without this - /// toolkit: metaclass wire codes with per-ordinal field tables - /// (property, kind, enum table, presence default), both the - /// compact and full ordinal spaces, the enum vocabularies, and - /// the header version axes and flags. Takes no payload inputs - #[arg(long, conflicts_with_all = ["find_base", "delta_from", "apply_to", "ids"])] - tables: bool, - /// Encode the single compact-JSON snapshot input to `.s2c` at - /// payload identity — no lift, no id re-derivation (contrast - /// `convert`, which parses its input as a model and re-derives - /// ids). The store-side inverse of a snapshot decode - #[arg(long, conflicts_with_all = ["find_base", "delta_from", "apply_to", "ids", "tables"])] - encode: bool, - /// Output file: the delta payload (--delta-from) or the applied - /// compact JSON (--apply-to) - #[arg(short, long)] - output: Option, - }, - /// Format .sysml / .kerml files in place (canonical style) - #[command( - long_about = "Format textual models to the canonical style: four-space\n\ - indentation, one member per line, symbolic specialization\n\ - operators. Notes (// …) and blank lines are preserved.\n\ - Files with parse errors are left untouched and reported.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 fmt model.sysml # rewrite in place\n\ - \x20 sysmlv2 fmt a.sysml b.kerml # several files\n\ - \x20 sysmlv2 fmt --check model.sysml # exit 1 if not formatted\n\ - \x20 sysmlv2 fmt --stdout model.sysml # print instead of rewriting\n\ - \x20 cat model.sysml | sysmlv2 fmt --stdout - # format stdin" - )] - Fmt { - /// Files to format; `-` reads stdin (requires --stdout or - /// --check); with --check, optional when SYSMLV2_MODEL_DIR is set - files: Vec, - /// Verify formatting without writing; exit 1 if any file differs - #[arg(long)] - check: bool, - /// Print the formatted output instead of rewriting the file - #[arg(long)] - stdout: bool, - /// Indentation for formatted output: `tabs` or a space count - /// (default 4) - #[arg(long, value_parser = parse_indent_arg, default_value = "4")] - indent: Indent, - }, - /// Parse and validate files (syntax + body-context legality; exit 1 on - /// any error). With --lib, also runs referential checks as warnings. - #[command(after_help = "Checks run in stages: parse diagnostics, then\n\ - body-context validation (members that the grammar\n\ - does not allow in their surrounding body, e.g. a\n\ - `transition` inside a plain `part` body, or a\n\ - `variant` member outside a `variation`).\n\ - With --lib, all files form one model resolved\n\ - against the library; referential findings are\n\ - warnings (unresolved references, alias targets,\n\ - circular imports), and semantic constraints are\n\ - checked (multiplicity bounds, self/circular\n\ - specialization — errors; duplicate\n\ - specializations — warnings). Private imports\n\ - that provably feed nothing in their unit warn\n\ - as `unused private import`.\n\ - Warnings never fail the run unless --strict is\n\ - given, which exits 1 on any finding at all.\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 check model.sysml\n\ - \x20 sysmlv2 check src/*.sysml lib/*.kerml\n\ - \x20 sysmlv2 check model.sysml --lib spec-refs/SysML-v2-Release/sysml.library\n\ - \x20 sysmlv2 check --strict --lib sysml.library/ model.sysml\n\ - \x20 cat model.sysml | sysmlv2 check -")] - Check { - /// Files to check; `-` reads stdin; optional when - /// SYSMLV2_MODEL_DIR is set - files: Vec, - /// Standard-library directory; enables referential checks - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Treat warnings as failures: exit 1 on any finding (for - /// pipelines that must refuse incomplete models, e.g. gating a - /// Flexo commit) - #[arg(long)] - strict: bool, - }, - /// Lint the model against configurable project-policy rules - #[command(after_help = "Rules are policy, not language law: lint runs\n\ - beside `check` and never changes its verdicts.\n\ - Config JSON: { \"rules\": { \"\": \"off\" |\n\ - \"hint\" | \"info\" | \"warn\" | \"error\" |\n\ - { \"severity\": …, \"scopes\": { \"\":\n\ - … }, …options } } } — default sysmlint.json\n\ - beside the first input. Policy rules default\n\ - off (undocumented-element,\n\ - untyped-usage, unused-definition,\n\ - unused-parameter, unit-spelling,\n\ - multiline-conditions, indentation) — opt in per\n\ - rule or per stereotype scope;\n\ - naming-convention defaults info (a casing\n\ - nudge — tighten or disable per project) and\n\ - dimensional-consistency warns by default (a\n\ - declared quantity type contradicting its value's\n\ - unit is a finding anywhere).\n\ - --fix applies safe fixes; fixes that DELETE model\n\ - text (e.g. removing an unused parameter) are\n\ - guarded behind --fix-deletes so information is\n\ - never lost without explicit approval.\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 lint model.sysml\n\ - \x20 sysmlv2 lint --config sysmlint.json src/*.sysml\n\ - \x20 sysmlv2 lint --rule unused-definition=warn model.sysml\n\ - \x20 sysmlv2 lint --fix --fix-deletes model.sysml\n\ - \x20 sysmlv2 lint --strict model.sysml")] - Lint { - /// Files to lint; `-` reads stdin; optional when - /// SYSMLV2_MODEL_DIR is set - files: Vec, - /// Standard-library directory (resolution context only; library - /// elements are never linted) - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Lint config JSON; defaults to sysmlint.json beside the first - /// input when present - #[arg(long)] - config: Option, - /// Override one rule's severity, e.g. unused-definition=warn - /// (repeatable; wins over the config file) - #[arg(long = "rule", value_name = "ID=LEVEL")] - rule: Vec, - /// Apply available auto-fixes that do not delete model text - #[arg(long)] - fix: bool, - /// With --fix: also apply fixes that DELETE model text (an - /// unused parameter's fix removes its declaration — deliberate - /// extra consent, deletions lose information) - #[arg(long, requires = "fix")] - fix_deletes: bool, - /// Exit 1 on any error-severity finding - #[arg(long)] - strict: bool, - }, - /// Check constraint/requirement bodies to verdicts - #[cfg(feature = "solve")] - #[command(after_help = "Evaluates every constraint, requirement, and\n\ - invariant body that carries its own trailing\n\ - result expression: satisfied / violated /\n\ - undecided (with the reason — unbound features,\n\ - unsupported constructs). Exit 1 if any\n\ - constraint is violated.\n\n\ - With --ranges, interval propagation narrows every\n\ - unbound feature to a finite range and upgrades\n\ - verdicts (satisfied/VIOLATED/unsatisfiable) with\n\ - no external solver.\n\n\ - With --solve, propagation runs first and Z3 (the\n\ - `z3` binary; see --z3) then handles only what it\n\ - left undecided: proved to hold for all values of\n\ - the unbound features (satisfied), proved\n\ - unsatisfiable (VIOLATED), or satisfiable with a\n\ - witness assignment.\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 verify model.sysml\n\ - \x20 sysmlv2 verify model.sysml --ranges\n\ - \x20 sysmlv2 verify model.sysml --solve\n\ - \x20 sysmlv2 verify src/*.sysml --lib spec-refs/SysML-v2-Release/sysml.library")] - Verify { - /// Input files (.sysml or .kerml) forming one model; `-` reads - /// stdin; optional when SYSMLV2_MODEL_DIR is set - files: Vec, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Interval-propagate undecided constraints and print narrowed - /// feature ranges (no external solver) - #[arg(long)] - ranges: bool, - /// Run Z3 over undecided constraints (witnesses, proofs); implies - /// propagation first, so Z3 only sees what it left undecided - #[arg(long)] - solve: bool, - /// Path to the z3 binary (default: `z3` on PATH) - #[arg(long, value_name = "PATH")] - z3: Option, - }, - /// Evaluate feature values in a model (expression evaluator) - #[command(after_help = "Evaluates the bound value expression of each named\n\ - feature against the resolved model: literals,\n\ - arithmetic/logical/comparison operators, ranges,\n\ - sequences, feature references (redefinition-aware),\n\ - and Kernel Function Library intrinsics incl.\n\ - collect/select/reduce lambdas. Use --all to list\n\ - every feature with a computed value.\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 eval model.sysml Demo::car::mass\n\ - \x20 sysmlv2 eval model.sysml --all --lib spec-refs/SysML-v2-Release/sysml.library\n\ - \x20 sysmlv2 eval a.sysml b.sysml --all\n\ - \x20 sysmlv2 eval model.sysml 'Pkg::totalMass' 'Pkg::cost'")] - Eval { - /// Input file (.sysml or .kerml), or `-` for stdin; optional when - /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a - /// name, not a file) - input: Option, - /// Qualified names to evaluate (e.g. `Pkg::part::attr`); arguments - /// ending in `.sysml`/`.kerml` are further files joining the model - names: Vec, - /// Evaluate every feature that has a value expression - #[arg(long)] - all: bool, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, - /// Query a model with an ad-hoc KerML expression - #[command( - long_about = "Query a model with an ad-hoc KerML expression, evaluated\n\ - against the root namespace — references resolve exactly\n\ - as they would in a model file (qualified names, feature\n\ - chains, select/collect/reduce lambdas, KFL intrinsics).\n\ - \n\ - Two extensions apply only here (never to feature values\n\ - in model files): `istype`/`as` on a model element\n\ - classify the declaration itself, so a miss against a\n\ - user-defined type answers `false` instead of undecided;\n\ - and the reflection functions `ownedMember(x)` /\n\ - `ownedFeature(x)` (the KerML derived properties as\n\ - functions) enumerate an element's owned members.\n\ - \n\ - A sequence result prints one item per line; elements\n\ - print as qualified name and metaclass.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 query model.sysml 'ownedFeature(Vehicle)->select { in p; p istype Wheel }'\n\ - \x20 sysmlv2 query model.sysml 'Demo::car.totalMass + 10'\n\ - \x20 sysmlv2 query a.sysml b.sysml 'size(ownedMember(Demo))'\n\ - \x20 cat model.sysml | sysmlv2 query - 'ownedFeature(Vehicle)'" - )] - Query { - /// Input file (.sysml or .kerml), or `-` for stdin; optional when - /// SYSMLV2_MODEL_DIR is set (the expression alone then suffices) - input: Option, - /// The query expression; arguments ending in `.sysml`/`.kerml` - /// are further files joining the model - args: Vec, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, - /// Render a view's template over its exposed model slice (semantic mode) - #[command( - long_about = "Render the component template a view usage presents over the\n\ - model elements the view exposes (semantic mode): the\n\ - view's rendering definition owns an imported template root whose\n\ - translated expressions evaluate over the exposed slice. Prints the\n\ - rendered tree as JSON, or as HTML with --html. The model is not\n\ - modified.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 render --lib sysml.library model.sysml PackagesView.sysml Site::packagesView\n\ - \x20 sysmlv2 render --lib sysml.library --html app.sysml App::home" - )] - Render { - /// Model files (.sysml/.kerml) followed by the view usage's qualified name - args: Vec, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Print HTML instead of the JSON node tree - #[arg(long)] - html: bool, - }, - /// Describe one element: metaclass, owner, typing, position - #[command( - long_about = "Describe one element of the resolved model: its metaclass,\n\ - owner, declared type, position among its owner's members,\n\ - and declaration site.", - after_help = "EXAMPLES:\n\ - \x20 sysmlv2 describe model.sysml Demo::car\n\ - \x20 sysmlv2 describe a.sysml b.sysml Demo::car::mass\n\ - \x20 sysmlv2 describe Demo::car (SYSMLV2_MODEL_DIR set)" - )] - Describe { - /// Input file (.sysml or .kerml), or `-` for stdin; optional when - /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a - /// name, not a file) - input: Option, - /// The ::-qualified element name; arguments ending in - /// `.sysml`/`.kerml` are further files joining the model - args: Vec, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, - /// List an element's owned members - #[command(after_help = "EXAMPLES:\n\ - \x20 sysmlv2 members model.sysml Demo\n\ - \x20 sysmlv2 members model.sysml Demo::car\n\ - \x20 sysmlv2 members Demo (SYSMLV2_MODEL_DIR set)")] - Members { - /// Input file (.sysml or .kerml), or `-` for stdin; optional when - /// SYSMLV2_MODEL_DIR is set (a leading qualified name is then a - /// name, not a file) - input: Option, - /// The ::-qualified element name; arguments ending in - /// `.sysml`/`.kerml` are further files joining the model - args: Vec, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, - /// Parse one file and dump diagnostics (and optionally the AST) - #[command(after_help = "EXAMPLES:\n\ - \x20 sysmlv2 parse model.sysml\n\ - \x20 sysmlv2 parse model.sysml --ast\n\ - \x20 cat model.sysml | sysmlv2 parse -")] - Parse { - /// Input file, or `-` for stdin; optional when SYSMLV2_MODEL_DIR - /// is set (each discovered file parses independently) - input: Option, - /// Pretty-print the syntax tree - #[arg(long)] - ast: bool, - }, - /// Emit a PlantUML diagram - #[cfg(feature = "viz")] - #[command(after_help = "Renders one view of the model as PlantUML text\n\ - (feed it to any PlantUML build to get SVG/PNG):\n\n\ - \x20 tree structure: packages, definitions, and\n\ - \x20 usages with attribute compartments, plus\n\ - \x20 composition/typing/specialization edges\n\ - \x20 interconnection parts as nested blocks with ports;\n\ - \x20 connections, interfaces, bindings, and\n\ - \x20 flows as edges between their ends\n\ - \x20 state state machines: states, transitions\n\ - \x20 (trigger [guard] / effect), entry/do/exit\n\ - \x20 action action flows: actions, control nodes,\n\ - \x20 successions, dashed flow edges\n\ - \x20 sequence lifelines and messages between events,\n\ - \x20 ordered by event successions\n\ - \x20 case use cases: actors, subjects, objectives,\n\ - \x20 «include» edges\n\ - \x20 mixed everything on one canvas: structure,\n\ - \x20 connectors, behaviors, cases, typing\n\n\ - Comment/doc bodies attach as notes (--no-notes to\n\ - omit); --color keys node colors on the metaclass;\n\ - --link-template embeds [[hyperlinks]] carried into\n\ - rendered SVG.\n\n\ - Library elements never render as nodes; with --lib\n\ - their names still appear in labels (attribute\n\ - types, supertypes, definition ports).\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 viz model.sysml\n\ - \x20 sysmlv2 viz model.sysml --view interconnection\n\ - \x20 sysmlv2 viz model.sysml --element Pkg::Part -o part.puml\n\ - \x20 sysmlv2 viz model.sysml --view mixed --color --link-template \"vscode://file/{file}:{line}\"\n\ - \x20 sysmlv2 viz src/*.sysml --lib sysml.library/ | java -jar plantuml.jar -tsvg -p > model.svg")] - Viz { - /// Files to render; `-` reads stdin; optional when - /// SYSMLV2_MODEL_DIR is set - files: Vec, - /// View to render: tree, interconnection, state, action, - /// sequence, case, or mixed. Default: tree — except when - /// --element targets a view usage, whose own `render` member - /// picks the style - #[arg(long)] - view: Option, - /// Root the diagram at this ::-qualified element - #[arg(long)] - element: Option, - /// Standard-library directory (names library references in labels) - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - /// Lay the diagram out left-to-right instead of top-to-bottom - #[arg(long)] - horizontal: bool, - /// Omit `= value` on attribute compartment lines - #[arg(long)] - no_values: bool, - /// Omit comment/doc bodies (attached as notes by default) - #[arg(long)] - no_notes: bool, - /// Hide metadata (annotation stereotypes and metadata nodes) - #[arg(long)] - hide_metadata: bool, - /// Add inherited compartment lines (one explicit hop, ^-marked) - #[arg(long)] - show_inherited: bool, - /// Render referenced standard-library types as marked nodes - #[arg(long)] - show_lib: bool, - /// Draw «import» edges between rendered nodes - #[arg(long)] - show_imported: bool, - /// Edge routing: polyline or ortho (default: PlantUML splines) - #[arg(long)] - line_style: Option, - /// Color nodes by metaclass family - #[arg(long)] - color: bool, - /// Hyperlink template for nodes; placeholders {file} {line} - /// {col} {qname} {id} (e.g. "vscode://file/{file}:{line}") - #[arg(long)] - link_template: Option, - /// Write the PlantUML text here instead of stdout - #[arg(short, long)] - output: Option, - }, - /// Usage↔definition refactorings: extract / inline - #[command( - long_about = "Move between the usage-oriented and definition-oriented\n\ - modeling styles:\n\ - \n\ - extract a usage's inline body becomes a new definition,\n\ - \x20 the usage retyped by it —\n\ - \x20 `part engine : A { … }` becomes\n\ - \x20 `part def Engine :> A { … }` + `part engine : Engine;`\n\ - inline a definition's body merges into its sole typed\n\ - \x20 usage and the definition is deleted\n\ - \n\ - Inlining a definition just produced by extract restores the\n\ - original text byte-for-byte. Both directions are verified\n\ - commits: every carried reference is checked at its new home,\n\ - newly unresolved references or body-context violations roll\n\ - the edit back, and the touched usage's effective members\n\ - must be structurally unchanged. Refusals name their reason\n\ - (ineligible kind, header shape, name collision, outside\n\ - references, …) and leave every file untouched." - )] - Refactor { - #[command(subcommand)] - op: RefactorOp, - }, - /// Run the Language Server Protocol server over stdio - #[cfg(feature = "lsp")] - #[command(after_help = "Speaks LSP over stdio until the client ends the\n\ - session — run it from an editor, not a terminal.\n\ - Serves parse + body-context diagnostics on every\n\ - change and whole-document formatting; position\n\ - encoding negotiates utf-8 when offered (utf-16\n\ - otherwise). Dialect follows the file extension\n\ - (.kerml is KerML, everything else SysML).\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 lsp (as an editor's configured server command)\n\ - \x20 vim.lsp.start { cmd = { 'sysmlv2', 'lsp' } } (Neovim config)")] - Lsp { - /// Standard-library directory: hover/definition/references/rename - /// resolve standard-library names too (cached, ~0.15 s warm) - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, -} - -/// The two refactoring directions. Reads follow the ambient-input -/// convention; in-place writes require explicit file paths — -/// the fmt precedent for destructive verbs — and `--dry-run` prints the -/// would-be changes instead. -#[derive(Subcommand)] -enum RefactorOp { - /// Extract a usage's inline body into a new definition - #[command(after_help = "EXAMPLES:\n\ - \x20 sysmlv2 refactor extract model.sysml Rig::engine\n\ - \x20 sysmlv2 refactor extract model.sysml Rig::engine --name Motor\n\ - \x20 sysmlv2 refactor extract Rig::engine --dry-run (SYSMLV2_MODEL_DIR set)")] - Extract { - /// Input file (.sysml or .kerml); optional when SYSMLV2_MODEL_DIR - /// is set (a leading qualified name is then a name, not a file) - input: Option, - /// The ::-qualified usage name; arguments ending in - /// `.sysml`/`.kerml` are further files joining the model - args: Vec, - /// Definition name (default: UpperCamel of the usage's name) - #[arg(long)] - name: Option, - /// Print the would-be changes as a diff; write nothing - #[arg(long)] - dry_run: bool, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, - /// Inline a definition into its sole typed usage and delete it - #[command(after_help = "Imports the deletion leaves unused are reported as\n\ - `note:` lines, never removed.\n\n\ - EXAMPLES:\n\ - \x20 sysmlv2 refactor inline model.sysml Rig::Engine\n\ - \x20 sysmlv2 refactor inline Rig::Engine --dry-run (SYSMLV2_MODEL_DIR set)")] - Inline { - /// Input file (.sysml or .kerml); optional when SYSMLV2_MODEL_DIR - /// is set (a leading qualified name is then a name, not a file) - input: Option, - /// The ::-qualified definition name; arguments ending in - /// `.sysml`/`.kerml` are further files joining the model - args: Vec, - /// Print the would-be changes as a diff; write nothing - #[arg(long)] - dry_run: bool, - /// Standard-library directory for reference resolution - #[arg(long, env = "SYSMLV2_LIB_DIR")] - lib: Option, - }, -} - -/// Render one query-result value: elements as `qualified::name (Metaclass)` -/// (anonymous elements keep just the metaclass), everything else through -/// the evaluator's own display. -fn render_query_value( - resolved: &mut sysmlv2_parser::json::ResolvedModel, - v: &sysmlv2_parser::eval::Value, -) -> String { - if let sysmlv2_parser::eval::Value::Element(e) | sysmlv2_parser::eval::Value::Unbound(e) = v { - let ty = resolved.element_type(*e); - return match resolved.element_qualified_name(*e) { - Some(qn) => format!("{qn} ({ty})"), - None => format!(" ({ty})"), - }; - } - v.to_string() -} - -/// `--indent` values: `tabs`, or a space count 1–16. -fn parse_indent_arg(s: &str) -> Result { - if s == "tabs" { - return Ok(Indent::Tabs); - } - s.parse::() - .ok() - .filter(|n| (1..=16).contains(n)) - .map(Indent::Spaces) - .ok_or_else(|| "expected `tabs` or a space count 1-16".to_string()) -} - -fn dialect_of(path: &Path) -> Dialect { - if path.extension().and_then(|e| e.to_str()) == Some("kerml") { - Dialect::Kerml - } else { - Dialect::Sysml - } -} - -fn parse_file(path: &Path, src: &str) -> Parse { - match dialect_of(path) { - Dialect::Kerml => parse_kerml_source(src), - Dialect::Sysml => parse_source(src), - } -} - -fn report(path: &Path, src: &str, diags: &[Diagnostic]) { - let index = LineIndex::new(src); - for d in diags { - let severity = match d.severity { - sysmlv2_parser::diag::Severity::Error => "error", - sysmlv2_parser::diag::Severity::Warning => "warning", - }; - let pos = index.line_col(d.span.start); - let line = src.lines().nth(pos.line as usize - 1).unwrap_or(""); - eprintln!( - "{severity}: {}\n --> {}:{}:{}\n |\n | {}\n", - d.message, - path.display(), - pos.line, - pos.col, - line.trim_end() - ); - } -} - -fn read(path: &Path) -> Result { - if path == Path::new("-") { - let mut src = String::new(); - return std::io::Read::read_to_string(&mut std::io::stdin(), &mut src) - .map(|_| src) - .map_err(|e| { - eprintln!("error: cannot read stdin: {e}"); - ExitCode::FAILURE - }); - } - std::fs::read_to_string(path).map_err(|e| { - eprintln!("error: cannot read {}: {e}", path.display()); - ExitCode::FAILURE - }) -} - -/// Load a delta base: a compact element array from `.json` or `.s2c`. -fn load_base_value(path: &Path) -> Result { - if path.extension().and_then(|e| e.to_str()) == Some("s2c") { - let bytes = std::fs::read(path).map_err(|e| { - eprintln!("error: cannot read {}: {e}", path.display()); - ExitCode::FAILURE - })?; - sysmlv2_cbor::from_cbor(&bytes).map_err(|e| { - eprintln!("error: invalid base payload {}: {e}", path.display()); - ExitCode::FAILURE - }) - } else { - let text = read(path)?; - serde_json::from_str(&text).map_err(|e| { - eprintln!("error: invalid base JSON {}: {e}", path.display()); - ExitCode::FAILURE - }) - } -} - -/// The codec tables as one self-contained versioned JSON document: -/// everything a consumer needs to label s2c payload structure without -/// this toolkit — container magic, header version axes and flags, the -/// field-kind legend, both ordinal spaces (metaclass wire code = -/// array position, field ordinal = table position, both also spelled -/// explicitly), enum vocabularies, and each field's presence default -/// where the kind has one (bool, enum). Semantics live in `CBOR.md`. -fn codec_tables_doc() -> serde_json::Value { - use sysmlv2_cbor::tables; - let space = |set: &[(&str, &[tables::CborField])]| -> Vec { - set.iter() - .enumerate() - .map(|(code, (name, fields))| { - let fields: Vec = fields - .iter() - .enumerate() - .map(|(ordinal, (prop, kind, etbl, dflt))| { - let mut f = serde_json::Map::new(); - f.insert("prop".into(), serde_json::json!(prop)); - f.insert("ordinal".into(), serde_json::json!(ordinal)); - f.insert("kind".into(), serde_json::json!(kind)); - if *etbl != 255 { - f.insert("enum".into(), serde_json::json!(etbl)); - } - match *kind { - tables::K_BOOL => { - f.insert("default".into(), serde_json::json!(*dflt == 1)); - } - tables::K_ENUM => { - let value = if *dflt == 255 { - serde_json::Value::Null - } else { - serde_json::json!( - tables::ENUM_TABLES[*etbl as usize][*dflt as usize] - ) - }; - f.insert("default".into(), value); - } - _ => {} - } - serde_json::Value::Object(f) - }) - .collect(); - serde_json::json!({ "name": name, "code": code, "fields": fields }) - }) - .collect() - }; - let enums: Vec = tables::ENUM_NAMES - .iter() - .zip(tables::ENUM_TABLES) - .map(|(name, values)| serde_json::json!({ "name": name, "values": values })) - .collect(); - serde_json::json!({ - "magic": sysmlv2_cbor::MAGIC - .iter() - .map(|b| format!("{b:02x}")) - .collect::(), - "versions": { - "layout": sysmlv2_cbor::LAYOUT_VERSION, - "tables": tables::CBOR_TABLES_VERSION, - "scheme": sysmlv2_cbor::ID_SCHEME_VERSION, - }, - "flags": { - "elideIds": sysmlv2_cbor::FLAG_ELIDE_IDS, - "fullForm": sysmlv2_cbor::FLAG_FULL_FORM, - "delta": sysmlv2_cbor::FLAG_DELTA, - "deltaPortable": sysmlv2_cbor::FLAG_DELTA_PORTABLE, - "unitPaths": sysmlv2_cbor::FLAG_UNIT_PATHS, - "impliedOwners": sysmlv2_cbor::FLAG_IMPLIED_OWNERS, - }, - "kinds": { - "bool": tables::K_BOOL, - "str": tables::K_STR, - "strList": tables::K_STR_LIST, - "ref": tables::K_REF, - "refList": tables::K_REF_LIST, - "enum": tables::K_ENUM, - "literal": tables::K_LITERAL, - "elementId": tables::K_ELEMENT_ID, - }, - "enums": enums, - "metaclasses": space(tables::METACLASS_FIELDS), - "fullMetaclasses": space(tables::FULL_METACLASS_FIELDS), - }) -} - -/// A snapshot payload exactly as the file carries it: `.s2c` decodes -/// (id-elided snapshots re-derive their ids through `names` — a -/// digest-gated recovery, still payload identity), anything else -/// parses as a compact interchange element array. Never lifts — the -/// producer's ids are authoritative. -fn load_snapshot_value( - path: &Path, - names: &HashMap, -) -> Result { - let value = if path.extension().and_then(|e| e.to_str()) == Some("s2c") { - let bytes = std::fs::read(path).map_err(|e| { - eprintln!("error: cannot read {}: {e}", path.display()); - ExitCode::FAILURE - })?; - decode_snapshot(&bytes, names).map_err(|e| { - eprintln!("error: invalid snapshot payload {}: {e}", path.display()); - ExitCode::FAILURE - })? - } else { - let text = read(path)?; - serde_json::from_str(&text).map_err(|e| { - eprintln!("error: invalid snapshot JSON {}: {e}", path.display()); - ExitCode::FAILURE - })? - }; - if !value.is_array() { - eprintln!( - "error: {}: not a snapshot (compact element array)", - path.display() - ); - return Err(ExitCode::FAILURE); - } - Ok(value) -} - -/// Decode snapshot CBOR to its compact element array; id-elided -/// payloads re-derive their ids with library targets named through -/// `names`. -fn decode_snapshot( - bytes: &[u8], - names: &HashMap, -) -> Result { - match sysmlv2_cbor::from_cbor(bytes) { - Err(e) if e.to_string().contains("elided") => { - sysmlv2_cbor::from_cbor_with(bytes, &|s| names.get(s).cloned()) - } - other => other, - } -} - -/// State digest of a snapshot file (compact `.json` or `.s2c`) — -/// `None` when the file is not a snapshot this build decodes (a -/// delta, foreign JSON, another format entirely). -fn snapshot_file_digest(path: &Path, names: &HashMap) -> Option { - let value = if path.extension().and_then(|e| e.to_str()) == Some("s2c") { - decode_snapshot(&std::fs::read(path).ok()?, names).ok()? - } else { - serde_json::from_str(&std::fs::read_to_string(path).ok()?).ok()? - }; - if !value.is_array() { - return None; - } - Some(sysmlv2_cbor::state_digest(&value).ok()?.to_string()) -} - -/// Payload-looking files (`.s2c` / `.json`) under `dir`, recursively, -/// in sorted order. -fn payload_files_under(dir: &Path) -> Vec { - let mut out = Vec::new(); - let mut stack = vec![dir.to_path_buf()]; - while let Some(d) = stack.pop() { - let Ok(entries) = std::fs::read_dir(&d) else { - continue; - }; - for entry in entries.flatten() { - let p = entry.path(); - if p.is_dir() { - stack.push(p); - } else if matches!(p.extension().and_then(|e| e.to_str()), Some("s2c" | "json")) { - out.push(p); - } - } - } - out.sort(); - out -} - -/// `elementId → last qualified-name segment` for the standard -/// library at `lib` (empty without one) — the resolver id-derivation -/// surfaces (elision, elided deltas) name external targets with. -fn load_library_id_names( - lib: Option<&Path>, -) -> Result, ExitCode> { - let Some(dir) = lib else { - return Ok(Default::default()); - }; - let mut model = Model::new(); - match load_library(&mut model, dir) { - Ok(cache) => { - let names = library_name_map(&model) - .into_iter() - .filter_map(|(id, segs)| segs.last().cloned().map(|n| (id.to_string(), n))) - .collect(); - save_library_cache(&model, cache); - Ok(names) - } - Err(e) => { - eprintln!("error: cannot load library {}: {e}", dir.display()); - Err(ExitCode::FAILURE) - } - } -} - -/// Re-key a unit-structure table (compact element indices → paths) -/// onto another emission of the same model, matching unit roots by -/// element id. Identity when `target` is the compact array itself. -fn remap_units( - compact: &serde_json::Value, - units: &[(usize, String)], - target: &serde_json::Value, -) -> Vec<(usize, String)> { - let id_of = |arr: &serde_json::Value, i: usize| -> Option { - arr.get(i)?.get("@id")?.as_str().map(str::to_owned) - }; - let by_id: std::collections::HashMap = target - .as_array() - .map(|arr| { - arr.iter() - .enumerate() - .filter_map(|(i, e)| { - e.get("@id") - .and_then(|v| v.as_str()) - .map(|s| (s.to_owned(), i)) - }) - .collect() - }) - .unwrap_or_default(); - let mut out: Vec<(usize, String)> = units - .iter() - .filter_map(|(i, path)| { - by_id - .get(&id_of(compact, *i)?) - .map(|&ti| (ti, path.clone())) - }) - .collect(); - out.sort_by_key(|&(i, _)| i); - out -} - -/// Write binary output (compact-form CBOR) to a file or raw stdout. -fn write_bytes(output: Option<&Path>, bytes: &[u8]) -> ExitCode { - use std::io::Write; - match output { - Some(out) => { - if let Err(e) = std::fs::write(out, bytes) { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => { - if let Err(e) = std::io::stdout().write_all(bytes) { - eprintln!("error: cannot write stdout: {e}"); - return ExitCode::FAILURE; - } - } - } - ExitCode::SUCCESS -} - -/// Read command inputs, expanding `.kpar` project archives (KerML 10.3) -/// into their contained textual units. Checksum mismatches against the -/// archive's `.meta.json` warn but do not fail. -fn read_inputs(paths: &[PathBuf]) -> Result, ExitCode> { - let mut out = Vec::new(); - for path in paths { - if path.extension().and_then(|e| e.to_str()) == Some("kpar") { - let bytes = std::fs::read(path).map_err(|e| { - eprintln!("error: cannot read {}: {e}", path.display()); - ExitCode::FAILURE - })?; - let archive = kpar::read(&bytes).map_err(|e| { - eprintln!("error: {}: {e}", path.display()); - ExitCode::FAILURE - })?; - for name in &archive.checksum_mismatches { - eprintln!( - "warning: {}: `{name}` does not match its .meta.json checksum", - path.display() - ); - } - for unit in archive.units { - out.push((path.join(&unit.file_name), unit.source)); - } - } else { - out.push((path.clone(), read(path)?)); - } - } - Ok(out) -} - -/// The ambient model context: when a verb's file -/// inputs are omitted and this variable names a directory, the -/// directory's `.sysml`/`.kerml` files form the model. Explicit inputs -/// always win — the variable only fills an absence. -const MODEL_DIR_VAR: &str = "SYSMLV2_MODEL_DIR"; - -/// Collect the model files under `dir`, depth-first with siblings in -/// name order, so unit order (and everything downstream of it) is -/// deterministic. Hidden entries are skipped; directory symlinks are -/// not followed (files reached through a symlinked name still count). -fn discover_model_files(dir: &Path) -> std::io::Result> { - fn walk(dir: &Path, out: &mut Vec) -> std::io::Result<()> { - let mut entries: Vec<_> = std::fs::read_dir(dir)?.collect::>()?; - entries.sort_by_key(|e| e.file_name()); - for entry in entries { - if entry.file_name().to_string_lossy().starts_with('.') { - continue; - } - let path = entry.path(); - if entry.file_type()?.is_dir() { - walk(&path, out)?; - } else if matches!( - path.extension().and_then(|e| e.to_str()), - Some("sysml" | "kerml") - ) { - out.push(path); - } - } - Ok(()) - } - let mut out = Vec::new(); - walk(dir, &mut out)?; - Ok(out) -} - -/// Resolve a verb's input files: explicit paths pass through untouched; -/// an empty list falls back to the ambient model directory (with a -/// provenance note on stderr, suppressed by --quiet, so output never -/// silently depends on ambient state); with neither, the error names -/// both remedies. -fn resolve_inputs(explicit: Vec, quiet: bool) -> Result, ExitCode> { - if !explicit.is_empty() { - return Ok(explicit); - } - let Some(dir) = std::env::var_os(MODEL_DIR_VAR).filter(|v| !v.is_empty()) else { - eprintln!( - "error: no input files — provide input files, or set \ - {MODEL_DIR_VAR} to a model directory" - ); - return Err(ExitCode::FAILURE); - }; - let dir = PathBuf::from(dir); - let files = discover_model_files(&dir).map_err(|e| { - eprintln!( - "error: cannot read {MODEL_DIR_VAR} directory {}: {e}", - dir.display() - ); - ExitCode::FAILURE - })?; - if files.is_empty() { - eprintln!( - "error: no .sysml/.kerml files under {} ({MODEL_DIR_VAR})", - dir.display() - ); - return Err(ExitCode::FAILURE); - } - if !quiet { - eprintln!( - "sysmlv2: model = {} file{} from {} ({MODEL_DIR_VAR})", - files.len(), - if files.len() == 1 { "" } else { "s" }, - dir.display() - ); - } - Ok(files) -} - -/// Shared front half of the inspection verbs (describe/members): the -/// eval/query positional convention — arguments ending in a model -/// extension are files, the leading positional joins that -/// classification (an existing *file* path counts as a file — a -/// directory or case-folded match does not), exactly one -/// non-file argument remains as the qualified name — then ambient -/// fallback, library load, parse gate, and model resolution. -fn resolve_model_and_name( - input: Option, - args: Vec, - lib: Option<&Path>, - quiet: bool, -) -> Result<(sysmlv2_parser::json::ResolvedModel, String), ExitCode> { - let is_file = |s: &str| s.ends_with(".sysml") || s.ends_with(".kerml") || s == "-"; - let (extra_files, mut names): (Vec, Vec) = - args.into_iter().partition(|a| is_file(a)); - let mut files: Vec = Vec::new(); - if let Some(input) = input { - let s = input.display().to_string(); - if is_file(&s) || input.is_file() { - files.push(input); - } else { - names.insert(0, s); - } - } - files.extend(extra_files.iter().map(PathBuf::from)); - let [qname] = names.as_slice() else { - eprintln!( - "error: expected exactly one qualified name, got {}", - names.len() - ); - return Err(ExitCode::FAILURE); - }; - let qname = qname.clone(); - let files = resolve_inputs(files, quiet)?; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = lib { - lib_cache_path = load_library(&mut model, lib).map_err(|e| { - eprintln!("error: cannot load library {}: {e}", lib.display()); - ExitCode::FAILURE - })?; - } - for path in &files { - let src = read(path)?; - let unit = model.add_source(path.display().to_string(), &src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, &src, &diags); - return Err(ExitCode::FAILURE); - } - } - let resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - Ok((resolved, qname)) -} - -/// The refactor verbs' front half: the describe/members positional -/// convention (files + exactly one qualified name), the fmt write -/// discipline (ambient inputs drive `--dry-run` only; stdin never), -/// then a transform `Session` over the files with the library loaded. -fn refactor_session( - input: Option, - args: Vec, - lib: Option<&Path>, - dry_run: bool, - quiet: bool, -) -> Result<(sysmlv2_transform::Session, String), ExitCode> { - let is_file = |s: &str| s.ends_with(".sysml") || s.ends_with(".kerml") || s == "-"; - let (extra_files, mut names): (Vec, Vec) = - args.into_iter().partition(|a| is_file(a)); - let mut files: Vec = Vec::new(); - if let Some(input) = input { - let s = input.display().to_string(); - if is_file(&s) || input.is_file() { - files.push(input); - } else { - names.insert(0, s); - } - } - files.extend(extra_files.iter().map(PathBuf::from)); - let [qname] = names.as_slice() else { - eprintln!( - "error: expected exactly one qualified name, got {}", - names.len() - ); - return Err(ExitCode::FAILURE); - }; - let qname = qname.clone(); - if files.iter().any(|f| f == Path::new("-")) { - eprintln!("error: stdin (`-`) cannot be rewritten in place; pass file paths"); - return Err(ExitCode::FAILURE); - } - if files.is_empty() && !dry_run { - eprintln!( - "error: no input files — refactor rewrites files in place, so ambient \ - {MODEL_DIR_VAR} inputs apply to --dry-run only; pass explicit paths" - ); - return Err(ExitCode::FAILURE); - } - let files = resolve_inputs(files, quiet)?; - let mut sources = Vec::new(); - for path in &files { - let src = read(path)?; - sources.push((path.display().to_string(), src)); - } - let mut session = match sysmlv2_transform::Session::from_sources(sources.clone()) { - Ok(s) => s, - Err(sysmlv2_transform::SessionError::Parse { unit, diagnostics }) => { - match sources.iter().find(|(n, _)| *n == unit) { - Some((_, src)) => report(Path::new(&unit), src, &diagnostics), - None => eprintln!("error: {unit} does not parse"), - } - return Err(ExitCode::FAILURE); - } - Err(e) => { - eprintln!("error: {e}"); - return Err(ExitCode::FAILURE); - } - }; - if let Some(lib) = lib { - if let Err(e) = session.load_library(lib) { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return Err(ExitCode::FAILURE); - } - } - Ok((session, qname)) -} - -/// Execute one refactor direction: resolve the name, run the verified -/// edit (dry runs go through the same pipeline against copies), print -/// findings as `note:` lines, then either print the would-be diff or -/// write every changed unit back in place. -fn run_refactor(op: RefactorOp, quiet: bool) -> ExitCode { - let (input, args, name, dry_run, lib, is_extract) = match op { - RefactorOp::Extract { - input, - args, - name, - dry_run, - lib, - } => (input, args, name, dry_run, lib, true), - RefactorOp::Inline { - input, - args, - dry_run, - lib, - } => (input, args, None, dry_run, lib, false), - }; - let (mut session, qname) = match refactor_session(input, args, lib.as_deref(), dry_run, quiet) { - Ok(v) => v, - Err(code) => return code, - }; - let Some(target) = session.resolved().resolve_qualified(&qname) else { - eprintln!("error: cannot resolve `{qname}`"); - return ExitCode::FAILURE; - }; - // Summary facts read before the edit — a commit advances the session. - let summary = if is_extract { - let def_name = match &name { - Some(n) => n.clone(), - None => session - .resolved() - .element_name(target) - .map(sysmlv2_transform::synthesized_definition_name) - .unwrap_or_default(), - }; - format!( - "extracted '{}' from `{qname}`", - sysmlv2_transform::spell_name(&def_name) - ) - } else { - format!("inlined `{qname}`") - }; - let before: Vec<(String, String)> = session - .units() - .map(|(_, n, s)| (n.to_string(), s.to_string())) - .collect(); - let mut edit = session.edit(); - if is_extract { - edit.extract_definition(target, name.as_deref()); - } else { - edit.inline_definition(target); - } - let result = if dry_run { edit.check() } else { edit.commit() }; - let report = match result { - Ok(r) => r, - Err(e) => { - eprintln!("error: {e}"); - return ExitCode::FAILURE; - } - }; - if dry_run { - for f in &report.findings { - eprintln!("note: {f}"); - } - for (unit_name, old) in &before { - let mut spl: Vec<_> = report - .splices - .iter() - .filter(|s| s.unit == *unit_name) - .collect(); - if spl.is_empty() { - continue; - } - spl.sort_by_key(|s| s.start); - let mut new = String::with_capacity(old.len()); - let mut cursor = 0usize; - for s in &spl { - new.push_str(&old[cursor..s.start as usize]); - new.push_str(&s.text); - cursor = s.end as usize; - } - new.push_str(&old[cursor..]); - print_unit_diff(unit_name, old, &new); - } - return ExitCode::SUCCESS; - } - let after: Vec<(String, String)> = session - .units() - .map(|(_, n, s)| (n.to_string(), s.to_string())) - .collect(); - if before.len() != after.len() - || before - .iter() - .zip(&after) - .any(|((before_name, _), (after_name, _))| before_name != after_name) - { - eprintln!("error: internal refactor failure: session unit order changed"); - return ExitCode::FAILURE; - } - let changes: Vec = before - .iter() - .zip(&after) - .filter(|((_, old), (_, new))| old != new) - .map(|((unit_name, old), (_, new))| RefactorFileChange { - path: PathBuf::from(unit_name), - old: old.clone(), - new: new.clone(), - }) - .collect(); - let cleanup_warnings = match persist_refactor_changes(&changes) { - Ok(warnings) => warnings, - Err(e) => { - eprintln!("error: refactor was not written: {e}"); - return ExitCode::FAILURE; - } - }; - for f in &report.findings { - eprintln!("note: {f}"); - } - for warning in cleanup_warnings { - eprintln!("warning: {warning}"); - } - if !quiet { - for change in &changes { - eprintln!("{summary} — rewrote {}", change.path.display()); - } - } - ExitCode::SUCCESS -} - -/// One changed user unit waiting to be persisted after the transform -/// engine has committed and verified the whole model in memory. -#[derive(Debug)] -struct RefactorFileChange { - path: PathBuf, - old: String, - new: String, -} - -#[derive(Debug)] -struct StagedRefactorFile { - display_path: PathBuf, - target: PathBuf, - new_path: PathBuf, - backup_path: PathBuf, -} - -#[derive(Debug)] -struct RefactorFileMetadata { - permissions: Permissions, - #[cfg(all(unix, not(target_os = "wasi")))] - uid: u32, - #[cfg(all(unix, not(target_os = "wasi")))] - gid: u32, - #[cfg(all(unix, not(target_os = "wasi")))] - xattrs: Vec<(std::ffi::OsString, Vec)>, -} - -/// Persist a verified multi-file refactor as one recoverable operation: -/// preflight every target, stage both new text and rollback copies beside -/// their files, recheck for concurrent changes, then replace. A failed -/// replacement restores unchanged earlier targets and retains a recovery -/// copy rather than knowingly overwriting a later external edit. -fn persist_refactor_changes(changes: &[RefactorFileChange]) -> Result, String> { - persist_refactor_changes_with(changes, |from, to| std::fs::rename(from, to)) -} - -fn persist_refactor_changes_with( - changes: &[RefactorFileChange], - mut replace: impl FnMut(&Path, &Path) -> std::io::Result<()>, -) -> Result, String> { - let mut prepared = Vec::with_capacity(changes.len()); - let mut write_guards = Vec::with_capacity(changes.len()); - let mut targets = HashSet::with_capacity(changes.len()); - for change in changes { - let target = refactor_target_path(&change.path).map_err(|e| { - format!( - "cannot resolve {} before writing: {e}", - change.path.display() - ) - })?; - if !targets.insert(target.clone()) { - return Err(format!( - "{} names the same file more than once", - change.path.display() - )); - } - let current = std::fs::read(&target).map_err(|e| { - format!( - "cannot reread {} before writing: {e}", - change.path.display() - ) - })?; - if current != change.old.as_bytes() { - return Err(format!( - "{} changed on disk while the refactor was running", - change.path.display() - )); - } - let guard = OpenOptions::new() - .write(true) - .open(&target) - .map_err(|e| format!("cannot open {} for writing: {e}", change.path.display()))?; - let metadata = refactor_file_metadata(&guard) - .map_err(|e| format!("cannot inspect {}: {e}", change.path.display()))?; - prepared.push((target, metadata)); - write_guards.push(guard); - } - - let mut staged = Vec::with_capacity(changes.len()); - for (change, (target, metadata)) in changes.iter().zip(&prepared) { - let new_path = match write_refactor_sidecar(target, "new", &change.new, metadata) { - Ok(path) => path, - Err(e) => { - cleanup_refactor_sidecars(&staged, &HashSet::new()); - return Err(format!( - "cannot stage {} before writing: {e}", - change.path.display() - )); - } - }; - let backup_path = match write_refactor_sidecar(target, "old", &change.old, metadata) { - Ok(path) => path, - Err(e) => { - let _ = std::fs::remove_file(&new_path); - cleanup_refactor_sidecars(&staged, &HashSet::new()); - return Err(format!( - "cannot stage rollback copy for {}: {e}", - change.path.display() - )); - } - }; - staged.push(StagedRefactorFile { - display_path: change.path.clone(), - target: target.clone(), - new_path, - backup_path, - }); - } - drop(write_guards); - - // Staging may take time: refuse to overwrite an editor or process - // that changed a source after the first preflight read. - for (change, entry) in changes.iter().zip(&staged) { - match std::fs::read(&entry.target) { - Ok(current) if current == change.old.as_bytes() => {} - Ok(_) => { - cleanup_refactor_sidecars(&staged, &HashSet::new()); - return Err(format!( - "{} changed on disk while the refactor was being staged", - entry.display_path.display() - )); - } - Err(e) => { - cleanup_refactor_sidecars(&staged, &HashSet::new()); - return Err(format!( - "cannot recheck {} before writing: {e}", - entry.display_path.display() - )); - } - } - } - - for (applied, (change, entry)) in changes.iter().zip(&staged).enumerate() { - // Check each target again immediately before its replacement. This - // catches an editor save that races the earlier all-file recheck; - // previously replaced files still roll back, while the external - // edit remains untouched. - let write_error = match std::fs::read(&entry.target) { - Ok(current) if current != change.old.as_bytes() => Some(format!( - "{} changed on disk before it could be replaced", - entry.display_path.display() - )), - Err(e) => Some(format!( - "cannot recheck {} before replacement: {e}", - entry.display_path.display() - )), - Ok(_) => replace(&entry.new_path, &entry.target) - .err() - .map(|e| format!("cannot replace {}: {e}", entry.display_path.display())), - }; - if let Some(write_error) = write_error { - let mut retained_backups = HashSet::new(); - let mut rollback_errors = Vec::new(); - for previous_index in (0..applied).rev() { - let previous = &staged[previous_index]; - let rollback_error = match std::fs::read(&previous.target) { - Ok(current) if current != changes[previous_index].new.as_bytes() => Some( - "changed after the refactor replaced it; external edit was preserved" - .to_string(), - ), - Err(e) => Some(format!("cannot recheck before rollback: {e}")), - Ok(_) => replace(&previous.backup_path, &previous.target) - .err() - .map(|e| e.to_string()), - }; - if let Some(e) = rollback_error { - retained_backups.insert(previous.backup_path.clone()); - rollback_errors.push(format!( - "{} ({e}; recovery copy: {})", - previous.display_path.display(), - previous.backup_path.display() - )); - } - } - cleanup_refactor_sidecars(&staged, &retained_backups); - let mut message = write_error; - if rollback_errors.is_empty() { - message.push_str(&format!("; rolled back {applied} earlier file(s)")); - } else { - message.push_str("; rollback incomplete for "); - message.push_str(&rollback_errors.join(", ")); - } - return Err(message); - } - } - - let mut warnings = Vec::new(); - for entry in &staged { - if let Err(e) = std::fs::remove_file(&entry.backup_path) { - warnings.push(format!( - "could not remove rollback copy {}: {e}", - entry.backup_path.display() - )); - } - } - Ok(warnings) -} - -#[cfg(not(target_os = "wasi"))] -fn refactor_target_path(path: &Path) -> std::io::Result { - // Follow symlinks before replacing the file so an in-place refactor - // retains the link instead of replacing the directory entry itself. - std::fs::canonicalize(path) -} - -#[cfg(target_os = "wasi")] -fn refactor_target_path(path: &Path) -> std::io::Result { - // WASI preview1 preopen paths are already capability-resolved and - // canonicalize is unsupported by Node's WASI filesystem adapter. - Ok(path.to_path_buf()) -} - -fn write_refactor_sidecar( - target: &Path, - kind: &str, - text: &str, - metadata: &RefactorFileMetadata, -) -> std::io::Result { - let parent = target.parent().unwrap_or_else(|| Path::new(".")); - let file_name = target.file_name().ok_or_else(|| { - std::io::Error::new(std::io::ErrorKind::InvalidInput, "target has no file name") - })?; - for _ in 0..16 { - let mut sidecar_name = std::ffi::OsString::from("."); - sidecar_name.push(file_name); - sidecar_name.push(format!(".sysmlv2-{kind}-{}", uuid::Uuid::new_v4())); - let path = parent.join(sidecar_name); - let mut options = OpenOptions::new(); - options.write(true).create_new(true); - #[cfg(unix)] - { - use std::os::unix::fs::OpenOptionsExt; - options.mode(0o600); - } - match options.open(&path) { - Ok(mut file) => { - let result = (|| { - file.write_all(text.as_bytes())?; - set_refactor_sidecar_metadata(&file, metadata)?; - file.sync_all() - })(); - if let Err(e) = result { - drop(file); - let _ = std::fs::remove_file(&path); - return Err(e); - } - return Ok(path); - } - Err(e) if e.kind() == std::io::ErrorKind::AlreadyExists => continue, - Err(e) => return Err(e), - } - } - Err(std::io::Error::new( - std::io::ErrorKind::AlreadyExists, - "could not allocate a unique sidecar name", - )) -} - -fn refactor_file_metadata(file: &std::fs::File) -> std::io::Result { - let metadata = file.metadata()?; - #[cfg(all(unix, not(target_os = "wasi")))] - { - use std::os::unix::fs::MetadataExt; - use xattr::FileExt; - - if metadata.nlink() != 1 { - return Err(std::io::Error::other(format!( - "has {} hard links; refusing to split linked paths during atomic replacement", - metadata.nlink() - ))); - } - let mut xattrs = Vec::new(); - match file.list_xattr() { - Ok(names) => { - for name in names { - if let Some(value) = file.get_xattr(&name)? { - xattrs.push((name, value)); - } - } - } - Err(e) if e.kind() == std::io::ErrorKind::Unsupported => {} - Err(e) => return Err(e), - } - Ok(RefactorFileMetadata { - permissions: metadata.permissions(), - uid: metadata.uid(), - gid: metadata.gid(), - xattrs, - }) - } - #[cfg(not(all(unix, not(target_os = "wasi"))))] - Ok(RefactorFileMetadata { - permissions: metadata.permissions(), - }) -} - -#[cfg(all(unix, not(target_os = "wasi")))] -fn set_refactor_sidecar_metadata( - file: &std::fs::File, - metadata: &RefactorFileMetadata, -) -> std::io::Result<()> { - use std::os::unix::fs::fchown; - use xattr::FileExt; - - fchown(file, Some(metadata.uid), Some(metadata.gid))?; - for (name, value) in &metadata.xattrs { - file.set_xattr(name, value)?; - } - file.set_permissions(metadata.permissions.clone()) -} - -#[cfg(all(not(unix), not(target_os = "wasi")))] -fn set_refactor_sidecar_metadata( - file: &std::fs::File, - metadata: &RefactorFileMetadata, -) -> std::io::Result<()> { - file.set_permissions(metadata.permissions.clone()) -} - -#[cfg(target_os = "wasi")] -fn set_refactor_sidecar_metadata( - _file: &std::fs::File, - _metadata: &RefactorFileMetadata, -) -> std::io::Result<()> { - // WASI preview1 has no chmod-equivalent. Files created through a - // preopen inherit the host adapter's normal creation permissions. - Ok(()) -} - -fn cleanup_refactor_sidecars(staged: &[StagedRefactorFile], retain: &HashSet) { - for entry in staged { - let _ = std::fs::remove_file(&entry.new_path); - if !retain.contains(&entry.backup_path) { - let _ = std::fs::remove_file(&entry.backup_path); - } - } -} - -/// One trimmed hunk per changed unit: common prefix/suffix lines are -/// elided, the middle prints as `-`/`+` lines (1-based line numbers, -/// unified-style header). Both refactor ops touch one contiguous region per -/// unit, so a single hunk is exact. -fn print_unit_diff(unit: &str, old: &str, new: &str) { - let o: Vec<&str> = old.split_inclusive('\n').collect(); - let n: Vec<&str> = new.split_inclusive('\n').collect(); - let mut p = 0; - while p < o.len() && p < n.len() && o[p] == n[p] { - p += 1; - } - let mut s = 0; - while s < o.len() - p && s < n.len() - p && o[o.len() - 1 - s] == n[n.len() - 1 - s] { - s += 1; - } - println!("--- {unit}"); - println!( - "@@ -{},{} +{},{} @@", - p + 1, - o.len() - p - s, - p + 1, - n.len() - p - s - ); - for l in &o[p..o.len() - s] { - print!("-{l}"); - if !l.ends_with('\n') { - println!(); - } - } - for l in &n[p..n.len() - s] { - print!("+{l}"); - if !l.ends_with('\n') { - println!(); - } - } -} - -/// Help echoes the active ambient context: with -/// SYSMLV2_MODEL_DIR set, the top level and every verb that honors -/// ambient inputs get a trailing `model context:` line appended to -/// their help footer, so `--help` confirms what a bare invocation -/// would run on. Without the variable, help is untouched. -fn ambient_help(mut cmd: clap::Command) -> clap::Command { - let Some(dir) = std::env::var_os(MODEL_DIR_VAR).filter(|v| !v.is_empty()) else { - return cmd; - }; - let dir = PathBuf::from(dir); - let count = match discover_model_files(&dir) { - Ok(files) => match files.len() { - 0 => "no model files".to_string(), - 1 => "1 model file".to_string(), - n => format!("{n} model files"), - }, - Err(e) => format!("unreadable: {e}"), - }; - let note = format!( - "model context: {} ({MODEL_DIR_VAR} — {count}); file inputs may be omitted", - dir.display() - ); - fn append(cmd: clap::Command, note: &str) -> clap::Command { - let text = match cmd.get_after_help() { - Some(existing) => format!("{existing}\n\n{note}"), - None => note.to_string(), - }; - cmd.after_help(text) - } - // Feature gates decide which verbs exist, so collect the present - // ones rather than naming a fixed list into mut_subcommand (which - // panics on absent names). - let verbs: Vec = cmd - .get_subcommands() - .map(|s| s.get_name().to_string()) - .filter(|n| { - matches!( - n.as_str(), - "convert" - | "fmt" - | "check" - | "verify" - | "eval" - | "query" - | "describe" - | "members" - | "parse" - | "viz" - | "refactor" - ) - }) - .collect(); - cmd = append(cmd, ¬e); - for name in verbs { - let note = if name == "fmt" { - format!("{note} (--check only)") - } else if name == "refactor" { - format!("{note} (--dry-run only)") - } else { - note.clone() - }; - cmd = cmd.mut_subcommand(name, |sub| append(sub, ¬e)); - } - cmd -} - -/// The tallying bucket a constraint's verdict falls in. -#[cfg(feature = "solve")] -enum VerdictCat { - Sat, - Vio, - Und, -} - -/// Render one constraint's combined verdict (evaluation, then propagation, -/// then Z3) into a display string and its tally bucket. Mirrors the -/// precedence in [`sysmlv2_solve::verify_constraints`]: a definitive -/// propagation conclusion pre-empts the solver, which only reports what -/// propagation left open. -#[cfg(feature = "solve")] -fn verdict_line( - verdict: &sysmlv2_parser::check::ConstraintVerdict, - propagate: Option<&sysmlv2_solve::PropagateOutcome>, - solve: Option<&sysmlv2_solve::SolveOutcome>, -) -> (String, VerdictCat) { - use sysmlv2_parser::check::ConstraintVerdict; - use sysmlv2_solve::{PropagateOutcome, SolveOutcome}; - match verdict { - ConstraintVerdict::Satisfied => ("satisfied".to_string(), VerdictCat::Sat), - ConstraintVerdict::Violated => ("VIOLATED".to_string(), VerdictCat::Vio), - ConstraintVerdict::Undecided(why) => match propagate { - Some(PropagateOutcome::Satisfied) => ( - "satisfied (propagation: holds for all values in the narrowed ranges)".to_string(), - VerdictCat::Sat, - ), - Some(PropagateOutcome::Violated) => ( - "VIOLATED (propagation: false for all values in the narrowed ranges)".to_string(), - VerdictCat::Vio, - ), - Some(PropagateOutcome::Unsatisfiable) => ( - "VIOLATED (propagation: domains contract to empty — unsatisfiable)".to_string(), - VerdictCat::Vio, - ), - _ => match solve { - Some(SolveOutcome::Valid) => ( - "satisfied (z3: holds for all values of unbound features)".to_string(), - VerdictCat::Sat, - ), - Some(SolveOutcome::Unsatisfiable) => ( - "VIOLATED (z3: unsatisfiable — no assignment can make this hold)".to_string(), - VerdictCat::Vio, - ), - Some(SolveOutcome::Satisfiable(w)) => { - let vals: Vec = w.iter().map(|(n, v)| format!("{n} = {v}")).collect(); - ( - format!( - "undecided ({why}) — z3: satisfiable, e.g. {}", - vals.join(", ") - ), - VerdictCat::Und, - ) - } - Some(SolveOutcome::Unknown(m)) => { - (format!("undecided ({why}; z3: {m})"), VerdictCat::Und) - } - None => match propagate { - Some(PropagateOutcome::Unsupported(m)) => ( - format!("undecided ({why}; propagation: {m})"), - VerdictCat::Und, - ), - _ => (format!("undecided ({why})"), VerdictCat::Und), - }, - }, - }, - } -} - -/// Append the evaluated feature values to a violated verdict line — -/// `VIOLATED (with reserveKg = 0.10)` — so the reader sees *why* -/// without re-deriving the bindings. Only bound references contribute; -/// non-violated lines pass through untouched. -#[cfg(feature = "solve")] -fn with_bindings( - line: String, - cat: &VerdictCat, - bindings: &[sysmlv2_parser::check::ConstraintBinding], -) -> String { - if !matches!(cat, VerdictCat::Vio) { - return line; - } - let vals: Vec = bindings - .iter() - .filter_map(|b| b.value.as_ref().map(|v| format!("{} = {v}", b.feature))) - .collect(); - if vals.is_empty() { - line - } else { - format!("{line} (with {})", vals.join(", ")) - } -} - -/// Run the requested verification stage over `model` and print per- -/// constraint verdicts (plus narrowed ranges under `--ranges`). Returns a -/// failure exit code iff any constraint is violated. -#[cfg(feature = "solve")] -fn verify_and_report( - model: &Model, - boundary: usize, - sources: &[(&PathBuf, String)], - ranges: bool, - solve: bool, - z3: Option, -) -> ExitCode { - use sysmlv2_solve::{PropagateConfig, SolverConfig}; - let indexes: Vec = sources.iter().map(|(_, src)| LineIndex::new(src)).collect(); - let (mut sat, mut vio, mut und) = (0usize, 0usize, 0usize); - - let mut print_one = |unit: usize, - start: u32, - name: &Option, - etype: &str, - context: Option<&str>, - line: String, - cat: VerdictCat| { - match cat { - VerdictCat::Sat => sat += 1, - VerdictCat::Vio => vio += 1, - VerdictCat::Und => und += 1, - } - let (path, _) = &sources[unit - boundary]; - let pos = indexes[unit - boundary].line_col(start); - let ctx = context - .map(|c| format!(", satisfies {c}")) - .unwrap_or_default(); - println!( - "{}:{}:{} {} ({}{}): {}", - path.display(), - pos.line, - pos.col, - name.as_deref().unwrap_or(""), - etype, - ctx, - line - ); - }; - - // Ranges to print once the verdicts are out (only under --ranges). - let mut narrowed: Vec = Vec::new(); - - if !ranges && !solve { - // Plain evaluation stage — no propagation, no solver. - for c in sysmlv2_parser::check::check_constraints(model) { - let (line, cat) = verdict_line(&c.verdict, None, None); - let line = with_bindings(line, &cat, &c.bindings); - print_one( - c.unit, - c.span.start, - &c.name, - c.element_type, - c.context.as_deref(), - line, - cat, - ); - } - } else { - let cfg = SolverConfig { - z3_path: z3, - ..Default::default() - }; - let report = match sysmlv2_solve::verify_constraints( - model, - solve.then_some(&cfg), - &PropagateConfig::default(), - ) { - Ok(r) => r, - Err(e) => { - eprintln!("error: {e}"); - return ExitCode::FAILURE; - } - }; - for c in &report.constraints { - let (line, cat) = verdict_line(&c.verdict, c.propagate.as_ref(), c.solve.as_ref()); - let line = with_bindings(line, &cat, &c.bindings); - print_one( - c.unit, - c.span.start, - &c.name, - c.element_type, - None, - line, - cat, - ); - } - // Satisfaction claims expand to subject-bound verdicts at the - // evaluation tier (propagation/solving see the unbound - // originals above). - let mut rm = sysmlv2_parser::json::ResolvedModel::build(model); - for c in sysmlv2_parser::check::satisfaction_checks(model, &mut rm) { - let (line, cat) = verdict_line(&c.verdict, None, None); - print_one( - c.unit, - c.span.start, - &c.name, - c.element_type, - c.context.as_deref(), - line, - cat, - ); - } - if ranges { - narrowed = report.ranges.into_iter().filter(|r| r.narrowed).collect(); - } - } - - println!("{sat} satisfied, {vio} violated, {und} undecided"); - if !narrowed.is_empty() { - println!("\nnarrowed ranges:"); - for r in &narrowed { - match &r.unit { - Some(u) => println!(" {} ∈ {} [{u}]", r.feature, r.range), - None => println!(" {} ∈ {}", r.feature, r.range), - } - } - } - if vio > 0 { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } -} - -fn main() -> ExitCode { - use clap::{CommandFactory, FromArgMatches}; - let cmd = ambient_help(Cli::command()); - let cli = Cli::from_arg_matches(&cmd.get_matches()).unwrap_or_else(|e| e.exit()); - let quiet = cli.quiet; - // Spelled power-product unit expansion is on by default; the flag or - // `SYSMLV2_UNIT_SPELLINGS=off` opts out. - if cli.no_unit_spellings - || std::env::var("SYSMLV2_UNIT_SPELLINGS").is_ok_and(|v| v == "off" || v == "0") - { - sysmlv2_parser::eval::set_unit_spelling_expansion(false); - } - match cli.command { - Command::Convert { - inputs, - to, - output, - lib, - flexo, - min_qual, - elide_ids, - delta_base, - delta_portable, - indent, - library, - } => { - if library { - if !inputs.is_empty() { - eprintln!( - "error: --library takes no inputs (the --lib directory is the input)" - ); - return ExitCode::FAILURE; - } - if !matches!(to, Target::CompactJson | Target::CompactCbor) { - eprintln!("error: --library targets compact-json or compact-cbor"); - return ExitCode::FAILURE; - } - if flexo || min_qual || elide_ids || delta_base.is_some() || delta_portable { - eprintln!("error: --library composes with no other conversion flags"); - return ExitCode::FAILURE; - } - let dir = lib.as_ref().expect("--library requires --lib"); - let mut model = Model::new(); - let lib_cache_path = match load_library(&mut model, dir) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", dir.display()); - return ExitCode::FAILURE; - } - }; - save_library_cache(&model, lib_cache_path); - let (json, units) = - sysmlv2_parser::json::library_to_compact_json_with_units(&model); - if matches!(to, Target::CompactCbor) { - return match sysmlv2_cbor::to_compact_cbor_with_units(&json, &units) { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode CBOR: {e}"); - ExitCode::FAILURE - } - }; - } - let text = serde_json::to_string_pretty(&json).unwrap(); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, text + "\n") { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => println!("{text}"), - } - return ExitCode::SUCCESS; - } - let inputs = match resolve_inputs(inputs, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - if flexo && matches!(to, Target::CompactCbor | Target::FullCbor) { - eprintln!( - "error: --flexo wraps JSON change records; CBOR carries \ - the bare element array" - ); - return ExitCode::FAILURE; - } - if elide_ids && !matches!(to, Target::CompactCbor) { - eprintln!("error: --elide-ids applies to --to compact-cbor"); - return ExitCode::FAILURE; - } - if delta_portable && delta_base.is_none() { - eprintln!("error: --delta-portable needs --delta-base"); - return ExitCode::FAILURE; - } - if elide_ids && delta_portable { - eprintln!( - "error: --elide-ids applies to strict deltas only \ - (portable identities are explicit ids by design)" - ); - return ExitCode::FAILURE; - } - // An .s2c input decodes to the compact element array up - // front and then flows through every JSON-input path. - let is_s2c_path = |p: &PathBuf| p.extension().and_then(|e| e.to_str()) == Some("s2c"); - let sources: Vec<(PathBuf, String)> = if inputs.len() == 1 && is_s2c_path(&inputs[0]) { - let bytes = match std::fs::read(&inputs[0]) { - Ok(b) => b, - Err(e) => { - eprintln!("error: cannot read {}: {e}", inputs[0].display()); - return ExitCode::FAILURE; - } - }; - // Id-elided payloads recompute their ids; the library - // (when given) names the effective-name targets. Delta - // payloads apply to --delta-base first. - let decoded = match sysmlv2_cbor::from_cbor(&bytes) { - Err(e) if e.to_string().contains("delta payload") => { - let Some(base_path) = &delta_base else { - eprintln!( - "error: input is a delta payload; pass \ - --delta-base to apply it" - ); - return ExitCode::FAILURE; - }; - let base = match load_base_value(base_path) { - Ok(v) => v, - Err(code) => return code, - }; - // Id-elided deltas re-derive their created ids - // through the library resolver (empty is fine - // for hermetic models; explicit-id deltas - // never consult it). - let names = match load_library_id_names(lib.as_deref()) { - Ok(n) => n, - Err(code) => return code, - }; - sysmlv2_cbor::apply_delta_cbor_with(&bytes, &base, &|s| { - names.get(s).cloned() - }) - } - Err(e) if e.to_string().contains("elided") => { - let names = match load_library_id_names(lib.as_deref()) { - Ok(n) => n, - Err(code) => return code, - }; - sysmlv2_cbor::from_cbor_with(&bytes, &|s| names.get(s).cloned()) - } - other => other, - }; - match decoded { - Ok(v) => vec![(inputs[0].clone(), serde_json::to_string(&v).unwrap())], - Err(e) => { - eprintln!("error: invalid CBOR payload: {e}"); - return ExitCode::FAILURE; - } - } - } else if inputs.iter().any(is_s2c_path) { - eprintln!("error: convert accepts one .s2c input on its own"); - return ExitCode::FAILURE; - } else { - match read_inputs(&inputs) { - Ok(s) => s, - Err(code) => return code, - } - }; - let looks_json = |p: &Path, s: &str| { - matches!(p.extension().and_then(|e| e.to_str()), Some("json" | "s2c")) - || s.trim_start().starts_with('[') - }; - let is_json_input = looks_json(&sources[0].0, &sources[0].1); - if sources.len() > 1 && sources.iter().any(|(p, s)| looks_json(p, s)) { - eprintln!("error: convert accepts several textual inputs or one JSON input"); - return ExitCode::FAILURE; - } - if min_qual && (!matches!(to, Target::Text) || !is_json_input) { - eprintln!("error: --min-qual applies to JSON \u{2192} text conversion"); - return ExitCode::FAILURE; - } - match to { - Target::Text => { - if !is_json_input { - eprintln!( - "error: the input is already textual notation; use \ - `sysmlv2 fmt` to reformat it" - ); - return ExitCode::FAILURE; - } - let src = &sources[0].1; - let mut value: serde_json::Value = match serde_json::from_str(src) { - Ok(v) => v, - Err(e) => { - eprintln!("error: invalid JSON: {e}"); - return ExitCode::FAILURE; - } - }; - if flexo { - value = flexo_unwrap(value); - } - // Minimal-qualification printing: lift through a - // transform session (same split/lift/naming path) and - // run the reparse-verified respelling pass over the - // whole document set, then write its units. - if min_qual { - let mut session = - match sysmlv2_transform::Session::from_interchange_json_with_library( - &value, - lib.as_deref(), - ) { - Ok(s) => s, - Err(e) => { - eprintln!("error: cannot lift JSON: {e}"); - return ExitCode::FAILURE; - } - }; - for w in session.warnings() { - eprintln!("warning: {w}"); - } - if let Err(e) = session.minimize_qualifications() { - eprintln!("error: minimal-qualification pass failed: {e}"); - return ExitCode::FAILURE; - } - let units: Vec<(String, String)> = session - .units() - .map(|(_, n, s)| (n.to_string(), s.to_string())) - .collect(); - if let Some(dir) = output.as_ref().filter(|o| o.is_dir()) { - for (name, text) in &units { - let file = dir.join(name); - if let Err(e) = std::fs::write(&file, text) { - eprintln!("error: cannot write {}: {e}", file.display()); - return ExitCode::FAILURE; - } - println!("{}", file.display()); - } - return ExitCode::SUCCESS; - } - let text: String = units - .into_iter() - .map(|(_, t)| t) - .collect::>() - .join(""); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, &text) { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => print!("{text}"), - } - return ExitCode::SUCCESS; - } - let names = match lib { - Some(dir) => { - let mut model = Model::new(); - let lib_cache_path = match load_library(&mut model, &dir) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", dir.display()); - return ExitCode::FAILURE; - } - }; - let names = library_name_map(&model); - save_library_cache(&model, lib_cache_path); - names - } - None => Default::default(), - }; - // A multi-document element list splits into one text - // file per root namespace when the output is a - // directory (the Flexo retrieval flow). A directory - // always receives files — one per document, or a - // single document-1.sysml when no split applies. - let split = sysmlv2_parser::lift::split_documents(&value); - if let Some(dir) = output.as_ref().filter(|o| o.is_dir()) { - let docs = split.clone().unwrap_or_else(|| vec![(None, value.clone())]); - // Cross-document references print as $::-rooted - // qualified names via a whole-list name map. - let mut names = names.clone(); - names.extend(sysmlv2_parser::lift::document_reference_name_map(&value)); - for (i, (name, doc)) in docs.iter().enumerate() { - let lifted = match from_compact_json_with_names(doc, &names) { - Ok(l) => l, - Err(e) => { - eprintln!("error: cannot lift document {i}: {e}"); - return ExitCode::FAILURE; - } - }; - for w in &lifted.errors { - eprintln!("warning: {w}"); - } - let file = dir.join(doc_file_name(name.as_deref(), i)); - if let Err(e) = std::fs::write( - &file, - print_source_opts( - &lifted.unit, - PrintOptions { - indent, - reflow_doc_bodies: true, - ..Default::default() - }, - ), - ) { - eprintln!("error: cannot write {}: {e}", file.display()); - return ExitCode::FAILURE; - } - println!("{}", file.display()); - } - return ExitCode::SUCCESS; - } - if split.is_some() { - eprintln!( - "note: input holds several documents — they are \ - concatenated; pass `-o ` to split \ - into one file per root namespace" - ); - } - let lifted = match from_compact_json_with_names(&value, &names) { - Ok(l) => l, - Err(e) => { - eprintln!("error: cannot lift JSON: {e}"); - return ExitCode::FAILURE; - } - }; - for w in &lifted.errors { - eprintln!("warning: {w}"); - } - let text = print_source_opts( - &lifted.unit, - PrintOptions { - indent, - reflow_doc_bodies: true, - ..Default::default() - }, - ); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, &text) { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => print!("{text}"), - } - ExitCode::SUCCESS - } - Target::FullJson | Target::FullCbor | Target::CompactJson | Target::CompactCbor - if !is_json_input => - { - let full = matches!(to, Target::FullJson | Target::FullCbor); - // --elide-ids: library element names for the - // effective-name chains (roots-only exception maps); - // filled when a library is loaded below. - let mut elide_names: std::collections::HashMap = - Default::default(); - // One no-lib file keeps the single-unit fast path; - // anything else builds a model (one root namespace per - // file, cross-file references resolved). Binary targets - // also carry the unit structure: each unit root's - // element index paired with its source path. - let (json, unit_paths) = if lib.is_some() || sources.len() > 1 { - let mut model = Model::new(); - let lib_cache_path = if let Some(lib) = &lib { - match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - } - } else { - None - }; - for (path, src) in &sources { - let name = path.to_string_lossy().into_owned(); - let unit = model.add_source(name, src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, src, &diags); - return ExitCode::FAILURE; - } - } - if full && lib.is_none() { - eprintln!( - "note: no --lib given — implied relationships are omitted \ - (isImpliedIncluded: false); derived properties are included" - ); - } - let (compact, units) = model_to_compact_json_with_units(&model); - let json = if full { - // --flexo commits must survive read-back even - // with unresolved references: emit recovery - // annotations alongside the dangling ids. - // Full interchange is lossless by default: - // unresolved textual references need recovery - // carriers independently of the Flexo envelope. - model_to_full_json_with(&model, true) - } else { - compact.clone() - }; - let unit_paths = remap_units(&compact, &units, &json); - if elide_ids && lib.is_some() { - elide_names = library_name_map(&model) - .into_iter() - .filter_map(|(id, segs)| { - segs.last().cloned().map(|n| (id.to_string(), n)) - }) - .collect(); - } - save_library_cache(&model, lib_cache_path); - (json, unit_paths) - } else { - let (input, src) = &sources[0]; - let parse = parse_file(input, src); - if !parse.diagnostics.is_empty() { - report(input, src, &parse.diagnostics); - return ExitCode::FAILURE; - } - // The builder emits each unit's root namespace - // first: the single unit's root is element 0 of - // the compact array. - let compact = to_compact_json(&parse.unit); - let units = vec![(0usize, input.to_string_lossy().into_owned())]; - if full { - eprintln!( - "note: no --lib given — implied relationships are omitted \ - (isImpliedIncluded: false); derived properties are included" - ); - let json = to_full_json_with(&parse.unit, true); - let unit_paths = remap_units(&compact, &units, &json); - (json, unit_paths) - } else { - (compact, units) - } - }; - let json = if flexo { - let names: Vec = sources - .iter() - .map(|(p, _)| { - p.file_name() - .map(|n| n.to_string_lossy().into_owned()) - .unwrap_or_else(|| "model.sysml".to_string()) - }) - .collect(); - flexo_payload(json, &names) - } else { - json - }; - if matches!(to, Target::CompactCbor | Target::FullCbor) { - let encoded = if matches!(to, Target::FullCbor) { - sysmlv2_cbor::to_full_cbor_with_units(&json, &unit_paths) - } else if let Some(base_path) = delta_base - .as_ref() - .filter(|_| matches!(to, Target::CompactCbor)) - { - let base = match load_base_value(base_path) { - Ok(v) => v, - Err(code) => return code, - }; - // This parse derived ids afresh; the base carries - // whatever its producer assigned. Rebase so - // unchanged elements coincide by identity. - let json = match sysmlv2_cbor::rebase_ids(&base, &json) { - Ok(v) => v, - Err(e) => { - eprintln!("error: cannot rebase onto the delta base: {e}"); - return ExitCode::FAILURE; - } - }; - // Unit paths ride strict deltas; - // rebase preserves element order, so the - // snapshot-side indices stay valid. - let units = if delta_portable { - Vec::new() - } else { - unit_paths.clone() - }; - if elide_ids { - sysmlv2_cbor::delta_compact_cbor_elided( - &base, - &json, - &sysmlv2_cbor::DeltaOptions { - units, - ..Default::default() - }, - &|s| elide_names.get(s).cloned(), - ) - } else { - sysmlv2_cbor::delta_compact_cbor( - &base, - &json, - &sysmlv2_cbor::DeltaOptions { - portable: delta_portable, - units, - ..Default::default() - }, - ) - } - } else if elide_ids { - sysmlv2_cbor::to_compact_cbor_elided_with_units( - &json, - &|s| elide_names.get(s).cloned(), - &unit_paths, - ) - } else { - sysmlv2_cbor::to_compact_cbor_with_units(&json, &unit_paths) - }; - return match encoded { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode CBOR: {e}"); - ExitCode::FAILURE - } - }; - } - let text = serde_json::to_string_pretty(&json).unwrap(); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, text + "\n") { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => println!("{text}"), - } - ExitCode::SUCCESS - } - Target::Kpar => { - if is_json_input { - eprintln!( - "error: a .kpar packs textual units; convert the JSON \ - to text first" - ); - return ExitCode::FAILURE; - } - let Some(out) = output else { - eprintln!("error: --to kpar needs -o "); - return ExitCode::FAILURE; - }; - let mut units: Vec<(String, String, String)> = Vec::new(); - for (path, src) in &sources { - let parse = parse_file(path, src); - if !parse.diagnostics.is_empty() { - report(path, src, &parse.diagnostics); - return ExitCode::FAILURE; - } - // The .meta.json index maps the unit's root - // namespace name to its file; an anonymous root - // falls back to the file stem. - let root = parse - .unit - .members - .iter() - .find_map(|m| match &m.kind { - sysmlv2_parser::ast::MemberKind::Package(pkg) => { - pkg.id.name.as_ref().map(|n| n.value.clone()) - } - _ => None, - }) - .unwrap_or_else(|| { - path.file_stem().map_or_else( - || "model".to_string(), - |st| st.to_string_lossy().into_owned(), - ) - }); - let file_name = path.file_name().map_or_else( - || "model.sysml".to_string(), - |f| f.to_string_lossy().into_owned(), - ); - units.push((file_name, src.clone(), root)); - } - let name = out.file_stem().map_or_else( - || "project".to_string(), - |st| st.to_string_lossy().into_owned(), - ); - let bytes = kpar::write(&name, "1.0.0", &units); - if let Err(e) = std::fs::write(&out, bytes) { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - ExitCode::SUCCESS - } - Target::FullJson | Target::FullCbor => { - // Compact JSON → full JSON re-derivation, **in place**: - // every element keeps its @id (derived properties and - // implied relationships are functions of the compact - // structure), so a stored payload upgrades without - // breaking external references to its elements. - let src = &sources[0].1; - let mut value: serde_json::Value = match serde_json::from_str(src) { - Ok(v) => v, - Err(e) => { - eprintln!("error: invalid JSON: {e}"); - return ExitCode::FAILURE; - } - }; - if flexo { - value = flexo_unwrap(value); - } - let by_name = if let Some(dir) = &lib { - let mut model = Model::new(); - let lib_cache_path = match load_library(&mut model, dir) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", dir.display()); - return ExitCode::FAILURE; - } - }; - save_library_cache(&model, lib_cache_path); - library_name_map(&model) - .into_iter() - .map(|(id, segments)| (segments.join("::"), id)) - .collect() - } else { - eprintln!( - "note: no --lib given — implied relationships are omitted \ - (isImpliedIncluded: false); derived properties are included" - ); - Default::default() - }; - let json = sysmlv2_parser::full::from_compact_value(value, &by_name, true); - if matches!(to, Target::FullCbor) { - return match sysmlv2_cbor::to_full_cbor(&json) { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode CBOR: {e}"); - ExitCode::FAILURE - } - }; - } - let json = if flexo { - flexo_payload(json, &[]) - } else { - json - }; - let text = serde_json::to_string_pretty(&json).unwrap(); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, text + "\n") { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => println!("{text}"), - } - ExitCode::SUCCESS - } - Target::CompactJson | Target::CompactCbor => { - // JSON → compact JSON/CBOR: normalize (drop implied - // relationships / derived properties) by lifting and - // re-emitting. - let src = &sources[0].1; - let value: serde_json::Value = match serde_json::from_str(src) { - Ok(v) => v, - Err(e) => { - eprintln!("error: invalid JSON: {e}"); - return ExitCode::FAILURE; - } - }; - let lifted = match from_compact_json_with_names(&value, &Default::default()) { - Ok(l) => l, - Err(e) => { - eprintln!("error: cannot lift JSON: {e}"); - return ExitCode::FAILURE; - } - }; - for w in &lifted.errors { - eprintln!("warning: {w}"); - } - let json = to_compact_json(&lifted.unit); - if matches!(to, Target::CompactCbor) { - // Hermetic normalize path: elision without a - // resolver is always safe — library-effective - // names simply ride the exception map. - let encoded = if let Some(base_path) = &delta_base { - let base = match load_base_value(base_path) { - Ok(v) => v, - Err(code) => return code, - }; - // The lift + re-emit derived ids afresh; rebase - // so unchanged elements coincide by identity. - let json = match sysmlv2_cbor::rebase_ids(&base, &json) { - Ok(v) => v, - Err(e) => { - eprintln!("error: cannot rebase onto the delta base: {e}"); - return ExitCode::FAILURE; - } - }; - if elide_ids { - sysmlv2_cbor::delta_compact_cbor_elided( - &base, - &json, - &Default::default(), - &|_| None, - ) - } else { - sysmlv2_cbor::delta_compact_cbor( - &base, - &json, - &sysmlv2_cbor::DeltaOptions { - portable: delta_portable, - ..Default::default() - }, - ) - } - } else if elide_ids { - sysmlv2_cbor::to_compact_cbor_elided(&json, &|_| None) - } else { - sysmlv2_cbor::to_compact_cbor(&json) - }; - return match encoded { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode CBOR: {e}"); - ExitCode::FAILURE - } - }; - } - let json = if flexo { - flexo_payload(json, &[]) - } else { - json - }; - let text = serde_json::to_string_pretty(&json).unwrap(); - match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, text + "\n") { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - } - None => println!("{text}"), - } - ExitCode::SUCCESS - } - } - } - - Command::Payload { - inputs, - find_base, - lib, - delta_from, - portable, - claim_project, - claim_commit, - claim_service, - apply_to, - lenient, - ids, - tables, - encode, - output, - } => { - if tables { - if !inputs.is_empty() { - eprintln!("error: --tables takes no payload inputs"); - return ExitCode::FAILURE; - } - let text = serde_json::to_string_pretty(&codec_tables_doc()).unwrap(); - return match output { - Some(out) => { - if let Err(e) = std::fs::write(&out, text + "\n") { - eprintln!("error: cannot write {}: {e}", out.display()); - return ExitCode::FAILURE; - } - ExitCode::SUCCESS - } - None => { - println!("{text}"); - ExitCode::SUCCESS - } - }; - } - if inputs.is_empty() { - eprintln!("error: no input payloads"); - return ExitCode::FAILURE; - } - let names = match load_library_id_names(lib.as_deref()) { - Ok(n) => n, - Err(code) => return code, - }; - if let Some(base_path) = &delta_from { - let [target_path] = inputs.as_slice() else { - eprintln!("error: --delta-from takes exactly one target snapshot"); - return ExitCode::FAILURE; - }; - let base = match load_snapshot_value(base_path, &names) { - Ok(v) => v, - Err(code) => return code, - }; - let target = match load_snapshot_value(target_path, &names) { - Ok(v) => v, - Err(code) => return code, - }; - let mut claims: Vec<(u64, sysmlv2_cbor::Claim)> = Vec::new(); - for (key, id) in [(0, &claim_project), (1, &claim_commit)] { - if let Some(s) = id { - match uuid::Uuid::try_parse(s) { - Ok(u) => claims.push((key, sysmlv2_cbor::Claim::Id(u))), - Err(_) => { - eprintln!("error: claim `{s}` is not a UUID"); - return ExitCode::FAILURE; - } - } - } - } - if let Some(s) = &claim_service { - claims.push((2, sysmlv2_cbor::Claim::Text(s.clone()))); - } - let opts = sysmlv2_cbor::DeltaOptions { - portable, - claims, - units: Vec::new(), - }; - return match sysmlv2_cbor::delta_compact_cbor(&base, &target, &opts) { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode the delta: {e}"); - ExitCode::FAILURE - } - }; - } - if let Some(base_path) = &apply_to { - let [delta_path] = inputs.as_slice() else { - eprintln!("error: --apply-to takes exactly one delta payload"); - return ExitCode::FAILURE; - }; - let Some(out_path) = &output else { - eprintln!("error: --apply-to writes the applied snapshot to --output"); - return ExitCode::FAILURE; - }; - let bytes = match std::fs::read(delta_path) { - Ok(b) => b, - Err(e) => { - eprintln!("error: cannot read {}: {e}", delta_path.display()); - return ExitCode::FAILURE; - } - }; - let base = match load_snapshot_value(base_path, &names) { - Ok(v) => v, - Err(code) => return code, - }; - let applied = if lenient { - sysmlv2_cbor::apply_delta_cbor_lenient(&bytes, &base) - } else { - sysmlv2_cbor::apply_delta_cbor_report_with(&bytes, &base, &|s| { - names.get(s).cloned() - }) - }; - let (result, report) = match applied { - Ok(r) => r, - Err(e) => { - eprintln!("error: cannot apply {}: {e}", delta_path.display()); - return ExitCode::FAILURE; - } - }; - let result_digest = match sysmlv2_cbor::state_digest(&result) { - Ok(d) => d.to_string(), - Err(e) => { - eprintln!("error: cannot digest the applied result: {e}"); - return ExitCode::FAILURE; - } - }; - let text = serde_json::to_string_pretty(&result).unwrap(); - if let Err(e) = std::fs::write(out_path, text + "\n") { - eprintln!("error: cannot write {}: {e}", out_path.display()); - return ExitCode::FAILURE; - } - let doc = serde_json::json!({ - "file": delta_path.display().to_string(), - "baseMatched": report.base_matched, - "noopDeletes": report.noop_deletes, - "upsertedUpdates": report.upserted_updates, - "replacedCreates": report.replaced_creates, - "units": report - .units - .iter() - .map(|(index, path)| serde_json::json!({ "index": index, "path": path })) - .collect::>(), - "resultElements": result.as_array().map(Vec::len), - "resultDigest": result_digest, - "output": out_path.display().to_string(), - }); - println!("{}", serde_json::to_string_pretty(&doc).unwrap()); - return ExitCode::SUCCESS; - } - if encode { - let [input] = inputs.as_slice() else { - eprintln!("error: --encode takes exactly one compact-JSON snapshot"); - return ExitCode::FAILURE; - }; - let value = match load_snapshot_value(input, &names) { - Ok(v) => v, - Err(code) => return code, - }; - return match sysmlv2_cbor::to_compact_cbor(&value) { - Ok(bytes) => write_bytes(output.as_deref(), &bytes), - Err(e) => { - eprintln!("error: cannot encode {}: {e}", input.display()); - ExitCode::FAILURE - } - }; - } - if ids { - let mut summaries = Vec::new(); - for path in &inputs { - let value = match load_snapshot_value(path, &names) { - Ok(v) => v, - Err(code) => return code, - }; - let canon = match sysmlv2_cbor::delta_canonical(&value) { - Ok(c) => c, - Err(e) => { - eprintln!("error: {}: cannot canonicalize: {e}", path.display()); - return ExitCode::FAILURE; - } - }; - let digest = match sysmlv2_cbor::state_digest(&value) { - Ok(d) => d.to_string(), - Err(e) => { - eprintln!("error: {}: cannot digest: {e}", path.display()); - return ExitCode::FAILURE; - } - }; - let id_seq: Vec<&str> = canon - .as_array() - .unwrap() - .iter() - .filter_map(|e| e.get("@id").and_then(serde_json::Value::as_str)) - .collect(); - summaries.push(serde_json::json!({ - "file": path.display().to_string(), - "elements": id_seq.len(), - "stateDigest": digest, - "ids": id_seq, - })); - } - let doc = if summaries.len() == 1 { - summaries.pop().unwrap() - } else { - serde_json::Value::Array(summaries) - }; - println!("{}", serde_json::to_string_pretty(&doc).unwrap()); - return ExitCode::SUCCESS; - } - // One scan shared by every delta input: digest each - // snapshot-looking file under the directory once. - let candidates: Option> = find_base.as_ref().map(|dir| { - payload_files_under(dir) - .into_iter() - .filter_map(|p| snapshot_file_digest(&p, &names).map(|d| (p, d))) - .collect() - }); - let mut summaries = Vec::new(); - let mut saw_delta = false; - let mut unmatched = false; - for path in &inputs { - let bytes = match std::fs::read(path) { - Ok(b) => b, - Err(e) => { - eprintln!("error: cannot read {}: {e}", path.display()); - return ExitCode::FAILURE; - } - }; - let mut summary = match sysmlv2_cbor::describe(&bytes) { - Ok(s) => { - let described = s.as_object().unwrap().clone(); - let mut o = serde_json::Map::new(); - o.insert("file".into(), serde_json::json!(path.display().to_string())); - o.insert("encoding".into(), serde_json::json!("cbor")); - o.extend(described); - serde_json::Value::Object(o) - } - // Not s2c — a compact interchange JSON snapshot - // still has a state digest worth printing. - Err(cbor_err) => match serde_json::from_slice::(&bytes) { - Ok(v) if v.is_array() => { - let digest = match sysmlv2_cbor::state_digest(&v) { - Ok(d) => d.to_string(), - Err(e) => { - eprintln!("error: {}: cannot digest: {e}", path.display()); - return ExitCode::FAILURE; - } - }; - serde_json::json!({ - "file": path.display().to_string(), - "encoding": "json", - "form": "compact", - "bytes": bytes.len(), - "elements": v.as_array().unwrap().len(), - "stateDigest": digest, - }) - } - _ => { - eprintln!( - "error: {}: not an interchange payload (s2c or \ - compact JSON element array): {cbor_err}", - path.display() - ); - return ExitCode::FAILURE; - } - }, - }; - if summary["form"] == "delta" { - saw_delta = true; - if let Some(cands) = &candidates { - let matches = |key: &str| -> Vec { - cands - .iter() - .filter(|(_, d)| Some(d.as_str()) == summary["delta"][key].as_str()) - .map(|(p, _)| serde_json::json!(p.display().to_string())) - .collect() - }; - let base_matches = matches("baseDigest"); - let result_matches = matches("resultDigest"); - if base_matches.is_empty() { - eprintln!( - "note: {}: no snapshot under {} matches the delta's \ - base digest", - path.display(), - find_base.as_ref().unwrap().display() - ); - unmatched = true; - } - let d = summary["delta"].as_object_mut().unwrap(); - d.insert("baseMatches".into(), serde_json::json!(base_matches)); - d.insert("resultMatches".into(), serde_json::json!(result_matches)); - } - } else if summary["encoding"] == "cbor" - && summary["form"] == "compact" - && summary["versions"]["supported"] == true - { - // Compact snapshot s2c: the state digest requires a - // decode (elided payloads re-derive their ids - // first). Full-form payloads have no state digest — - // the digest space is compact-form canonical. - match decode_snapshot(&bytes, &names) { - Ok(v) => match sysmlv2_cbor::state_digest(&v) { - Ok(d) => { - summary - .as_object_mut() - .unwrap() - .insert("stateDigest".into(), serde_json::json!(d.to_string())); - } - Err(e) => { - eprintln!("error: {}: cannot digest: {e}", path.display()); - return ExitCode::FAILURE; - } - }, - Err(e) => { - summary.as_object_mut().unwrap().insert( - "stateDigestError".into(), - serde_json::json!(e.to_string()), - ); - } - } - } - summaries.push(summary); - } - if candidates.is_some() && !saw_delta { - eprintln!("error: --find-base needs a delta payload input"); - return ExitCode::FAILURE; - } - let doc = if summaries.len() == 1 { - summaries.pop().unwrap() - } else { - serde_json::Value::Array(summaries) - }; - println!("{}", serde_json::to_string_pretty(&doc).unwrap()); - if unmatched { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - - Command::Fmt { - files, - check, - stdout, - indent, - } => { - // Ambient inputs never drive an in-place rewrite: a whole - // workspace reformatted because an env var happened to be - // set is a footgun. --check is the read-only mode. - let files = if files.is_empty() && !check { - eprintln!( - "error: no input files — fmt rewrites in place, so ambient \ - {MODEL_DIR_VAR} inputs apply to --check only; pass explicit paths" - ); - return ExitCode::FAILURE; - } else { - match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - } - }; - let mut failed = false; - for path in &files { - if path == Path::new("-") && !stdout && !check { - eprintln!("error: cannot format stdin (`-`) in place; use --stdout or --check"); - failed = true; - continue; - } - let src = match read(path) { - Ok(s) => s, - Err(_) => { - failed = true; - continue; - } - }; - match format_source_with(&src, dialect_of(path), indent) { - Err(diags) => { - report(path, &src, &diags); - failed = true; - } - Ok(formatted) => { - if stdout { - print!("{formatted}"); - } else if check { - if formatted != src { - eprintln!("would reformat: {}", path.display()); - failed = true; - } - } else if formatted != src { - if let Err(e) = std::fs::write(path, &formatted) { - eprintln!("error: cannot write {}: {e}", path.display()); - failed = true; - } - } - } - } - } - if failed { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - - Command::Check { files, lib, strict } => { - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let mut errors = 0usize; - let mut warnings = 0usize; - // `.kpar` archives expand to their contained textual units. - let inputs = match read_inputs(&files) { - Ok(i) => i, - Err(code) => return code, - }; - // (path, source) per cleanly-parsed file, for the model stage. - let mut sources: Vec<(&PathBuf, String)> = Vec::new(); - for (path, src) in &inputs { - let src = src.clone(); - let parse = parse_file(path, &src); - if !parse.diagnostics.is_empty() { - report(path, &src, &parse.diagnostics); - errors += parse.diagnostics.len(); - continue; // context checks on a broken parse would mislead - } - let context_diags = sysmlv2_parser::check::validate(&parse.unit); - if !context_diags.is_empty() { - report(path, &src, &context_diags); - errors += context_diags.len(); - } - sources.push((path, src)); - } - - // Referential and semantic checks always run over all cleanly - // parsed files as one model. A standard library enriches - // resolution, but basic local constraints must not disappear - // merely because `--lib` was omitted. - if !sources.is_empty() { - let mut model = Model::new(); - let lib_cache_path = if let Some(lib) = &lib { - match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - } - } else { - None - }; - // Unit indices: libraries first, then our files in order. - let boundary = model.units().len(); - for (path, src) in &sources { - model.add_source(path.display().to_string(), src); - } - let mut r = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - for (unit, d) in sysmlv2_parser::check::validate_model_with(&mut r, &model) - .into_iter() - .chain(sysmlv2_parser::check::validate_semantics_with( - &mut r, &model, - )) - { - let (path, src) = &sources[unit - boundary]; - match d.severity { - sysmlv2_parser::diag::Severity::Error => errors += 1, - sysmlv2_parser::diag::Severity::Warning => warnings += 1, - } - report(path, src, &[d]); - } - if lib.is_some() { - // Unused private imports: provenance + - // owner-chain + textual conditions, corpus-triaged. - let texts: Vec<(usize, String)> = sources - .iter() - .enumerate() - .map(|(i, (_, src))| (boundary + i, src.clone())) - .collect(); - for (unit, span) in - sysmlv2_transform::unused_private_imports_with(&mut r, &texts) - { - let (path, src) = &sources[unit - boundary]; - warnings += 1; - report( - path, - src, - &[sysmlv2_parser::Diagnostic::warning( - span, - "unused private import", - )], - ); - } - } - } - - if warnings > 0 { - eprintln!("{warnings} warning(s)"); - } - if errors > 0 { - eprintln!("{errors} error(s)"); - ExitCode::FAILURE - } else if strict && warnings > 0 { - eprintln!("--strict: warnings are failures"); - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - - Command::Lint { - files, - lib, - config, - rule, - fix, - fix_deletes, - strict, - } => { - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let inputs = match read_inputs(&files) { - Ok(i) => i, - Err(code) => return code, - }; - // Config: --config, else sysmlint.json beside the first input. - let config_path = config.or_else(|| { - let candidate = files - .first() - .and_then(|f| f.parent()) - .map(|d| d.join("sysmlint.json"))?; - candidate.exists().then_some(candidate) - }); - let mut cfg = match &config_path { - Some(p) => match std::fs::read_to_string(p) - .map_err(|e| e.to_string()) - .and_then(|t| sysmlv2_lint::Config::from_json(&t)) - { - Ok(c) => c, - Err(e) => { - eprintln!("error: cannot read lint config {}: {e}", p.display()); - return ExitCode::FAILURE; - } - }, - None => sysmlv2_lint::Config::default(), - }; - for r in &rule { - let Some((id, level)) = r.split_once('=') else { - eprintln!("error: --rule wants ID=LEVEL, got `{r}`"); - return ExitCode::FAILURE; - }; - let level = match level { - "off" => sysmlv2_lint::Severity::Off, - "hint" => sysmlv2_lint::Severity::Hint, - "info" => sysmlv2_lint::Severity::Info, - "warn" => sysmlv2_lint::Severity::Warn, - "error" => sysmlv2_lint::Severity::Error, - other => { - eprintln!( - "error: --rule level must be off|hint|info|warn|error, got `{other}`" - ); - return ExitCode::FAILURE; - } - }; - cfg.set(id, level); - } - - // The model stage wants cleanly-parsed sources only. - let mut errors = 0usize; - let mut warnings = 0usize; - let mut sources: Vec<(&PathBuf, String)> = Vec::new(); - for (path, src) in &inputs { - let parse = parse_file(path, src); - if !parse.diagnostics.is_empty() { - report(path, src, &parse.diagnostics); - errors += parse.diagnostics.len(); - continue; - } - sources.push((path, src.clone())); - } - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = &lib { - lib_cache_path = match load_library(&mut model, lib) { - Ok(p) => Some(p), - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - }; - } - // Without `--lib`, the ambient libraries still load so - // ordinary content + sidecar invocations resolve their - // provenance record types (with `--lib` they came along). - if lib.is_none() { - sysmlv2_parser::ambient::add_to(&mut model); - } - let boundary = model.units().len(); - for (path, src) in &sources { - model.add_source(path.display().to_string(), src); - } - let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - if let Some(p) = lib_cache_path { - save_library_cache(&model, p); - } - // The textual tier (`indentation`) reads the units' source - // text; unit indexes start past the library units. Names - // ride along (AA7g): the generated-provenance rules audit - // the sidecar placement contract, which is spelled in unit - // names — with lint_with_sources they were silent in CI. - let names: Vec = sources - .iter() - .map(|(path, _)| path.display().to_string()) - .collect(); - let texts: Vec<(usize, &str, &str)> = sources - .iter() - .enumerate() - .map(|(i, (_, src))| (boundary + i, names[i].as_str(), src.as_str())) - .collect(); - let findings = sysmlv2_lint::lint_units(&mut resolved, &cfg, &texts); - - for f in &findings { - match (f.unit, f.span) { - (Some(unit), Some(span)) => { - let (path, src) = &sources[unit - boundary]; - let message = format!("{} [{}]", f.message, f.rule); - let diag = match f.severity { - sysmlv2_lint::Severity::Error => { - errors += 1; - sysmlv2_parser::Diagnostic::error(span, message) - } - _ => { - warnings += 1; - sysmlv2_parser::Diagnostic::warning(span, message) - } - }; - report(path, src, &[diag]); - } - _ => { - warnings += 1; - eprintln!("warning: {} [{}]", f.message, f.rule); - } - } - } - - // Fix application: safe fixes under --fix; fixes that delete - // model text additionally need --fix-deletes. Whole-line - // deletions swallow their now-blank line; every rewritten - // source must reparse cleanly before it is written back. - if fix { - let mut skipped_deletes = 0usize; - let mut edits_by_unit: HashMap> = HashMap::new(); - for f in &findings { - let Some(fx) = &f.fix else { continue }; - if fx.deletes && !fix_deletes { - skipped_deletes += 1; - continue; - } - for e in &fx.edits { - edits_by_unit - .entry(e.unit) - .or_default() - .push((Span::new(e.span.start, e.span.end), e.replacement.clone())); - } - } - let mut units: Vec<_> = edits_by_unit.into_iter().collect(); - units.sort_by_key(|(u, _)| *u); - for (unit, mut edits) in units { - let (path, src) = &sources[unit - boundary]; - // Two findings can carry the same edit (each - // import-adding fix restates the insert so it works - // standalone) or overlapping ones (two rules - // rewriting one span) — identical edits collapse, - // and of an overlapping pair only the first - // survives. - edits.sort_by(|a, b| { - (a.0.start, a.0.end, &a.1).cmp(&(b.0.start, b.0.end, &b.1)) - }); - edits.dedup(); - let mut kept: Vec<(Span, String)> = Vec::new(); - for e in edits { - let overlaps = kept.last().is_some_and(|(prev, _)| e.0.start < prev.end); - if !overlaps { - kept.push(e); - } - } - let mut edits = kept; - edits.sort_by_key(|(s, _)| std::cmp::Reverse(s.start)); - let mut text = src.clone(); - for (span, replacement) in edits { - let (mut start, mut end) = (span.start as usize, span.end as usize); - if replacement.is_empty() { - // Swallow the whole line when deleting leaves - // it blank. - let line_start = text[..start].rfind('\n').map(|i| i + 1).unwrap_or(0); - let line_end = text[end..] - .find('\n') - .map(|i| end + i + 1) - .unwrap_or(text.len()); - let blank = |s: &str| s.chars().all(char::is_whitespace); - if blank(&text[line_start..start]) - && blank(text[end..line_end.min(text.len())].trim_end_matches('\n')) - { - start = line_start; - end = line_end; - } - } - text.replace_range(start..end, &replacement); - } - let reparse = parse_file(path, &text); - if !reparse.diagnostics.is_empty() { - eprintln!("error: fixes would break {} — not written", path.display()); - errors += 1; - continue; - } - if !path.exists() { - eprintln!( - "note: {} is not a plain file (stdin or archive) — fixed text \ - not written", - path.display() - ); - continue; - } - if let Err(e) = std::fs::write(path, &text) { - eprintln!("error: cannot write {}: {e}", path.display()); - errors += 1; - continue; - } - if !quiet { - eprintln!("fixed: {}", path.display()); - } - } - if skipped_deletes > 0 { - eprintln!( - "{skipped_deletes} deletion fix(es) available but not applied — \ - deleting model text needs --fix --fix-deletes" - ); - } - } - - if warnings > 0 { - eprintln!("{warnings} warning(s)"); - } - if errors > 0 { - eprintln!("{errors} error(s)"); - ExitCode::FAILURE - } else if strict && warnings > 0 { - eprintln!("--strict: warnings are failures"); - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - - #[cfg(feature = "solve")] - Command::Verify { - files, - lib, - ranges, - solve, - z3, - } => { - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = &lib { - lib_cache_path = match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - }; - } - // Unit indices: libraries first, then our files in order. - let boundary = model.units().len(); - let mut sources: Vec<(&PathBuf, String)> = Vec::new(); - for path in &files { - let src = match read(path) { - Ok(s) => s, - Err(code) => return code, - }; - let unit = model.add_source(path.display().to_string(), &src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, &src, &diags); - return ExitCode::FAILURE; - } - sources.push((path, src)); - } - let code = verify_and_report(&model, boundary, &sources, ranges, solve, z3); - save_library_cache(&model, lib_cache_path); - code - } - - Command::Eval { - input, - names, - all, - lib, - } => { - // Positional arguments ending in a model extension are further - // files joining the model; the rest are names to evaluate. The - // leading positional joins the classification (an existing file - // path counts even without a model extension), so with an - // ambient model dir `sysmlv2 eval Demo::mass` is all names. - let is_file = |s: &str| s.ends_with(".sysml") || s.ends_with(".kerml") || s == "-"; - let (extra_files, mut names): (Vec, Vec) = - names.into_iter().partition(|n| is_file(n)); - let mut files: Vec = Vec::new(); - if let Some(input) = input { - let s = input.display().to_string(); - if is_file(&s) || input.is_file() { - files.push(input); - } else { - names.insert(0, s); - } - } - files.extend(extra_files.iter().map(PathBuf::from)); - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = &lib { - lib_cache_path = match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - }; - } - for path in &files { - let src = match read(path) { - Ok(s) => s, - Err(code) => return code, - }; - let unit = model.add_source(path.display().to_string(), &src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, &src, &diags); - return ExitCode::FAILURE; - } - } - let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - let mut failed = false; - if all { - for e in resolved.features_with_values() { - let label = resolved - .element_name(e) - .unwrap_or("") - .to_string(); - match resolved.evaluate(e) { - Ok(v) => println!("{label} = {v}"), - Err(err) => println!("{label}: {err}"), - } - } - } - for name in &names { - if resolved.resolve_qualified(name).is_none() { - eprintln!("error: cannot resolve `{name}`"); - failed = true; - continue; - } - // Chain-step semantics: the path prefix establishes the - // featuring context, so `Pkg::part::attr` computes the - // same value as `part.attr`. - match resolved.evaluate_qualified(name) { - Ok(v) => println!("{name} = {v}"), - Err(err) => { - eprintln!("error: {name}: {err}"); - failed = true; - } - } - } - if failed { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - - Command::Render { args, lib, html } => { - let is_file = |s: &str| s.ends_with(".sysml") || s.ends_with(".kerml"); - let (files, names): (Vec, Vec) = - args.into_iter().partition(|a| is_file(a)); - let [view_name] = names.as_slice() else { - eprintln!( - "error: expected exactly one view usage name, got {}", - names.len() - ); - return ExitCode::FAILURE; - }; - let files = match resolve_inputs(files.into_iter().map(PathBuf::from).collect(), quiet) - { - Ok(files) => files, - Err(code) => return code, - }; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = &lib { - lib_cache_path = match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - }; - } - for path in &files { - let src = match read(path) { - Ok(s) => s, - Err(code) => return code, - }; - let unit = model.add_source(path.display().to_string(), &src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, &src, &diags); - return ExitCode::FAILURE; - } - } - let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - let Some(view) = resolved.resolve_qualified(view_name) else { - eprintln!("error: element not found: {view_name}"); - return ExitCode::FAILURE; - }; - match resolved.render_view(view) { - Ok(nodes) => { - if html { - println!("{}", sysmlv2_parser::render::to_html(&nodes)); - } else { - let json = - serde_json::Value::Array(nodes.iter().map(|n| n.to_json()).collect()); - println!("{}", serde_json::to_string_pretty(&json).unwrap()); - } - ExitCode::SUCCESS - } - Err(e) => { - eprintln!("error: {e}"); - ExitCode::FAILURE - } - } - } - Command::Query { input, args, lib } => { - // Positional arguments ending in a model extension are further - // files joining the model; exactly one remaining argument is - // the query expression. The leading positional joins the - // classification (an existing file path counts even without a - // model extension), so with an ambient model dir - // `sysmlv2 query ''` is just the expression. - let is_file = |s: &str| s.ends_with(".sysml") || s.ends_with(".kerml") || s == "-"; - let (extra_files, mut exprs): (Vec, Vec) = - args.into_iter().partition(|a| is_file(a)); - let mut files: Vec = Vec::new(); - if let Some(input) = input { - let s = input.display().to_string(); - if is_file(&s) || input.is_file() { - files.push(input); - } else { - exprs.insert(0, s); - } - } - files.extend(extra_files.iter().map(PathBuf::from)); - let [expr_src] = exprs.as_slice() else { - eprintln!( - "error: expected exactly one query expression, got {}", - exprs.len() - ); - return ExitCode::FAILURE; - }; - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let parsed = sysmlv2_parser::parser::parse_expression(expr_src); - if !parsed.diagnostics.is_empty() { - report(Path::new(""), expr_src, &parsed.diagnostics); - return ExitCode::FAILURE; - } - let Some(expr) = parsed.expr else { - eprintln!("error: the query is not an expression"); - return ExitCode::FAILURE; - }; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(lib) = &lib { - lib_cache_path = match load_library(&mut model, lib) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", lib.display()); - return ExitCode::FAILURE; - } - }; - } - for path in &files { - let src = match read(path) { - Ok(s) => s, - Err(code) => return code, - }; - let unit = model.add_source(path.display().to_string(), &src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, &src, &diags); - return ExitCode::FAILURE; - } - } - let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - let root = resolved.root_scope(); - match resolved.query(root, &expr) { - Ok(sysmlv2_parser::eval::Value::Sequence(items)) => { - for item in items { - println!("{}", render_query_value(&mut resolved, &item)); - } - ExitCode::SUCCESS - } - Ok(v) => { - println!("{}", render_query_value(&mut resolved, &v)); - ExitCode::SUCCESS - } - Err(e) => { - eprintln!("error: {e}"); - ExitCode::FAILURE - } - } - } - - Command::Describe { input, args, lib } => { - let (mut resolved, qname) = - match resolve_model_and_name(input, args, lib.as_deref(), quiet) { - Ok(v) => v, - Err(code) => return code, - }; - let Some(e) = resolved.resolve_qualified(&qname) else { - eprintln!("error: cannot resolve `{qname}`"); - return ExitCode::FAILURE; - }; - println!("{qname}"); - println!(" metaclass {}", resolved.element_type(e)); - let owner = resolved.owner(e); - if let Some(owner) = owner { - if let Some(oq) = resolved.element_qualified_name(owner) { - println!(" owner {oq}"); - } - } - if let Some(t) = resolved.typings(e).first().copied() { - let label = resolved - .element_qualified_name(t) - .or_else(|| resolved.element_name(t).map(str::to_string)); - if let Some(label) = label { - println!(" type {label}"); - } - } - if let Some(owner) = owner { - let members = resolved.owned_members(owner); - if let Some(idx) = members.iter().position(|m| *m == e) { - println!(" position {} of {}", idx + 1, members.len()); - } - } - if let Some((file, line, col)) = resolved.declaration_position(e) { - println!(" location {file}:{line}:{col}"); - } - ExitCode::SUCCESS - } - - Command::Members { input, args, lib } => { - let (mut resolved, qname) = - match resolve_model_and_name(input, args, lib.as_deref(), quiet) { - Ok(v) => v, - Err(code) => return code, - }; - let Some(e) = resolved.resolve_qualified(&qname) else { - eprintln!("error: cannot resolve `{qname}`"); - return ExitCode::FAILURE; - }; - for m in resolved.owned_members(e) { - let name = resolved - .element_name(m) - .unwrap_or("(anonymous)") - .to_string(); - println!("{name:<28} {}", resolved.element_type(m)); - } - ExitCode::SUCCESS - } - - Command::Refactor { op } => run_refactor(op, quiet), - Command::Parse { input, ast } => { - // Ambient inputs make this a per-file loop: each file parses - // (and reports) independently, any diagnostic fails the run. - let files = match resolve_inputs(input.into_iter().collect(), quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let mut failed = false; - for input in &files { - let src = match read(input) { - Ok(s) => s, - Err(code) => return code, - }; - let parse = parse_file(input, &src); - report(input, &src, &parse.diagnostics); - if ast { - println!("{:#?}", parse.unit); - } else { - println!( - "{}: {} top-level member(s), {} diagnostic(s)", - input.display(), - parse.unit.members.len(), - parse.diagnostics.len() - ); - } - failed |= !parse.diagnostics.is_empty(); - } - if failed { - ExitCode::FAILURE - } else { - ExitCode::SUCCESS - } - } - #[cfg(feature = "viz")] - Command::Viz { - files, - view, - element, - lib, - horizontal, - no_values, - no_notes, - hide_metadata, - show_inherited, - show_lib, - show_imported, - line_style, - color, - link_template, - output, - } => { - let view = match view.as_deref() { - None => None, - Some("tree") => Some(sysmlv2_viz::View::Tree), - Some("interconnection" | "ic") => Some(sysmlv2_viz::View::Interconnection), - Some("state") => Some(sysmlv2_viz::View::State), - Some("action") => Some(sysmlv2_viz::View::Action), - Some("sequence" | "seq") => Some(sysmlv2_viz::View::Sequence), - Some("case") => Some(sysmlv2_viz::View::Case), - Some("mixed") => Some(sysmlv2_viz::View::Mixed), - Some(other) => { - eprintln!( - "error: unknown view `{other}` (expected tree, interconnection, state, action, sequence, case, or mixed)" - ); - return ExitCode::FAILURE; - } - }; - let line_style = match line_style.as_deref() { - None => sysmlv2_viz::LineStyle::Default, - Some("polyline") => sysmlv2_viz::LineStyle::Polyline, - Some("ortho") => sysmlv2_viz::LineStyle::Ortho, - Some(other) => { - eprintln!("error: unknown line style `{other}` (expected polyline or ortho)"); - return ExitCode::FAILURE; - } - }; - let files = match resolve_inputs(files, quiet) { - Ok(files) => files, - Err(code) => return code, - }; - let inputs = match read_inputs(&files) { - Ok(i) => i, - Err(code) => return code, - }; - let mut model = Model::new(); - let mut lib_cache_path = None; - if let Some(dir) = &lib { - lib_cache_path = match load_library(&mut model, dir) { - Ok(p) => p, - Err(e) => { - eprintln!("error: cannot load library {}: {e}", dir.display()); - return ExitCode::FAILURE; - } - }; - } - let mut parse_errors = false; - for (path, src) in &inputs { - let unit = model.add_source(path.display().to_string(), src); - if !unit.diagnostics.is_empty() { - let diags = unit.diagnostics.clone(); - report(path, src, &diags); - parse_errors = true; - } - } - if parse_errors { - return ExitCode::FAILURE; - } - let mut resolved = sysmlv2_parser::json::ResolvedModel::build(&model); - save_library_cache(&model, lib_cache_path); - let root = match &element { - Some(name) => match resolved.resolve_qualified(name) { - Some(e) => Some(e), - None => { - eprintln!("error: element not found: {name}"); - return ExitCode::FAILURE; - } - }, - None => None, - }; - // A view usage directs its own rendering: the diagram's - // elements are what the view exposes (filter conditions - // applied), and its `render` member picks the style unless - // --view was given explicitly. - let (root, view, roots) = match root { - Some(e) => match sysmlv2_viz::view_directed(&mut resolved, e) { - Some((style, exposed)) => (None, view.or(style), Some(exposed)), - None => (Some(e), view, None), - }, - None => (None, view, None), - }; - let view = view.unwrap_or(sysmlv2_viz::View::Tree); - let opts = sysmlv2_viz::VizOptions { - direction: if horizontal { - sysmlv2_viz::Direction::LeftToRight - } else { - sysmlv2_viz::Direction::TopToBottom - }, - show_values: !no_values, - view, - show_notes: !no_notes, - show_metadata: !hide_metadata, - show_inherited, - show_lib, - show_imported, - line_style, - std_color: color, - link_template, - roots, - }; - let text = sysmlv2_viz::plantuml(&mut resolved, root, &opts); - match &output { - Some(path) => { - if let Err(e) = std::fs::write(path, &text) { - eprintln!("error: cannot write {}: {e}", path.display()); - return ExitCode::FAILURE; - } - } - None => print!("{text}"), - } - ExitCode::SUCCESS - } - - #[cfg(feature = "lsp")] - Command::Lsp { lib } => match sysmlv2_lsp::run_stdio(lib) { - Ok(()) => ExitCode::SUCCESS, - Err(e) => { - eprintln!("error: {e}"); - ExitCode::FAILURE - } - }, - } -} - -#[cfg(test)] -mod refactor_persistence_tests { - use super::*; - - struct TestDir(PathBuf); - - impl TestDir { - fn new() -> Self { - let path = std::env::temp_dir() - .join(format!("sysmlv2-cli-persist-test-{}", uuid::Uuid::new_v4())); - std::fs::create_dir(&path).expect("create test directory"); - Self(path) - } - } - - impl Drop for TestDir { - fn drop(&mut self) { - let _ = std::fs::remove_dir_all(&self.0); - } - } - - #[test] - fn a_later_replace_failure_rolls_back_earlier_files() { - let dir = TestDir::new(); - let a = dir.0.join("a.sysml"); - let b = dir.0.join("b.sysml"); - std::fs::write(&a, "old a\n").unwrap(); - std::fs::write(&b, "old b\n").unwrap(); - let changes = vec![ - RefactorFileChange { - path: a.clone(), - old: "old a\n".into(), - new: "new a\n".into(), - }, - RefactorFileChange { - path: b.clone(), - old: "old b\n".into(), - new: "new b\n".into(), - }, - ]; - let mut promotions = 0; - let error = persist_refactor_changes_with(&changes, |from, to| { - if from - .file_name() - .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")) - { - promotions += 1; - if promotions == 2 { - return Err(std::io::Error::new( - std::io::ErrorKind::PermissionDenied, - "simulated second replacement failure", - )); - } - } - std::fs::rename(from, to) - }) - .expect_err("second replacement must fail"); - - assert!(error.contains("simulated second replacement failure")); - assert!(error.contains("rolled back 1 earlier file(s)")); - assert_eq!(std::fs::read_to_string(a).unwrap(), "old a\n"); - assert_eq!(std::fs::read_to_string(b).unwrap(), "old b\n"); - let leftovers: Vec<_> = std::fs::read_dir(&dir.0) - .unwrap() - .map(|e| e.unwrap().file_name()) - .filter(|n| n.to_string_lossy().contains(".sysmlv2-")) - .collect(); - assert!(leftovers.is_empty(), "leftover sidecars: {leftovers:?}"); - } - - #[test] - fn a_concurrent_later_edit_is_preserved_while_earlier_files_roll_back() { - let dir = TestDir::new(); - let a = dir.0.join("a.sysml"); - let b = dir.0.join("b.sysml"); - std::fs::write(&a, "old a\n").unwrap(); - std::fs::write(&b, "old b\n").unwrap(); - let changes = vec![ - RefactorFileChange { - path: a.clone(), - old: "old a\n".into(), - new: "new a\n".into(), - }, - RefactorFileChange { - path: b.clone(), - old: "old b\n".into(), - new: "new b\n".into(), - }, - ]; - let mut promotions = 0; - let error = persist_refactor_changes_with(&changes, |from, to| { - let is_promotion = from - .file_name() - .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")); - let result = std::fs::rename(from, to); - if is_promotion { - promotions += 1; - if promotions == 1 { - std::fs::write(&b, "external b\n").unwrap(); - } - } - result - }) - .expect_err("concurrent second-file edit must refuse"); - - assert!(error.contains("changed on disk before it could be replaced")); - assert!(error.contains("rolled back 1 earlier file(s)")); - assert_eq!(std::fs::read_to_string(a).unwrap(), "old a\n"); - assert_eq!(std::fs::read_to_string(b).unwrap(), "external b\n"); - } - - #[test] - fn a_concurrent_edit_to_an_applied_file_is_not_overwritten_by_rollback() { - let dir = TestDir::new(); - let a = dir.0.join("a.sysml"); - let b = dir.0.join("b.sysml"); - std::fs::write(&a, "old a\n").unwrap(); - std::fs::write(&b, "old b\n").unwrap(); - let changes = vec![ - RefactorFileChange { - path: a.clone(), - old: "old a\n".into(), - new: "new a\n".into(), - }, - RefactorFileChange { - path: b.clone(), - old: "old b\n".into(), - new: "new b\n".into(), - }, - ]; - let mut promotions = 0; - let error = persist_refactor_changes_with(&changes, |from, to| { - let is_promotion = from - .file_name() - .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-new-")); - if is_promotion { - promotions += 1; - if promotions == 2 { - return Err(std::io::Error::new( - std::io::ErrorKind::PermissionDenied, - "simulated second replacement failure", - )); - } - } - let result = std::fs::rename(from, to); - if is_promotion && promotions == 1 { - std::fs::write(&a, "external a\n").unwrap(); - } - result - }) - .expect_err("second replacement must fail"); - - assert!(error.contains("rollback incomplete"), "{error}"); - assert!(error.contains("external edit was preserved"), "{error}"); - assert!(error.contains("recovery copy:"), "{error}"); - assert_eq!(std::fs::read_to_string(&a).unwrap(), "external a\n"); - assert_eq!(std::fs::read_to_string(&b).unwrap(), "old b\n"); - let leftovers: Vec<_> = std::fs::read_dir(&dir.0) - .unwrap() - .map(|e| e.unwrap().path()) - .filter(|p| { - p.file_name() - .is_some_and(|n| n.to_string_lossy().contains(".sysmlv2-")) - }) - .collect(); - assert_eq!(leftovers.len(), 1, "retained recovery copy: {leftovers:?}"); - assert_eq!(std::fs::read_to_string(&leftovers[0]).unwrap(), "old a\n"); - } - - #[cfg(all(unix, not(target_os = "wasi")))] - #[test] - fn a_hard_linked_target_is_refused_without_splitting_the_links() { - let dir = TestDir::new(); - let path = dir.0.join("model.sysml"); - let alias = dir.0.join("alias.sysml"); - std::fs::write(&path, "old\n").unwrap(); - std::fs::hard_link(&path, &alias).unwrap(); - let changes = [RefactorFileChange { - path: path.clone(), - old: "old\n".into(), - new: "new\n".into(), - }]; - - let error = persist_refactor_changes(&changes).expect_err("hard link must refuse"); - - assert!(error.contains("has 2 hard links"), "{error}"); - assert_eq!(std::fs::read_to_string(path).unwrap(), "old\n"); - assert_eq!(std::fs::read_to_string(alias).unwrap(), "old\n"); - } - - #[cfg(all(unix, not(target_os = "wasi")))] - #[test] - fn a_successful_replacement_preserves_unix_file_metadata() { - use std::os::unix::fs::{MetadataExt, PermissionsExt}; - - let dir = TestDir::new(); - let path = dir.0.join("model.sysml"); - std::fs::write(&path, "old\n").unwrap(); - std::fs::set_permissions(&path, Permissions::from_mode(0o640)).unwrap(); - let xattr_name = if cfg!(target_os = "macos") { - "com.openmbee.sysmlv2-test" - } else { - "user.sysmlv2-test" - }; - xattr::set(&path, xattr_name, b"retained").unwrap(); - let original_metadata = std::fs::metadata(&path).unwrap(); - let changes = [RefactorFileChange { - path: path.clone(), - old: "old\n".into(), - new: "new\n".into(), - }]; - - persist_refactor_changes(&changes).expect("replacement succeeds"); - - assert_eq!(std::fs::read_to_string(&path).unwrap(), "new\n"); - let replaced_metadata = std::fs::metadata(&path).unwrap(); - assert_eq!(replaced_metadata.permissions().mode() & 0o777, 0o640); - assert_eq!(replaced_metadata.uid(), original_metadata.uid()); - assert_eq!(replaced_metadata.gid(), original_metadata.gid()); - assert_eq!( - xattr::get(path, xattr_name).unwrap().as_deref(), - Some(b"retained".as_slice()) - ); - } +fn main() -> std::process::ExitCode { + sysmlv2_cli::run(std::env::args_os()) } diff --git a/crates/sysmlv2-cli/tests/cli.rs b/crates/sysmlv2-cli/tests/cli.rs index 8893301..ad12485 100644 --- a/crates/sysmlv2-cli/tests/cli.rs +++ b/crates/sysmlv2-cli/tests/cli.rs @@ -79,7 +79,7 @@ fn every_subcommand_help_has_examples() { #[test] fn convert_to_compact_json() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-convert"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-convert-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write(&input, "package P { part def V; part v : V; }").unwrap(); @@ -106,7 +106,10 @@ fn convert_to_compact_json() { #[test] fn plain_full_json_preserves_unresolved_reference_spelling() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-full-recovery"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-full-recovery-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let input = dir.join("partial.sysml"); fs::write(&input, "package P { part x : Missing; }").unwrap(); @@ -123,7 +126,7 @@ fn plain_full_json_preserves_unresolved_reference_spelling() { #[test] fn fmt_check_and_rewrite() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-fmt"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-fmt-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("messy.sysml"); fs::write(&input, "package P{part def V;part v:V;}").unwrap(); @@ -155,7 +158,7 @@ fn verify_ranges_narrows_and_attributes_verdicts() { // narrow `wingSpan`; a separate contradictory pair empties `count`. The // empty domain must implicate only the constraint that references it — // not its innocent siblings in the same unit. - let dir = std::env::temp_dir().join("sysmlv2-cli-test-ranges"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-ranges-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -197,7 +200,7 @@ fn verify_ranges_narrows_and_attributes_verdicts() { #[test] fn check_reports_rustc_style_diagnostics() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-check"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-check-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let good = dir.join("good.sysml"); let bad = dir.join("bad.sysml"); @@ -216,7 +219,7 @@ fn check_reports_rustc_style_diagnostics() { #[test] fn lint_flags_unused_parameters_and_deletes_only_behind_the_guard() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-lint"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-lint-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); let src = "package P {\n attribute def Real;\n calc def T {\n in force : Real;\n in radius : Real;\n return t : Real = force * 2;\n }\n}\n"; @@ -276,7 +279,10 @@ fn lint_flags_unused_parameters_and_deletes_only_behind_the_guard() { #[test] fn lint_rule_overrides_and_config_findings() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-lint-rules"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-lint-rules-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -316,7 +322,7 @@ fn lint_rule_overrides_and_config_findings() { #[test] fn convert_json_back_to_text() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-lift"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-lift-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -375,7 +381,7 @@ fn convert_with_library_uses_normative_ids() { eprintln!("skipping: corpus not present"); return; } - let dir = std::env::temp_dir().join("sysmlv2-cli-test-lib"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-lib-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -548,7 +554,10 @@ fn check_reports_unused_private_imports() { eprintln!("skipping: corpus not present"); return; } - let dir = std::env::temp_dir().join("sysmlv2-cli-test-unused-import"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-unused-import-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let defs = dir.join("defs.sysml"); let uses = dir.join("uses.sysml"); @@ -585,6 +594,31 @@ fn check_reports_unused_private_imports() { lib.to_str().unwrap(), ]); assert!(!out.status.success()); + + // As JSON: a referential-stage warning located in the second + // input, although the library units come first in the model. + let out = sysmlv2(&[ + "check", + "--format", + "json", + defs.to_str().unwrap(), + uses.to_str().unwrap(), + "--lib", + lib.to_str().unwrap(), + ]); + assert!(out.status.success(), "{}", stderr(&out)); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + let f = doc["findings"] + .as_array() + .unwrap() + .iter() + .find(|f| f["message"] == "unused private import") + .unwrap_or_else(|| panic!("{doc}")); + assert_eq!(f["stage"], "referential"); + assert_eq!(f["severity"], "warn"); + assert_eq!(f["unit"], 1); + assert_eq!(f["unitName"], uses.display().to_string()); + assert_eq!(f["line"], 2); } #[test] @@ -906,7 +940,8 @@ fn query_reads_multiple_files_and_stdin() { #[test] fn viz_view_selects_diagram_and_unknown_view_fails() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-viz-view"); + let dir = + std::env::temp_dir().join(format!("sysmlv2-cli-test-viz-view-{}", std::process::id())); std::fs::create_dir_all(&dir).unwrap(); let model = dir.join("m.sysml"); std::fs::write( @@ -935,6 +970,8 @@ fn viz_view_selects_diagram_and_unknown_view_fails() { let ic = run("interconnection"); assert!(ic.contains("rectangle"), "{ic}"); assert!(ic.contains(" : c1\n"), "{ic}"); + // The short spellings name the same views. + assert_eq!(run("ic"), ic); let state = run("state"); assert!(state.contains("<>"), "{state}"); assert!(state.contains("-->"), "{state}"); @@ -945,6 +982,7 @@ fn viz_view_selects_diagram_and_unknown_view_fails() { assert!(seq.contains("participant"), "{seq}"); assert!(seq.contains(" ->> "), "{seq}"); assert!(seq.contains(" : m1"), "{seq}"); + assert_eq!(run("seq"), seq); let mixed = run("mixed"); assert!(mixed.contains("rectangle"), "{mixed}"); assert!(mixed.contains("<>"), "{mixed}"); @@ -967,13 +1005,21 @@ fn viz_view_selects_diagram_and_unknown_view_fails() { assert!(styled.contains("BackgroundColor<>"), "{styled}"); assert!(styled.contains("[[x://"), "{styled}"); - let out = Command::new(env!("CARGO_BIN_EXE_sysmlv2")) - .args(["viz", model.to_str().unwrap(), "--view", "usecase"]) - .output() - .expect("run"); - assert!(!out.status.success()); - let err = String::from_utf8(out.stderr).unwrap(); - assert!(err.contains("unknown view"), "{err}"); + // A view or a routing the repertoire does not have is a usage + // error, listing what is accepted, like any other enumerated option. + for (flag, value) in [("--view", "usecase"), ("--line-style", "curvy")] { + let out = Command::new(env!("CARGO_BIN_EXE_sysmlv2")) + .args(["viz", model.to_str().unwrap(), flag, value]) + .output() + .expect("run"); + assert!(!out.status.success()); + let err = String::from_utf8(out.stderr).unwrap(); + assert!( + err.contains(&format!("invalid value '{value}' for '{flag}")), + "{err}" + ); + assert!(err.contains("possible values"), "{err}"); + } fs::remove_dir_all(&dir).ok(); } @@ -1003,7 +1049,7 @@ fn viz_emits_structure_diagram_from_stdin() { #[test] fn viz_element_scopes_and_unknown_element_fails() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-viz"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-viz-{}", std::process::id())); std::fs::create_dir_all(&dir).unwrap(); let model = dir.join("m.sysml"); std::fs::write( @@ -1032,7 +1078,7 @@ fn viz_element_scopes_and_unknown_element_fails() { #[test] fn convert_min_qual_respells_references() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-minqual"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-minqual-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -1087,7 +1133,7 @@ fn convert_min_qual_respells_references() { #[test] fn convert_compact_cbor_round_trip() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-cbor"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-cbor-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write(&input, "package P { part def V; part v : V; }").unwrap(); @@ -1122,6 +1168,14 @@ fn convert_compact_cbor_round_trip() { let direct: serde_json::Value = serde_json::from_str(&stdout(&out)).unwrap(); assert_eq!(via_cbor, direct); + // …through the full-form re-derivation… + let out = sysmlv2(&["convert", cbor_path.to_str().unwrap(), "--to", "full-json"]); + assert!(out.status.success(), "{}", stderr(&out)); + let via_cbor: serde_json::Value = serde_json::from_str(&stdout(&out)).unwrap(); + let out = sysmlv2(&["convert", input.to_str().unwrap(), "--to", "full-json"]); + let direct: serde_json::Value = serde_json::from_str(&stdout(&out)).unwrap(); + assert_eq!(via_cbor, direct); + // …and all the way back to textual notation. let out = sysmlv2(&["convert", cbor_path.to_str().unwrap(), "--to", "text"]); assert!(out.status.success(), "{}", stderr(&out)); @@ -1158,7 +1212,8 @@ fn convert_compact_cbor_round_trip() { #[test] fn convert_full_cbor_matches_full_json() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-fullcbor"); + let dir = + std::env::temp_dir().join(format!("sysmlv2-cli-test-fullcbor-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write(&input, "package P { part def V; part v : V; }").unwrap(); @@ -1187,7 +1242,7 @@ fn convert_full_cbor_matches_full_json() { #[test] fn convert_elide_ids_round_trips() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-elide"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-elide-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let input = dir.join("m.sysml"); fs::write( @@ -1241,7 +1296,7 @@ fn convert_elide_ids_round_trips() { #[test] fn convert_delta_emit_and_apply() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-delta"); + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-delta-{}", std::process::id())); fs::create_dir_all(&dir).unwrap(); let v1 = dir.join("v1.sysml"); let v2 = dir.join("v2.sysml"); @@ -1323,7 +1378,10 @@ fn convert_delta_emit_and_apply() { #[test] fn convert_elided_delta_emit_and_apply() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-elided-delta"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-elided-delta-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let v1 = dir.join("v1.sysml"); let v2 = dir.join("v2.sysml"); @@ -1389,6 +1447,18 @@ fn convert_elided_delta_emit_and_apply() { stdout(&out) ); + // A portable delta without a base is a usage error: the dependency + // is declared on the argument. + let out = sysmlv2(&[ + "convert", + v2.to_str().unwrap(), + "--to", + "compact-cbor", + "--delta-portable", + ]); + assert!(!out.status.success()); + assert!(stderr(&out).contains("--delta-base"), "{}", stderr(&out)); + // Portable + elided is refused with guidance. let out = sysmlv2(&[ "convert", @@ -1645,7 +1715,10 @@ fn lib_dir_env_enables_referential_checks() { #[test] fn check_runs_model_semantics_without_a_library() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-no-lib-semantics"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-no-lib-semantics-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let input = dir.join("bad.sysml"); fs::write(&input, "package P { part def D; part x : D[2..1]; }").unwrap(); @@ -2089,7 +2162,7 @@ fn payload_ids_prints_the_delta_canonical_sequence() { assert_eq!(from_json["stateDigest"], from_s2c["stateDigest"]); assert_eq!( from_json["ids"].as_array().unwrap().len(), - from_json["elements"].as_u64().unwrap() as usize + usize::try_from(from_json["elements"].as_u64().unwrap()).unwrap() ); fs::remove_dir_all(&dir).ok(); } @@ -2277,6 +2350,25 @@ fn convert_library_exports_the_resolved_stdlib() { "{}", stderr(&out) ); + // The conversion flags --library does not compose with are declared + // on the argument, so the combination is a usage error. + for flag in ["--flexo", "--min-qual", "--elide-ids"] { + let out = sysmlv2(&[ + "convert", + "--library", + "--lib", + &lib, + "--to", + "compact-json", + flag, + ]); + assert!(!out.status.success()); + assert!( + stderr(&out).contains(&format!("cannot be used with '{flag}'")), + "{}", + stderr(&out) + ); + } fs::remove_dir_all(&dir).ok(); } @@ -2366,7 +2458,10 @@ fn refactor_help_documents_both_directions() { #[test] fn refactor_extract_and_inline_round_trip_in_place() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-refactor-roundtrip"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-refactor-roundtrip-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let file = dir.join("model.sysml"); fs::write(&file, REFACTOR_RIG).unwrap(); @@ -2392,7 +2487,10 @@ fn refactor_extract_and_inline_round_trip_in_place() { #[test] fn refactor_dry_run_prints_the_diff_and_writes_nothing() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-refactor-dryrun"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-refactor-dryrun-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let file = dir.join("model.sysml"); fs::write(&file, REFACTOR_RIG).unwrap(); @@ -2423,7 +2521,10 @@ fn refactor_dry_run_prints_the_diff_and_writes_nothing() { #[test] fn refactor_ambient_inputs_apply_to_dry_run_only() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-refactor-ambient"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-refactor-ambient-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); fs::write(dir.join("model.sysml"), REFACTOR_RIG).unwrap(); let env = [("SYSMLV2_MODEL_DIR", dir.to_str().unwrap())]; @@ -2455,7 +2556,10 @@ fn refactor_ambient_inputs_apply_to_dry_run_only() { #[test] fn refactor_refusals_name_their_reason_and_touch_nothing() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-refactor-refuse"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-refactor-refuse-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let file = dir.join("model.sysml"); fs::write(&file, REFACTOR_RIG).unwrap(); @@ -2494,7 +2598,10 @@ fn refactor_refusals_name_their_reason_and_touch_nothing() { #[test] fn refactor_inline_reports_unused_imports_cross_file() { - let dir = std::env::temp_dir().join("sysmlv2-cli-test-refactor-imports"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-refactor-imports-{}", + std::process::id() + )); fs::create_dir_all(&dir).unwrap(); let defs = dir.join("defs.sysml"); let uses = dir.join("use.sysml"); @@ -2578,7 +2685,10 @@ fn lint_runs_generated_rules_with_sidecar_attribution() { use sysmlv2_lint::{Config, canonical_member_text, canonicalization_digest}; use sysmlv2_model::structure::{member_structure_digest, sha256_hex}; - let dir = std::env::temp_dir().join("sysmlv2-cli-test-lint-generated"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-lint-generated-{}", + std::process::id() + )); let _ = fs::remove_dir_all(&dir); fs::create_dir_all(&dir).unwrap(); @@ -2638,7 +2748,10 @@ fn lint_runs_generated_rules_with_sidecar_attribution() { // Clean fixture: silent, success. let out = sysmlv2(&["lint", paths[0], paths[1]]); assert!(out.status.success(), "{}", stderr(&out)); - assert!(!stderr(&out).contains("generated-"), "{}", stderr(&out)); + // The rule id as it is printed, not the bare prefix: the scratch + // directory's own name carries that prefix and appears in every + // location line. + assert!(!stderr(&out).contains("[generated-"), "{}", stderr(&out)); // A tampered member surfaces generated-element-modified at its // content-unit location — warn by default (exit 0), a failure @@ -2710,3 +2823,498 @@ fn lint_runs_generated_rules_with_sidecar_attribution() { ]); assert!(out.status.success(), "{}", stderr(&out)); } + +const SPLIT_RIG: &str = "package Lib { part def Thing; } +package R { + private import Lib::*; + package A { part def X; part t : Thing; } + package B { part def Y :> A::X; } + part r : A::X; +} +"; + +#[test] +fn refactor_split_dry_run_prints_the_tree_and_writes_nothing() { + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-split-dryrun-{}", + std::process::id() + )); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + let file = dir.join("model.sysml"); + fs::write(&file, SPLIT_RIG).unwrap(); + let path = file.to_str().unwrap(); + let out = sysmlv2(&["refactor", "split", path, "R", "--dry-run", "--slug"]); + assert!(out.status.success(), "{}", stderr(&out)); + let err = stderr(&out); + assert!(err.contains("model/A.sysml: `R::A`"), "{err}"); + assert!(err.contains("model/B.sysml: `R::B`"), "{err}"); + let text = stdout(&out); + assert!(text.contains("model/A.sysml (new)"), "{text}"); + assert!(text.contains("part t : Lib::Thing;"), "{text}"); + assert!(text.contains("+ public import A;"), "{text}"); + assert_eq!(fs::read_to_string(&file).unwrap(), SPLIT_RIG); + assert!(!dir.join("model").exists()); +} + +#[test] +fn refactor_split_writes_new_files_and_refuses_to_overwrite() { + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-split-write-{}", + std::process::id() + )); + let _ = fs::remove_dir_all(&dir); + fs::create_dir_all(&dir).unwrap(); + let file = dir.join("model.sysml"); + fs::write(&file, SPLIT_RIG).unwrap(); + let path = file.to_str().unwrap(); + let out_dir = dir.join("parts"); + let out = sysmlv2(&[ + "refactor", + "split", + path, + "R", + "--dir", + out_dir.to_str().unwrap(), + ]); + assert!(out.status.success(), "{}", stderr(&out)); + assert!( + stderr(&out).contains("split `R` — rewrote"), + "{}", + stderr(&out) + ); + let a = fs::read_to_string(out_dir.join("A.sysml")).unwrap(); + assert_eq!(a, "package A { part def X; part t : Lib::Thing; }\n"); + let root = fs::read_to_string(&file).unwrap(); + assert!( + root.contains(" public import A;\n public import B;\n"), + "{root}" + ); + assert!(!root.contains("package A"), "{root}"); + // The split model checks clean as three files. + let out = sysmlv2(&[ + "check", + path, + out_dir.join("A.sysml").to_str().unwrap(), + out_dir.join("B.sysml").to_str().unwrap(), + ]); + assert!(out.status.success(), "{}", stderr(&out)); + // Running again refuses: the files exist and nothing is rewritten. + fs::write(&file, SPLIT_RIG).unwrap(); + let out = sysmlv2(&[ + "refactor", + "split", + path, + "R", + "--dir", + out_dir.to_str().unwrap(), + ]); + assert!(!out.status.success()); + assert!(stderr(&out).contains("already exists"), "{}", stderr(&out)); + assert_eq!(fs::read_to_string(&file).unwrap(), SPLIT_RIG); +} + +/// `members` lists an element by the specification's `name`: a feature +/// that declares no name is listed by its naming feature — the return +/// parameter `result`, the redefined feature's name — not as anonymous. +#[test] +fn members_list_unnamed_features_by_their_effective_name() { + let dir = std::env::temp_dir().join(format!("sysmlv2-members-names-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let file = dir.join("m.sysml"); + fs::write( + &file, + "package M { + part def Car { part engine; attribute mass; } + calc def Area { in x; return : Real = x; } + part car : Car { part :>> engine; attribute :>> mass = 5; part :>> nope; } + }", + ) + .unwrap(); + let out = sysmlv2(&["members", file.to_str().unwrap(), "M::Area"]); + assert!(out.status.success(), "{}", stderr(&out)); + let text = stdout(&out); + let lines: Vec<&str> = text.lines().collect(); + assert_eq!(lines.len(), 2, "{text}"); + assert!(lines[0].starts_with("x "), "{text}"); + assert!(lines[1].starts_with("result "), "{text}"); + // A redefining feature is listed by the redefined feature's name — as + // written when the redefinition did not resolve. + let out = sysmlv2(&["members", file.to_str().unwrap(), "M::car"]); + assert!(out.status.success(), "{}", stderr(&out)); + let text = stdout(&out); + for expected in ["engine ", "mass ", "nope "] { + assert!( + text.lines().any(|l| l.starts_with(expected)), + "{expected}: {text}" + ); + } + assert!(!text.contains("anonymous"), "{text}"); + // `eval --all` labels a valued feature the same way. + let out = sysmlv2(&["eval", "--all", file.to_str().unwrap()]); + assert!(out.status.success(), "{}", stderr(&out)); + assert!(stdout(&out).contains("mass = 5"), "{}", stdout(&out)); + fs::remove_dir_all(&dir).ok(); +} + +#[test] +fn lint_format_json_writes_one_report_to_stdout() { + let dir = + std::env::temp_dir().join(format!("sysmlv2-cli-test-lint-json-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let input = dir.join("m.sysml"); + let src = "package P {\n attribute def Real;\n calc def T {\n in force : Real;\n in radius : Real;\n return t : Real = force * 2;\n }\n}\n"; + fs::write(&input, src).unwrap(); + + let out = sysmlv2(&[ + "lint", + "--format", + "json", + "--rule", + "unused-parameter=warn", + input.to_str().unwrap(), + ]); + assert!(out.status.success(), "{}", stderr(&out)); + // The report is the whole of stdout; the text tallies stay off stderr. + assert!(!stderr(&out).contains("warning(s)"), "{}", stderr(&out)); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + assert_eq!( + doc["summary"], + serde_json::json!({"errors": 0, "warnings": 1, "infos": 0, "hints": 0}) + ); + let f = &doc["findings"][0]; + assert_eq!(f["stage"], "lint"); + assert_eq!(f["rule"], "unused-parameter"); + assert_eq!(f["severity"], "warn"); + assert!(f["message"].as_str().unwrap().contains("`radius`"), "{f}"); + assert_eq!(f["unit"], 0); + assert_eq!(f["unitName"], input.display().to_string()); + assert_eq!(f["line"], 5); + assert!(f["col"].as_u64().is_some() && f["endLine"] == 5, "{f}"); + let start = usize::try_from(f["start"].as_u64().unwrap()).unwrap(); + let end = usize::try_from(f["end"].as_u64().unwrap()).unwrap(); + assert_eq!(&src[start..end], "radius", "{f}"); + assert_eq!(f["fix"]["deletes"], true); + assert_eq!( + f["fix"]["edits"][0]["unitName"], + input.display().to_string() + ); + assert_eq!( + fs::read_to_string(&input).unwrap(), + src, + "no --fix, no write" + ); + + // A configuration finding has no location: nulls, not zeros. + let out = sysmlv2(&[ + "lint", + "--format", + "json", + "--rule", + "no-such=warn", + input.to_str().unwrap(), + ]); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + let f = &doc["findings"][0]; + assert_eq!(f["rule"], "lint-config"); + assert!( + f["unit"].is_null() && f["unitName"].is_null() && f["line"].is_null(), + "{f}" + ); +} + +#[test] +fn check_format_json_reports_stages_with_the_same_exit_codes() { + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-check-json-{}", + std::process::id() + )); + fs::create_dir_all(&dir).unwrap(); + let good = dir.join("good.sysml"); + let bad = dir.join("bad.sysml"); + fs::write(&good, "package P;").unwrap(); + fs::write(&bad, "package Q { part x : ; }").unwrap(); + + let out = sysmlv2(&["check", "--format", "json", good.to_str().unwrap()]); + assert!(out.status.success(), "{}", stderr(&out)); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + assert_eq!(doc["findings"], serde_json::json!([])); + assert_eq!(doc["summary"]["errors"], 0); + + // Two inputs: the broken one is a parse-stage error located in the + // right file; the clean one still goes through the model stage. + let out = sysmlv2(&[ + "check", + "--format", + "json", + good.to_str().unwrap(), + bad.to_str().unwrap(), + ]); + assert!(!out.status.success()); + assert!(!stderr(&out).contains("error(s)"), "{}", stderr(&out)); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + let f = &doc["findings"][0]; + assert_eq!(f["stage"], "parse"); + assert_eq!(f["severity"], "error"); + assert!(f["rule"].is_null(), "{f}"); + assert_eq!(f["unit"], 1); + assert_eq!(f["unitName"], bad.display().to_string()); + assert_eq!(f["line"], 1); + assert!( + f["fix"].is_null() && f["alternatives"] == serde_json::json!([]), + "{f}" + ); + assert_eq!( + doc["summary"]["errors"], + doc["findings"].as_array().unwrap().len() + ); + + // Text mode is untouched: stderr diagnostics, empty stdout. + let out = sysmlv2(&["check", bad.to_str().unwrap()]); + assert!(stdout(&out).is_empty(), "{}", stdout(&out)); + assert!(stderr(&out).contains("error(s)"), "{}", stderr(&out)); +} + +#[test] +fn lint_format_json_locates_findings_past_a_parse_failure() { + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-test-lint-json-mixed-{}", + std::process::id() + )); + fs::create_dir_all(&dir).unwrap(); + let bad = dir.join("bad.sysml"); + let good = dir.join("good.sysml"); + fs::write(&bad, "package Q { part x : ; }").unwrap(); + let src = "package P {\n attribute def Real;\n calc def T {\n in force : Real;\n in radius : Real;\n return t : Real = force * 2;\n }\n}\n"; + fs::write(&good, src).unwrap(); + + // The broken first input never reaches the model, so the clean + // second input is model unit 0 but input 1: every location in + // the report must say input 1. + let out = sysmlv2(&[ + "lint", + "--format", + "json", + "--rule", + "unused-parameter=warn", + "--rule", + "no-such=warn", + bad.to_str().unwrap(), + good.to_str().unwrap(), + ]); + assert!(!out.status.success(), "parse errors fail the run"); + let doc: serde_json::Value = serde_json::from_str(&stdout(&out)).expect("stdout is JSON"); + let findings = doc["findings"].as_array().unwrap(); + let by_rule = |rule: &str| { + findings + .iter() + .find(|f| f["rule"] == rule) + .unwrap_or_else(|| panic!("no {rule} finding: {doc}")) + }; + let parse = findings + .iter() + .find(|f| f["stage"] == "parse") + .unwrap_or_else(|| panic!("{doc}")); + assert_eq!(parse["unit"], 0); + assert_eq!(parse["unitName"], bad.display().to_string()); + let config = by_rule("lint-config"); + assert!( + config["unit"].is_null() && config["unitName"].is_null(), + "{config}" + ); + let unused = by_rule("unused-parameter"); + assert_eq!(unused["unit"], 1); + assert_eq!(unused["unitName"], good.display().to_string()); + assert_eq!(unused["line"], 5); + let edit = &unused["fix"]["edits"][0]; + assert_eq!(edit["unit"], 1); + assert_eq!(edit["unitName"], good.display().to_string()); + let start = usize::try_from(edit["start"].as_u64().unwrap()).unwrap(); + let end = usize::try_from(edit["end"].as_u64().unwrap()).unwrap(); + assert!(src[start..end].contains("radius"), "{edit}"); + assert_eq!(doc["summary"]["errors"], 1); + assert_eq!(doc["summary"]["warnings"], 2); +} + +#[test] +fn piped_output_ends_quietly_when_the_reader_closes() { + // A reader that closes the pipe early (`sysmlv2 … | head`) must end + // the run without a panic banner: no message, exit status 0. The + // model is large enough that the writer blocks on the pipe before it + // can finish, so the closed read end is always observed — for one + // JSON document streamed to stdout, one large text dump, and one + // line-per-item listing. + use std::fmt::Write as _; + use std::io::Read as _; + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-pipe-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let model = dir.join("big.sysml"); + let mut text = String::from("package Big {\n"); + for i in 0..3000 { + writeln!(text, " part def P{i} {{ attribute a : Real = {i}; }}").unwrap(); + } + text.push_str("}\n"); + fs::write(&model, &text).unwrap(); + let model = model.to_str().unwrap(); + for args in [ + vec!["convert", model, "--to", "compact-json"], + vec!["parse", model, "--ast"], + vec!["members", model, "Big"], + ] { + let mut child = Command::new(env!("CARGO_BIN_EXE_sysmlv2")) + .env_remove("SYSMLV2_MODEL_DIR") + .env_remove("SYSMLV2_LIB_DIR") + .args(&args) + .stdout(std::process::Stdio::piped()) + .stderr(std::process::Stdio::piped()) + .spawn() + .expect("spawn"); + let mut head = [0u8; 64]; + let mut child_stdout = child.stdout.take().unwrap(); + child_stdout + .read_exact(&mut head) + .expect("some output arrives"); + drop(child_stdout); + let out = child.wait_with_output().expect("wait"); + let err = String::from_utf8_lossy(&out.stderr); + assert_eq!(out.status.code(), Some(0), "{args:?}: {err}"); + assert!(err.is_empty(), "{args:?}: {err}"); + } + fs::remove_dir_all(&dir).ok(); +} + +#[test] +fn model_extensions_are_recognized_whatever_their_case() { + // A file name's extension decides both whether an argument is a + // model source at all and which dialect it parses in, and neither + // question turns on the case it is spelled in: `K.KerML` is KerML, + // and `M.SysML` is a file rather than a name to evaluate. + let dir = std::env::temp_dir().join(format!("sysmlv2-ext-case-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let kerml = dir.join("K.KerML"); + fs::write(&kerml, "package K {\n struct S;\n}\n").unwrap(); + let sysml = dir.join("M.SysML"); + fs::write( + &sysml, + "package P {\n attribute x : ScalarValues::Integer = 3;\n}\n", + ) + .unwrap(); + + // `struct` is KerML-only, so this parses only in the KerML dialect. + let out = sysmlv2(&["check", kerml.to_str().unwrap()]); + assert!(out.status.success(), "{}", stderr(&out)); + + let out = sysmlv2(&["eval", sysml.to_str().unwrap(), "P::x"]); + assert!(out.status.success(), "{}", stderr(&out)); + assert!(stdout(&out).contains("P::x = 3"), "{}", stdout(&out)); + + // …and an archive built from such a file packs and reads back. + let archive = dir.join("p.kpar"); + let out = sysmlv2(&[ + "convert", + sysml.to_str().unwrap(), + "--to", + "kpar", + "-o", + archive.to_str().unwrap(), + ]); + assert!(out.status.success(), "{}", stderr(&out)); + let out = sysmlv2(&["convert", archive.to_str().unwrap(), "--to", "compact-json"]); + assert!(out.status.success(), "{}", stderr(&out)); + assert!(stdout(&out).contains("\"@id\""), "{}", stdout(&out)); + fs::remove_dir_all(&dir).ok(); +} + +/// Every verb parses, and the parser's bound only turns unbounded input +/// into a diagnostic on a stack that reaches the bound. Input nested to +/// it is ordinary input with nothing to report — a kilobyte and a half +/// here — and on a stack too small for it the descent ends the process: +/// no diagnostic, no unwind, no exit status worth reading. +/// +/// A process's own thread is the small stack: eight megabytes by +/// default, which an unoptimized build already overruns, and less +/// wherever the host caps it. The run is shrunk to two megabytes where +/// the shell can shrink it, so the reservation is what carries the +/// descent in either build. +#[test] +fn a_verb_parses_at_the_nesting_bound() { + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-test-deep-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let deep = dir.join("deep.sysml"); + // One level is the package, so the braces within it stop one short. + let levels = sysmlv2_parser::parser::MAX_NESTING as usize - 1; + fs::write( + &deep, + format!( + "package P {{ {}part x;{} }}\n", + "part x { ".repeat(levels), + "}".repeat(levels) + ), + ) + .unwrap(); + + let out = check_under_a_small_stack(deep.to_str().unwrap()); + assert!( + out.status.success(), + "nesting the parser accepts has nothing to report: {:?}, {}", + out.status, + stderr(&out) + ); + assert!(stderr(&out).is_empty(), "{}", stderr(&out)); + fs::remove_dir_all(&dir).ok(); +} + +#[cfg(unix)] +fn check_under_a_small_stack(file: &str) -> Output { + // `ulimit` caps the process's own thread and nothing else, so a + // reserved thread is unaffected by it — which is the point. + Command::new("/bin/sh") + .arg("-c") + .arg(r#"ulimit -s 2048 2>/dev/null; exec "$0" check "$1""#) + .arg(env!("CARGO_BIN_EXE_sysmlv2")) + .arg(file) + .env_remove("SYSMLV2_MODEL_DIR") + .env_remove("SYSMLV2_LIB_DIR") + .output() + .expect("failed to run sysmlv2") +} + +#[cfg(not(unix))] +fn check_under_a_small_stack(file: &str) -> Output { + sysmlv2(&["check", file]) +} + +/// A subprocess makes a stack-overflow regression an ordinary test +/// failure, including when nested if-nodes omit their action keyword. +#[test] +fn else_if_chains_respect_the_nesting_bound() { + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-else-if-{}", std::process::id())); + fs::create_dir_all(&dir).unwrap(); + let source = dir.join("chain.sysml"); + for prefix in ["if true {} else ", "action if true {} else "] { + for links in [32, 1000] { + fs::write( + &source, + format!("action a {{ {}{{}} }}", prefix.repeat(links)), + ) + .unwrap(); + let out = sysmlv2(&["parse", source.to_str().unwrap()]); + assert!( + out.status.code().is_some(), + "parser aborted: {}", + stderr(&out) + ); + if links == 32 { + assert!(out.status.success(), "{}", stderr(&out)); + } else { + assert!(!out.status.success()); + assert!( + stderr(&out).contains("nesting is too deep"), + "{}", + stderr(&out) + ); + } + } + } + fs::remove_dir_all(dir).unwrap(); +} diff --git a/crates/sysmlv2-cli/tests/fulljson_roundtrip.rs b/crates/sysmlv2-cli/tests/fulljson_roundtrip.rs index dc75197..16352f5 100644 --- a/crates/sysmlv2-cli/tests/fulljson_roundtrip.rs +++ b/crates/sysmlv2-cli/tests/fulljson_roundtrip.rs @@ -1,6 +1,6 @@ //! Full-form JSON → text sentinels: converting a model's *full* JSON back //! to text must print exactly what the compact-JSON path prints. Minimal -//! repros for the two 2026-07-17 lift defects — view `filter` clauses +//! repros for two lift defects — view `filter` clauses //! dropped, and positional invocation arguments re-rendered as named — //! plus the inverse guard that genuinely named arguments stay named. diff --git a/crates/sysmlv2-cli/tests/inprocess.rs b/crates/sysmlv2-cli/tests/inprocess.rs new file mode 100644 index 0000000..cba91a7 --- /dev/null +++ b/crates/sysmlv2-cli/tests/inprocess.rs @@ -0,0 +1,269 @@ +//! The command line driven in process: the shared model prologue and +//! the verbs that sit on it, called directly rather than through a +//! spawned binary, so each one's outcome is inspected as a value. + +use std::path::{Path, PathBuf}; +use std::process::ExitCode; +use sysmlv2_cli::{CliError, LoadedModel}; + +/// A scratch directory holding `files`, removed when the test ends. +struct Workspace(PathBuf); + +impl Workspace { + fn new(name: &str, files: &[(&str, &str)]) -> Workspace { + let dir = std::env::temp_dir().join(format!( + "sysmlv2-cli-inprocess-{}-{name}", + std::process::id() + )); + std::fs::create_dir_all(&dir).unwrap(); + for (file, source) in files { + std::fs::write(dir.join(file), source).unwrap(); + } + Workspace(dir) + } + + fn path(&self, file: &str) -> PathBuf { + self.0.join(file) + } + + fn inputs(&self, files: &[&str]) -> Vec { + files.iter().map(|f| self.path(f)).collect() + } +} + +impl Drop for Workspace { + fn drop(&mut self) { + std::fs::remove_dir_all(&self.0).ok(); + } +} + +/// An exit status carries no equality, so statuses are compared by the +/// only thing one shows of itself. +fn same_status(left: ExitCode, right: ExitCode) -> bool { + format!("{left:?}") == format!("{right:?}") +} + +/// The message an error carries, or `None` when it has already said +/// everything it will. +fn message(e: &CliError) -> Option { + match e { + CliError::Reported(_) => None, + CliError::Message(_) => Some(e.to_string()), + } +} + +fn load(files: Vec) -> Result { + sysmlv2_cli::load_model(files, None, true) +} + +/// The error a refused call carries. A loaded model says nothing of +/// itself, so the accepted side is dropped rather than unwrapped. +fn refusal(outcome: Result) -> CliError { + match outcome { + Ok(_) => panic!("the call was accepted"), + Err(e) => e, + } +} + +#[test] +fn the_prologue_parses_every_input_into_one_model() { + let ws = Workspace::new( + "prologue", + &[ + ("a.sysml", "package A {\n part def V;\n}\n"), + ("b.sysml", "package B {\n part def W;\n}\n"), + ], + ); + let loaded = load(ws.inputs(&["a.sysml", "b.sysml"])).expect("both files parse"); + // Without a standard library nothing precedes the inputs, and each + // one is kept with the text it was read from. + assert_eq!(loaded.boundary, 0); + assert_eq!(loaded.sources.len(), 2); + assert_eq!(loaded.sources[0].0, ws.path("a.sysml")); + assert!(loaded.sources[1].1.contains("part def W")); + + // One model: a name from either file resolves in the same view. + let mut resolved = loaded.into_resolved(); + assert!(resolved.resolve_qualified("A::V").is_some()); + assert!(resolved.resolve_qualified("B::W").is_some()); + assert!(resolved.resolve_qualified("A::W").is_none()); +} + +#[test] +fn the_prologue_reports_a_parse_failure_and_stops() { + let ws = Workspace::new("illformed", &[("bad.sysml", "package P { part def ;")]); + let e = refusal(load(ws.inputs(&["bad.sysml"]))); + // The diagnostic has already gone out against its own file, so the + // error carries only the status the run ends with. + assert_eq!(message(&e), None); +} + +#[test] +fn the_prologue_expands_a_project_archive_into_its_units() { + let ws = Workspace::new( + "archive", + &[("m.sysml", "package M {\n part def V;\n}\n")], + ); + let archive = ws.path("m.kpar"); + let status = sysmlv2_cli::run([ + "sysmlv2", + "convert", + ws.path("m.sysml").to_str().unwrap(), + "--to", + "kpar", + "-o", + archive.to_str().unwrap(), + ]); + assert!(same_status(status, ExitCode::SUCCESS)); + + let loaded = load(vec![archive.clone()]).expect("the archive's units parse"); + assert_eq!(loaded.sources.len(), 1); + assert_eq!(loaded.sources[0].0, archive.join("m.sysml")); + assert!(loaded.into_resolved().resolve_qualified("M::V").is_some()); +} + +#[test] +fn a_verb_that_cannot_resolve_its_name_says_so() { + let ws = Workspace::new( + "resolve", + &[("m.sysml", "package M {\n part def V;\n}\n")], + ); + let model = ws.path("m.sysml").display().to_string(); + + sysmlv2_cli::run_describe(Some(ws.path("m.sysml")), vec!["M::V".into()], None, true) + .expect("the element is there"); + let e = sysmlv2_cli::run_members(Some(ws.path("m.sysml")), vec!["M::Gone".into()], None, true) + .expect_err("refused"); + assert_eq!(message(&e).as_deref(), Some("cannot resolve `M::Gone`")); + + // Too many names is a refusal too, before anything is loaded. + let e = sysmlv2_cli::run_describe(None, vec![model, "A".into(), "B".into()], None, true) + .expect_err("refused"); + assert_eq!( + message(&e).as_deref(), + Some("expected exactly one qualified name, got 2") + ); +} + +#[test] +fn the_expression_verbs_refuse_an_argument_list_they_cannot_read() { + let ws = Workspace::new("args", &[("m.sysml", "package M {\n part def V;\n}\n")]); + let model = ws.path("m.sysml").display().to_string(); + + let e = sysmlv2_cli::run_query( + None, + vec![model.clone(), "1".into(), "2".into()], + None, + true, + ) + .expect_err("refused"); + assert_eq!( + message(&e).as_deref(), + Some("expected exactly one query expression, got 2") + ); + + let e = sysmlv2_cli::run_render(vec![model], None, false, true).expect_err("refused"); + assert_eq!( + message(&e).as_deref(), + Some("expected exactly one view usage name, got 0") + ); +} + +#[test] +fn eval_fails_the_run_after_reporting_every_name_it_could_not_evaluate() { + let ws = Workspace::new( + "eval", + &[( + "m.sysml", + "package M {\n attribute x : ScalarValues::Integer = 2 + 3;\n}\n", + )], + ); + sysmlv2_cli::run_eval( + Some(ws.path("m.sysml")), + vec!["M::x".into()], + false, + None, + true, + ) + .expect("the attribute evaluates"); + + let e = sysmlv2_cli::run_eval( + Some(ws.path("m.sysml")), + vec!["M::x".into(), "M::gone".into()], + false, + None, + true, + ) + .expect_err("refused"); + // Each unresolved name was reported as it was reached, so only the + // status is left to carry. + assert_eq!(message(&e), None); +} + +#[test] +fn parse_answers_for_every_file_it_was_given() { + let ws = Workspace::new( + "parse", + &[ + ("ok.sysml", "package P;\n"), + ("bad.sysml", "package P { part def ;"), + ], + ); + sysmlv2_cli::run_parse(Some(ws.path("ok.sysml")), false, true).expect("it parses"); + let e = sysmlv2_cli::run_parse(Some(ws.path("bad.sysml")), false, true).expect_err("refused"); + assert_eq!(message(&e), None); +} + +#[test] +fn the_whole_command_line_runs_in_process() { + let ws = Workspace::new( + "run", + &[( + "m.sysml", + "package M {\n part def V;\n part v : V;\n}\n", + )], + ); + let model = ws.path("m.sysml"); + let model = model.to_str().unwrap(); + assert!(same_status( + sysmlv2_cli::run(["sysmlv2", "check", model]), + ExitCode::SUCCESS + )); + assert!(same_status( + sysmlv2_cli::run(["sysmlv2", "members", model, "M"]), + ExitCode::SUCCESS + )); + // An argument list the parser refuses never reaches a verb. + assert!(same_status( + sysmlv2_cli::run(["sysmlv2", "members", model, "M", "--bogus"]), + ExitCode::from(2) + )); + // …and a file that does not exist fails the run. + assert!(same_status( + sysmlv2_cli::run([ + "sysmlv2", + "check", + &ws.path("gone.sysml").display().to_string() + ]), + ExitCode::FAILURE + )); +} + +#[test] +fn the_prologue_takes_a_standard_library_before_the_inputs() { + // The library directory is only consulted when one is named; a + // directory that is not one fails the prologue with a message. + let ws = Workspace::new("lib", &[("m.sysml", "package M;\n")]); + let e = refusal(sysmlv2_cli::load_model( + ws.inputs(&["m.sysml"]), + Some(Path::new("/nonexistent-library-directory")), + true, + )); + assert!( + message(&e) + .unwrap_or_default() + .starts_with("cannot load library /nonexistent-library-directory"), + "{:?}", + message(&e) + ); +} diff --git a/crates/sysmlv2-cli/tests/prepared_cache.rs b/crates/sysmlv2-cli/tests/prepared_cache.rs new file mode 100644 index 0000000..e36ceef --- /dev/null +++ b/crates/sysmlv2-cli/tests/prepared_cache.rs @@ -0,0 +1,86 @@ +//! Complete CLI cache lifecycle, independent of the installed library/cache. +use std::{fs, process::Command}; +#[test] +fn prepared_cli_reuses_repairs_and_invalidates_its_cache() { + let root = std::env::temp_dir().join(format!("sysml-prepared-cli-{}", uuid::Uuid::new_v4())); + let lib = root.join("library"); + let cache = root.join("cache"); + fs::create_dir_all(&lib).unwrap(); + let source = lib.join("Lib.sysml"); + let user = root.join("user.sysml"); + fs::write(&source, "package Lib { part def T; }").unwrap(); + fs::write(&user, "package U { part x : Lib::T; }").unwrap(); + let run = || { + Command::new(env!("CARGO_BIN_EXE_sysmlv2")) + .args(["check", "--lib"]) + .arg(&lib) + .arg(&user) + .env("SYSMLV2_AMBIENT", "off") + .env("SYSMLV2_CACHE_DIR", &cache) + .env_remove("SYSMLV2_LIB_CACHE") + .output() + .unwrap() + }; + let first = run(); + assert!( + first.status.success(), + "{}", + String::from_utf8_lossy(&first.stderr) + ); + let files: Vec<_> = fs::read_dir(&cache) + .unwrap() + .map(|e| e.unwrap().path()) + .collect(); + // The complete snapshot plus the resolution recording that joint + // fallback builds replay. + assert_eq!(files.len(), 2, "{files:?}"); + let path = files + .iter() + .find(|p| p.extension().unwrap() == "prepared") + .unwrap(); + assert!(files.iter().any(|p| p.extension().unwrap() == "libcache")); + let original = fs::read(path).unwrap(); + let modified = fs::metadata(path).unwrap().modified().unwrap(); + let warm = run(); + assert_eq!(first.stderr, warm.stderr); + assert!(warm.status.success()); + assert_eq!( + fs::metadata(path).unwrap().modified().unwrap(), + modified, + "warm load must not rewrite the snapshot" + ); + fs::write(path, b"damaged cache").unwrap(); + let repaired = run(); + assert_eq!(first.stderr, repaired.stderr); + assert!(repaired.status.success()); + assert!(fs::read(path).unwrap().len() > 20); + // The filename/content identity changes even when the library name stays put. + fs::write(&source, "package Lib { part def Renamed; }").unwrap(); + let changed = run(); + assert_ne!(first.stderr, changed.stderr); + assert!(String::from_utf8_lossy(&changed.stderr).contains("unresolved reference")); + assert_eq!(fs::read_dir(&cache).unwrap().count(), 4); + assert!(!original.is_empty()); + // An unwritable cache location still analyses, and says once why every + // run will be slow. + let blocked = root.join("blocked"); + fs::write(&blocked, b"not a directory").unwrap(); + let unsaved = Command::new(env!("CARGO_BIN_EXE_sysmlv2")) + .args(["check", "--lib"]) + .arg(&lib) + .arg(&user) + .env("SYSMLV2_AMBIENT", "off") + .env("SYSMLV2_CACHE_DIR", &blocked) + .env_remove("SYSMLV2_LIB_CACHE") + .output() + .unwrap(); + assert!(unsaved.status.success()); + let stderr = String::from_utf8_lossy(&unsaved.stderr); + assert_eq!( + stderr.matches("could not save the library cache").count(), + 1, + "{stderr}" + ); + assert!(stderr.contains("unresolved reference"), "{stderr}"); + fs::remove_dir_all(root).unwrap(); +} diff --git a/crates/sysmlv2-cli/tests/unit_spelling_switch.rs b/crates/sysmlv2-cli/tests/unit_spelling_switch.rs new file mode 100644 index 0000000..fd94372 --- /dev/null +++ b/crates/sysmlv2-cli/tests/unit_spelling_switch.rs @@ -0,0 +1,34 @@ +//! The spelled-unit expansion switch against repeated runs in one +//! process. +//! +//! Lives in its own test binary because the switch is process-wide: a run +//! in a neighbouring test would set it while this one reads it back. + +use std::process::ExitCode; +use sysmlv2_parser::eval::unit_spelling_expansion; + +/// The command line is a library entry point a host may call many times +/// in one process, so each run sets the switch from its own arguments: a +/// run that opts out must not decide the setting for the run after it, +/// which says nothing about spellings and therefore wants the default. +#[test] +fn each_run_sets_the_switch_from_its_own_arguments() { + let dir = std::env::temp_dir().join(format!("sysmlv2-cli-units-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("m.sysml"); + std::fs::write(&path, "package M {\n part def V;\n}\n").unwrap(); + let file = path.to_str().unwrap(); + + let status = sysmlv2_cli::run(["sysmlv2", "-q", "--no-unit-spellings", "parse", file]); + assert_eq!(format!("{status:?}"), format!("{:?}", ExitCode::SUCCESS)); + assert!(!unit_spelling_expansion(), "the run opted out"); + + let status = sysmlv2_cli::run(["sysmlv2", "-q", "parse", file]); + assert_eq!(format!("{status:?}"), format!("{:?}", ExitCode::SUCCESS)); + assert!( + unit_spelling_expansion(), + "a run saying nothing about spellings expands them" + ); + + std::fs::remove_dir_all(&dir).ok(); +} diff --git a/crates/sysmlv2-lint/Cargo.toml b/crates/sysmlv2-lint/Cargo.toml index 3a37d8c..d8b5f1d 100644 --- a/crates/sysmlv2-lint/Cargo.toml +++ b/crates/sysmlv2-lint/Cargo.toml @@ -12,8 +12,8 @@ repository.workspace = true include = ["src/**", "Cargo.toml"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } serde_json.workspace = true regex-lite.workspace = true diff --git a/crates/sysmlv2-lint/src/json.rs b/crates/sysmlv2-lint/src/json.rs new file mode 100644 index 0000000..e3e70c9 --- /dev/null +++ b/crates/sysmlv2-lint/src/json.rs @@ -0,0 +1,444 @@ +//! JSON projection of findings and diagnostics — the one report shape +//! `sysmlv2 lint --format json`, `sysmlv2 check --format json` and the +//! wasm `Session.lint` surface emit, so a consumer parses one schema +//! whichever verb produced it. +//! +//! ```text +//! { +//! "findings": [ +//! { +//! "stage": "lint" | "parse" | "context" | "referential" | "semantic", +//! "rule": "" | null, +//! "severity": "error" | "warn" | "info" | "hint", +//! "message": "…", +//! "unit": | null, "unitName": "" | null, +//! "start": , "end": , // null without a location +//! "line": …, "col": …, "endLine": …, "endCol": …, // 1-based; null without a location +//! "element": "" | null, +//! "suggest": "" | null, +//! "fix": { "label", "deletes", "semantic", +//! "edits": [ { "unit", "unitName", "start", "end", "replacement" } ] } | null, +//! "alternatives": [ , … ] +//! } +//! ], +//! "summary": { "errors", "warnings", "infos", "hints" } +//! } +//! ``` +//! +//! Findings without a location (a `lint-config` complaint) carry null +//! for `unit`, `unitName` and every position. Positions are computed +//! from the unit's source text, indexed on first use, so a report over +//! many clean units never scans them. + +use std::cell::OnceCell; +use std::collections::HashMap; + +use serde_json::{Value, json}; +use sysmlv2_syntax::span::LineIndex; +use sysmlv2_syntax::{Diagnostic, Span}; + +use crate::{Finding, Fix, Severity}; + +/// The units a report may cite, each under the index and name the +/// report spells. The lint engine numbers units its own way (library +/// units first), so a host maps every engine index a finding may +/// carry onto a reported one with [`Units::alias`] — the wasm session +/// aliases each unit to itself, the CLI aliases model units to +/// input-file indexes. An engine unit without an alias is reported +/// without a location rather than under a wrong unit. +#[derive(Default)] +pub struct Units<'a> { + units: HashMap>, + engine: HashMap, +} + +struct Unit<'a> { + name: String, + text: &'a str, + lines: OnceCell, +} + +impl<'a> Units<'a> { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// Register the unit reported as `index`, with the name the report + /// spells and the source text positions are computed from. + pub fn add(&mut self, index: usize, name: impl Into, text: &'a str) { + self.units.insert( + index, + Unit { + name: name.into(), + text, + lines: OnceCell::new(), + }, + ); + } + + /// Report engine unit `engine_unit` (a `Finding::unit` or + /// `Edit::unit`) as `index`. + pub fn alias(&mut self, engine_unit: usize, index: usize) { + self.engine.insert(engine_unit, index); + } + + fn reported(&self, engine_unit: usize) -> Option { + self.engine.get(&engine_unit).copied() + } + + fn get(&self, index: usize) -> Option<&Unit<'a>> { + self.units.get(&index) + } +} + +impl Unit<'_> { + fn lines(&self) -> &LineIndex { + self.lines.get_or_init(|| LineIndex::new(self.text)) + } +} + +/// The report's severity vocabulary — the lint config spelling. +#[derive(Clone, Copy)] +enum Sev { + Error, + Warn, + Info, + Hint, +} + +impl Sev { + fn as_str(self) -> &'static str { + match self { + Sev::Error => "error", + Sev::Warn => "warn", + Sev::Info => "info", + Sev::Hint => "hint", + } + } +} + +/// A report under construction: findings in push order plus the +/// severity tallies for `summary`. +#[derive(Default)] +pub struct Report { + findings: Vec, + errors: usize, + warnings: usize, + infos: usize, + hints: usize, +} + +impl Report { + #[must_use] + pub fn new() -> Self { + Self::default() + } + + /// Add a lint finding. Its unit and any fix-edit units are + /// translated through the table's aliases; an unaliased unit + /// leaves the location null. + pub fn push_finding(&mut self, f: &Finding, units: &Units<'_>) { + let severity = match f.severity { + Severity::Error => Sev::Error, + Severity::Info => Sev::Info, + Severity::Hint => Sev::Hint, + Severity::Warn | Severity::Off => Sev::Warn, + }; + self.tally(severity); + let unit = f.unit.and_then(|u| units.reported(u)); + let mut item = item( + "lint", + Some(f.rule.id()), + severity, + &f.message, + unit.zip(f.span), + units, + ); + item["element"] = json!(f.element); + item["suggest"] = json!(f.suggest); + item["fix"] = f.fix.as_ref().map_or(Value::Null, |fx| fix_json(fx, units)); + item["alternatives"] = Value::Array( + f.alternatives + .iter() + .map(|fx| fix_json(fx, units)) + .collect(), + ); + self.findings.push(item); + } + + /// Add a checker diagnostic from `stage` (`parse`, `context`, + /// `referential`, `semantic`) located in the unit reported as + /// `index`. No alias translation: a parse-stage diagnostic belongs + /// to a unit the engine never numbered, so the caller already + /// speaks in reported indexes, and running those through the + /// engine aliases would remap them wrongly wherever the two index + /// spaces overlap. + pub fn push_diagnostic( + &mut self, + stage: &str, + index: usize, + d: &Diagnostic, + units: &Units<'_>, + ) { + let severity = match d.severity { + sysmlv2_syntax::diag::Severity::Error => Sev::Error, + sysmlv2_syntax::diag::Severity::Warning => Sev::Warn, + }; + self.tally(severity); + let mut item = item( + stage, + None, + severity, + &d.message, + Some((index, d.span)), + units, + ); + item["element"] = Value::Null; + item["suggest"] = Value::Null; + item["fix"] = Value::Null; + item["alternatives"] = json!([]); + self.findings.push(item); + } + + /// `(errors, warnings, infos, hints)` so far. + #[must_use] + pub fn counts(&self) -> (usize, usize, usize, usize) { + (self.errors, self.warnings, self.infos, self.hints) + } + + /// The report document: `{"findings": […], "summary": {…}}`. + #[must_use] + pub fn into_value(self) -> Value { + json!({ + "findings": self.findings, + "summary": { + "errors": self.errors, + "warnings": self.warnings, + "infos": self.infos, + "hints": self.hints, + }, + }) + } + + fn tally(&mut self, severity: Sev) { + match severity { + Sev::Error => self.errors += 1, + Sev::Warn => self.warnings += 1, + Sev::Info => self.infos += 1, + Sev::Hint => self.hints += 1, + } + } +} + +/// The keys every item carries, whichever verb produced it; the +/// lint-only keys are added by the caller. +fn item( + stage: &str, + rule: Option<&str>, + severity: Sev, + message: &str, + location: Option<(usize, Span)>, + units: &Units<'_>, +) -> Value { + let unit = location.map(|(u, _)| u); + let entry = unit.and_then(|u| units.get(u)); + let (start, end) = location.map(|(_, s)| (s.start, s.end)).unzip(); + let (from, to) = location + .zip(entry) + .map(|((_, span), unit)| { + let lines = unit.lines(); + (lines.line_col(span.start), lines.line_col(span.end)) + }) + .unzip(); + json!({ + "stage": stage, + "rule": rule, + "severity": severity.as_str(), + "message": message, + "unit": unit, + "unitName": entry.map(|u| u.name.as_str()), + "start": start, + "end": end, + "line": from.map(|p| p.line), + "col": from.map(|p| p.col), + "endLine": to.map(|p| p.line), + "endCol": to.map(|p| p.col), + }) +} + +fn fix_json(fx: &Fix, units: &Units<'_>) -> Value { + let edits: Vec = fx + .edits + .iter() + .map(|e| { + let unit = units.reported(e.unit); + json!({ + "unit": unit, + "unitName": unit.and_then(|u| units.get(u)).map(|u| u.name.as_str()), + "start": e.span.start, + "end": e.span.end, + "replacement": e.replacement, + }) + }) + .collect(); + json!({ + "label": fx.label, + "deletes": fx.deletes, + "semantic": fx.semantic, + "edits": edits, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::{Edit, RuleId}; + + fn finding(unit: Option, span: Option) -> Finding { + Finding { + rule: RuleId::UnusedParameter, + severity: Severity::Warn, + message: "`radius` is never read".into(), + unit, + span, + element: Some("P::T::radius".into()), + suggest: None, + fix: Some(Fix { + label: "remove `radius`".into(), + deletes: true, + semantic: false, + edits: vec![Edit { + unit: unit.unwrap_or(0), + span: span.unwrap_or_else(|| Span::new(0, 0)), + replacement: String::new(), + }], + }), + alternatives: Vec::new(), + } + } + + #[test] + fn findings_report_positions_under_aliased_units() { + let text = "package P {\n in radius : Real;\n}\n"; + let mut units = Units::new(); + units.add(0, "m.sysml", text); + units.alias(7, 0); // engine unit 7 is the first (only) input + let mut report = Report::new(); + report.push_finding(&finding(Some(7), Some(Span::new(19, 25))), &units); + let (e, w, i, h) = report.counts(); + assert_eq!((e, w, i, h), (0, 1, 0, 0)); + let v = report.into_value(); + let f = &v["findings"][0]; + assert_eq!(f["stage"], "lint"); + assert_eq!(f["rule"], "unused-parameter"); + assert_eq!(f["severity"], "warn"); + assert_eq!(f["unit"], 0); + assert_eq!(f["unitName"], "m.sysml"); + assert_eq!( + (f["start"].as_u64(), f["end"].as_u64()), + (Some(19), Some(25)) + ); + assert_eq!((f["line"].as_u64(), f["col"].as_u64()), (Some(2), Some(8))); + assert_eq!( + (f["endLine"].as_u64(), f["endCol"].as_u64()), + (Some(2), Some(14)) + ); + assert_eq!(f["element"], "P::T::radius"); + assert_eq!(f["fix"]["deletes"], true); + assert_eq!(f["fix"]["edits"][0]["unit"], 0); + assert_eq!(f["fix"]["edits"][0]["unitName"], "m.sysml"); + assert_eq!( + v["summary"], + json!({"errors": 0, "warnings": 1, "infos": 0, "hints": 0}) + ); + } + + #[test] + fn unlocated_findings_carry_nulls_not_zeros() { + let units = Units::new(); + let mut report = Report::new(); + let mut f = finding(None, None); + f.rule = RuleId::LintConfig; + f.severity = Severity::Error; + f.fix = None; + report.push_finding(&f, &units); + let v = report.into_value(); + let f = &v["findings"][0]; + for key in [ + "unit", "unitName", "start", "end", "line", "col", "endLine", "endCol", "fix", + ] { + assert!(f[key].is_null(), "{key} should be null: {f}"); + } + assert_eq!(v["summary"]["errors"], 1); + } + + #[test] + fn unaliased_engine_units_lose_their_location_not_their_finding() { + let text = "package P;\n"; + let mut units = Units::new(); + units.add(0, "m.sysml", text); + units.alias(5, 0); + let mut report = Report::new(); + // Engine unit 2 (a library unit, say) was never aliased: the + // finding stays, its location and its edit's unit go null. + report.push_finding(&finding(Some(2), Some(Span::new(0, 4))), &units); + let v = report.into_value(); + let f = &v["findings"][0]; + assert_eq!(f["rule"], "unused-parameter"); + for key in ["unit", "unitName", "start", "end", "line", "col"] { + assert!(f[key].is_null(), "{key}: {f}"); + } + assert!(f["fix"]["edits"][0]["unit"].is_null(), "{f}"); + assert!(f["fix"]["edits"][0]["unitName"].is_null(), "{f}"); + assert_eq!(f["fix"]["edits"][0]["start"], 0); + assert_eq!(v["summary"]["warnings"], 1); + } + + #[test] + fn diagnostics_share_the_finding_shape() { + let text = "part def A {\n"; + let mut units = Units::new(); + units.add(3, "broken.sysml", text); + let mut report = Report::new(); + report.push_diagnostic( + "parse", + 3, + &Diagnostic::error(Span::new(13, 13), "expected `}`"), + &units, + ); + report.push_diagnostic( + "semantic", + 3, + &Diagnostic::warning(Span::new(0, 4), "unused"), + &units, + ); + assert_eq!(report.counts(), (1, 1, 0, 0)); + let v = report.into_value(); + let d = &v["findings"][0]; + assert_eq!(d["stage"], "parse"); + assert!(d["rule"].is_null()); + assert_eq!(d["severity"], "error"); + assert_eq!(d["unit"], 3); + assert_eq!(d["unitName"], "broken.sysml"); + assert_eq!((d["line"].as_u64(), d["col"].as_u64()), (Some(2), Some(1))); + assert_eq!(d["alternatives"], json!([])); + assert_eq!(v["findings"][1]["severity"], "warn"); + let keys: Vec = d.as_object().unwrap().keys().cloned().collect(); + let mut units = Units::new(); + units.add(0, "m.sysml", text); + units.alias(0, 0); + let mut r = Report::new(); + r.push_finding(&finding(Some(0), Some(Span::new(0, 4))), &units); + let lint_keys: Vec = r.into_value()["findings"][0] + .as_object() + .unwrap() + .keys() + .cloned() + .collect(); + assert_eq!( + keys, lint_keys, + "check and lint items must share one key set" + ); + } +} diff --git a/crates/sysmlv2-lint/src/lib.rs b/crates/sysmlv2-lint/src/lib.rs index add3973..2f2b474 100644 --- a/crates/sysmlv2-lint/src/lib.rs +++ b/crates/sysmlv2-lint/src/lib.rs @@ -34,8 +34,11 @@ //! (the declared name re-spelled in the required style) — the hooks a //! host's quick fixes key on. +pub mod json; + use regex_lite::Regex; -use std::collections::{BTreeMap, BTreeSet}; +use std::collections::{BTreeMap, BTreeSet, HashMap, HashSet}; +use std::sync::LazyLock; use sysmlv2_model::json::{ElementRef, ResolvedModel}; use sysmlv2_syntax::Span; @@ -64,6 +67,7 @@ impl Severity { } /// The config spelling ("off" | "hint" | "info" | "warn" | "error"). + #[must_use] pub fn as_str(self) -> &'static str { match self { Severity::Off => "off", @@ -89,6 +93,7 @@ pub const STYLES: &[(&str, &str)] = &[ ]; /// Style-preset names, for inventories and validation messages. +#[must_use] pub fn style_names() -> Vec<&'static str> { STYLES.iter().map(|(n, _)| *n).collect() } @@ -107,13 +112,14 @@ pub struct ScopeInfo { pub default_style: Option<&'static str>, } -/// One rule's identity and configuration surface: stable kebab-case -/// id, one-line description (doubles as UI copy), default severity, -/// the scopes its inventory advertises, the style presets its scopes -/// accept (empty = severity-only scopes), and family-level style -/// options (`(key, label, default style)`). +/// One rule's identity and configuration surface: its [`RuleId`] +/// (whose spelling is the stable kebab-case id), one-line description +/// (doubles as UI copy), default severity, the scopes its inventory +/// advertises, the style presets its scopes accept (empty = +/// severity-only scopes), and family-level style options (`(key, +/// label, default style)`). pub struct Rule { - pub id: &'static str, + pub id: RuleId, pub description: &'static str, pub default: Severity, pub scopes: &'static [ScopeInfo], @@ -149,6 +155,137 @@ pub enum OptionKind { }, } +/// Declares [`RuleId`] with the wire spelling of every variant, so the +/// enum, [`RuleId::id`] and its `FromStr` cannot drift apart. +macro_rules! rule_ids { + ($($(#[$attr:meta])* $variant:ident = $id:literal,)+) => { + /// The identity of a rule as findings and configuration carry + /// it. Every rule of [`RULES`] has a variant; `LintConfig` is + /// the pseudo-rule configuration findings report under — never + /// configurable, so [`RuleId::rule`] answers `None` for it. + /// [`RuleId::id`] (and `Display`) is the stable kebab-case + /// spelling reports and config use; `FromStr` reads it back. + /// Findings sort by that spelling, not by variant order. + #[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] + pub enum RuleId { + $($(#[$attr])* $variant,)+ + } + + impl RuleId { + /// Every id the crate knows, in declaration order. + pub const ALL: &'static [RuleId] = &[$(RuleId::$variant,)+]; + + /// The stable kebab-case id — the rule's name on the wire + /// (reports, `sysmlint.json`, diagnostic codes). + #[must_use] + pub const fn id(self) -> &'static str { + match self { + $(RuleId::$variant => $id,)+ + } + } + } + + impl std::str::FromStr for RuleId { + type Err = LintError; + + fn from_str(s: &str) -> Result { + match s { + $($id => Ok(RuleId::$variant),)+ + _ => Err(LintError::UnknownRule(s.to_string())), + } + } + } + }; +} + +rule_ids! { + NamingConvention = "naming-convention", + UndocumentedElement = "undocumented-element", + UntypedUsage = "untyped-usage", + UnusedDefinition = "unused-definition", + UnusedParameter = "unused-parameter", + ImportVisibility = "import-visibility", + VisibilityBlockedReference = "visibility-blocked-reference", + UsageKindMismatch = "usage-kind-mismatch", + PortMemberReferential = "port-member-referential", + InheritedNameShadow = "inherited-name-shadow", + UnqualifiedEnumLiteral = "unqualified-enum-literal", + UnitSpelling = "unit-spelling", + DimensionalConsistency = "dimensional-consistency", + QualifiedNames = "qualified-names", + MultilineConditions = "multiline-conditions", + Indentation = "indentation", + GeneratedProvenanceInvalid = "generated-provenance-invalid", + GeneratedProvenanceBaselineOutdated = "generated-provenance-baseline-outdated", + GeneratedElementModified = "generated-element-modified", + /// A complaint about the configuration itself, not the model. + LintConfig = "lint-config", +} + +impl RuleId { + /// The rule's inventory entry; `None` for `lint-config`, which is + /// not a configurable rule. + #[must_use] + pub fn rule(self) -> Option<&'static Rule> { + RULES.iter().find(|r| r.id == self) + } + + /// Whether the rule reports model text nothing uses (a dead + /// definition or parameter) — findings editors render faded, like + /// unused imports. + #[must_use] + pub const fn is_dead_model(self) -> bool { + matches!(self, RuleId::UnusedDefinition | RuleId::UnusedParameter) + } +} + +impl std::fmt::Display for RuleId { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + f.write_str(self.id()) + } +} + +/// Compare against a wire spelling a host handed in — a diagnostic +/// code, a `--rule` argument — without spelling `.id()` at every site. +impl PartialEq<&str> for RuleId { + fn eq(&self, other: &&str) -> bool { + self.id() == *other + } +} + +/// The failures the crate reports outside a lint pass (a pass itself +/// speaks only in findings) — what a caller may branch on. A +/// configuration whose *content* is wrong is never one of these: an +/// unknown id, option or value inside readable JSON becomes a +/// `lint-config` finding, so a host sees it beside the model's own. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum LintError { + /// No rule carries the id ([`RuleId`]'s [`FromStr`](std::str::FromStr), + /// `Config::set`). + UnknownRule(String), + /// The configuration text is not JSON at all, so no rule setting + /// in it was read ([`Config::from_json`]). + ConfigNotJson(String), + /// A member's text does not parse on its own, so it has no + /// canonical form ([`canonical_member_text`]). + UnparseableMember(String), +} + +impl std::fmt::Display for LintError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LintError::UnknownRule(id) => write!(f, "unknown lint rule `{id}`"), + LintError::ConfigNotJson(detail) => write!(f, "config is not JSON: {detail}"), + LintError::UnparseableMember(detail) => { + write!(f, "member does not parse: {detail}") + } + } + } +} + +impl std::error::Error for LintError {} + const STYLE_NAMES: &[&str] = &[ "camelCase", "PascalCase", @@ -228,7 +365,7 @@ const DEF_SCOPES: &[ScopeInfo] = &[ /// Every rule the engine knows, in documentation order. pub const RULES: &[Rule] = &[ Rule { - id: "naming-convention", + id: RuleId::NamingConvention, description: "a declared name off the project's casing conventions — definitions \ PascalCase, usages and features camelCase by default; families and \ per-stereotype scopes take a style preset or a regex (info by \ @@ -247,7 +384,7 @@ pub const RULES: &[Rule] = &[ options: NAMING_OPTIONS, }, Rule { - id: "undocumented-element", + id: RuleId::UndocumentedElement, description: "a definition without a documentation body — its own `doc` or a \ comment written `about` it; `depth` extends below the top-level \ default, scopes tune severity and depth per stereotype", @@ -258,7 +395,7 @@ pub const RULES: &[Rule] = &[ options: UNDOCUMENTED_OPTIONS, }, Rule { - id: "untyped-usage", + id: RuleId::UntypedUsage, description: "a named usage declaring no typing, subsetting, or redefinition \ clause; enumeration literals and transitions are off by default \ (scopes re-enable or silence per stereotype)", @@ -269,7 +406,7 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "unused-definition", + id: RuleId::UnusedDefinition, description: "a user definition nothing in the user model references (closed \ world: off by default — models are interchange artifacts and \ outside consumers are invisible here)", @@ -280,7 +417,7 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "unused-parameter", + id: RuleId::UnusedParameter, description: "an input parameter of a calc/constraint/action definition never \ used in its body (fix: delete the parameter); scopes toggle each \ definition context; off by default", @@ -291,7 +428,83 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "unit-spelling", + id: RuleId::ImportVisibility, + description: "an import declared without a visibility keyword (the grammar \ + requires one); the fix declares the visibility its dependents \ + need — `private` when nothing outside the importing namespace \ + resolves through it, `public` (or `protected` inside a type) \ + otherwise; the other keywords are offered as rewrites. Info by \ + default: the syntax check already reports the missing keyword \ + as an error, this finding carries the fix", + default: Severity::Info, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::VisibilityBlockedReference, + description: "an unresolved reference that names a member the resolver \ + can reach only by ignoring visibility (a chain step or \ + qualified name into a private member); the fix widens the \ + member's visibility to `public` — a rewrite, applied only on \ + request", + default: Severity::Warn, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::UsageKindMismatch, + description: "a usage typed by a definition of another kind (an `attribute` typed \ + by a port definition); the fix rewrites the usage keyword to the \ + definition's kind — a rewrite, applied only on request. Info by \ + default: the semantic check already reports the typing as an error, \ + this finding carries the fix", + default: Severity::Info, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::PortMemberReferential, + description: "a composite non-port usage inside a port body (ports own only \ + referential members); the fix inserts `ref`. Info by default: the \ + semantic check already reports the member as an error, this finding \ + carries the fix", + default: Severity::Info, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::InheritedNameShadow, + description: "a member reusing an inherited member's name without redefining it, \ + or a type inheriting one name from two places; the fix spells the \ + redefinition (`:>>`) when the member's types and multiplicity allow \ + one. Info by default: the semantic check already reports the \ + collision as a warning, this finding carries the fix", + default: Severity::Info, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::UnqualifiedEnumLiteral, + description: "an unresolved simple name that matches exactly one enumeration \ + literal in the model; the fix qualifies it", + default: Severity::Warn, + scopes: &[], + styles: &[], + families: &[], + options: &[], + }, + Rule { + id: RuleId::UnitSpelling, description: "quantity-bracket unit spellings — the same unit spelled two ways \ across the model (`'m⋅s⁻¹'` here, `m/s` there), and, with the \ `style` option (`quoted-product` | `expression`), any multi-factor \ @@ -303,7 +516,7 @@ pub const RULES: &[Rule] = &[ options: UNIT_OPTIONS, }, Rule { - id: "dimensional-consistency", + id: RuleId::DimensionalConsistency, description: "a quantity attribute whose declared type and value unit disagree \ dimensionally (`: MassValue = 9.8 [m/s^2]` — fix: re-type to the \ unit's quantity type); the `untyped` scope (warn by default) \ @@ -317,7 +530,7 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "qualified-names", + id: RuleId::QualifiedNames, description: "one element, one reference spelling — the same target written \ `MassValue` here and `ISQ::MassValue` there flags the minority \ sites (fix: re-spell to the majority form); the `style` option \ @@ -333,7 +546,7 @@ pub const RULES: &[Rule] = &[ options: QUALIFIED_OPTIONS, }, Rule { - id: "multiline-conditions", + id: RuleId::MultilineConditions, description: "a long condition chain written on one source line — chains of \ `min` or more operands (default 3) read best one condition per \ line, the connective leading each continuation, which is what \ @@ -346,7 +559,7 @@ pub const RULES: &[Rule] = &[ options: CHAIN_OPTIONS, }, Rule { - id: "indentation", + id: RuleId::Indentation, description: "leading whitespace off the project's indentation style — tabs by \ default, or a fixed number of spaces (`style` picks the character, \ `size` the columns one level takes); lines inside a verbatim \ @@ -359,7 +572,7 @@ pub const RULES: &[Rule] = &[ options: INDENT_OPTIONS, }, Rule { - id: "generated-provenance-invalid", + id: RuleId::GeneratedProvenanceInvalid, description: "corrupted transformer ownership — a Generated marker without a \ provenance record, a record whose `about` target is missing, \ multiple, unmarked, or carries the wrong key, duplicate \ @@ -375,7 +588,7 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "generated-provenance-baseline-outdated", + id: RuleId::GeneratedProvenanceBaselineOutdated, description: "a provenance record predating the structure/policy baseline \ fields — valid legacy provenance, not tamper; the next \ successful sync backfills the record without changing the \ @@ -387,7 +600,7 @@ pub const RULES: &[Rule] = &[ options: &[], }, Rule { - id: "generated-element-modified", + id: RuleId::GeneratedElementModified, description: "a generated member drifting from its provenance baseline, \ classified without consulting the data source: a changed \ canonicalization policy/schema is baseline drift the next sync \ @@ -499,10 +712,6 @@ const CHAIN_SCOPES: &[ScopeInfo] = &[ scope!("Invariant", "invariant"), ]; -fn rule(id: &str) -> Option<&'static Rule> { - RULES.iter().find(|r| r.id == id) -} - /// A compiled naming pattern with the words used to describe it in /// findings and, for presets, the style name suggestions convert to. #[derive(Clone)] @@ -600,7 +809,9 @@ impl RuleConfig { /// config and any host overrides. Unknown ids, options, and malformed /// values collect as configuration findings. pub struct Config { - rules: BTreeMap<&'static str, RuleConfig>, + /// One entry per rule of [`RULES`] — membership is what makes an + /// id configurable. + rules: BTreeMap, naming_definitions: Pattern, naming_usages: Pattern, undocumented_depth: u32, @@ -703,11 +914,12 @@ impl Config { } } - /// Parse the JSON config form. Errors are unreadable JSON only — - /// unknown ids/levels/options become findings, not errors. - pub fn from_json(text: &str) -> Result { + /// Parse the JSON config form. The only error is text that is not + /// JSON at all ([`LintError::ConfigNotJson`]) — unknown + /// ids/levels/options become findings, not errors. + pub fn from_json(text: &str) -> Result { let v: serde_json::Value = - serde_json::from_str(text).map_err(|e| format!("config is not JSON: {e}"))?; + serde_json::from_str(text).map_err(|e| LintError::ConfigNotJson(e.to_string()))?; let mut cfg = Config::default(); let Some(rules) = v.get("rules") else { return Ok(cfg); @@ -718,9 +930,16 @@ impl Config { return Ok(cfg); }; for (id, val) in rules { + let rule = match cfg.configurable(id) { + Ok(rule) => rule, + Err(e) => { + cfg.complaints.push(e.to_string()); + continue; + } + }; match val { serde_json::Value::String(s) => match Severity::parse(s) { - Some(level) => cfg.set(id, level), + Some(level) => cfg.set_level(rule, level), None => cfg.complaints.push(format!( "rule `{id}`: level must be one of {}", SEVERITIES.join(", ") @@ -729,7 +948,7 @@ impl Config { serde_json::Value::Object(o) => { if let Some(s) = o.get("severity") { match s.as_str().and_then(Severity::parse) { - Some(level) => cfg.set(id, level), + Some(level) => cfg.set_level(rule, level), None => cfg.complaints.push(format!( "rule `{id}`: severity must be one of {}", SEVERITIES.join(", ") @@ -737,7 +956,7 @@ impl Config { } } for (key, val) in o.iter().filter(|(k, _)| *k != "severity") { - cfg.set_option(id, key, val); + cfg.set_option(rule, key, val); } } _ => cfg.complaints.push(format!( @@ -749,21 +968,37 @@ impl Config { Ok(cfg) } + /// The configurable rule an id spells. `lint-config` is unknown + /// here like any other id no rule entry backs: it reports on the + /// configuration, it is not configured. + fn configurable(&self, id: &str) -> Result { + id.parse::() + .ok() + .filter(|rule| self.rules.contains_key(rule)) + .ok_or_else(|| LintError::UnknownRule(id.to_string())) + } + /// Override one rule's base severity (the CLI's `--rule id=level`). /// Unknown ids become configuration findings. pub fn set(&mut self, id: &str, level: Severity) { - match rule(id) { - Some(r) => self.rules.get_mut(r.id).expect("seeded").base = level, - None => self.complaints.push(format!("unknown lint rule `{id}`")), + match self.configurable(id) { + Ok(rule) => self.set_level(rule, level), + Err(e) => self.complaints.push(e.to_string()), + } + } + + fn set_level(&mut self, rule: RuleId, level: Severity) { + if let Some(cfg) = self.rules.get_mut(&rule) { + cfg.base = level; } } /// Apply one rule option from config. Unknown keys and malformed /// values become configuration findings; the rule keeps its /// defaults for anything that fails to parse. - fn set_option(&mut self, id: &str, key: &str, val: &serde_json::Value) { + fn set_option(&mut self, id: RuleId, key: &str, val: &serde_json::Value) { let complaint = match (id, key) { - ("naming-convention", "definitions" | "usages") => match parse_style_spec(val) { + (RuleId::NamingConvention, "definitions" | "usages") => match parse_style_spec(val) { Ok(pat) => { match key { "definitions" => self.naming_definitions = pat, @@ -773,7 +1008,7 @@ impl Config { } Err(e) => format!("rule `{id}`: option `{key}` {e}"), }, - ("unit-spelling", "style") => match val.as_str() { + (RuleId::UnitSpelling, "style") => match val.as_str() { Some("quoted-product") => { self.unit_style = Some(UnitStyle::QuotedProduct); return; @@ -786,7 +1021,7 @@ impl Config { format!("rule `{id}`: option `{key}` must be `quoted-product` or `expression`") } }, - ("qualified-names", "style") => match val.as_str() { + (RuleId::QualifiedNames, "style") => match val.as_str() { Some("qualified") => { self.qualified_style = Some(QualifiedStyle::Qualified); return; @@ -805,20 +1040,20 @@ impl Config { ) } }, - ("undocumented-element", "depth") => match val.as_u64() { + (RuleId::UndocumentedElement, "depth") => match val.as_u64() { Some(d) if d >= 1 => { - self.undocumented_depth = d.min(u32::MAX as u64) as u32; + self.undocumented_depth = u32::try_from(d).unwrap_or(u32::MAX); return; } _ => format!("rule `{id}`: option `{key}` must be a positive integer"), }, - ("multiline-conditions", "min") => match val.as_u64() { + (RuleId::MultilineConditions, "min") => match val.as_u64() { Some(0) => { self.chain_min = 0; return; } Some(n) if n >= 2 => { - self.chain_min = n.min(u8::MAX as u64) as u8; + self.chain_min = u8::try_from(n).unwrap_or(u8::MAX); return; } _ => format!( @@ -826,7 +1061,7 @@ impl Config { integer ≥ 2" ), }, - ("indentation", "style") => match val.as_str() { + (RuleId::Indentation, "style") => match val.as_str() { Some("tabs") => { self.indent_style = IndentStyle::Tabs; return; @@ -837,14 +1072,14 @@ impl Config { } _ => format!("rule `{id}`: option `{key}` must be `tabs` or `spaces`"), }, - ("indentation", "size") => match val.as_u64() { + (RuleId::Indentation, "size") => match val.as_u64() { Some(n) if n >= 1 => { - self.indent_size = n.min(u8::MAX as u64) as u8; + self.indent_size = u8::try_from(n).unwrap_or(u8::MAX); return; } _ => format!("rule `{id}`: option `{key}` must be a positive integer"), }, - (_, "scopes") if rule(id).is_some() => { + (_, "scopes") => { let Some(map) = val.as_object() else { self.complaints.push(format!( "rule `{id}`: `scopes` must be an object of metaclass → setting" @@ -864,19 +1099,21 @@ impl Config { /// One `scopes` entry: key validated against the rule's context /// shape, value = severity string, style name (styled rules), or /// an object of per-scope settings. - fn set_scope(&mut self, id: &str, key: &str, val: &serde_json::Value) { - let Some(r) = rule(id) else { return }; + fn set_scope(&mut self, id: RuleId, key: &str, val: &serde_json::Value) { + let Some(r) = id.rule() else { return }; let valid_key = r.scopes.iter().any(|s| s.key == key) || match id { - "unused-parameter" => false, // strict: the three contexts only + RuleId::UnusedParameter => false, // strict: the three contexts only // Textual rule: a line has no metaclass to scope by. - "indentation" => false, + RuleId::Indentation => false, // Aspect scopes, not metaclasses: the two inventory keys only. - "dimensional-consistency" => false, + RuleId::DimensionalConsistency => false, // Reference sites have no metaclass to scope by. - "qualified-names" => false, - "untyped-usage" => key.ends_with("Usage"), - "undocumented-element" | "unused-definition" => key.ends_with("Definition"), + RuleId::QualifiedNames => false, + RuleId::UntypedUsage => key.ends_with("Usage"), + RuleId::UndocumentedElement | RuleId::UnusedDefinition => { + key.ends_with("Definition") + } _ => key.ends_with("Definition") || key.ends_with("Usage") || key == "Feature", }; if !valid_key { @@ -929,9 +1166,9 @@ impl Config { "rule `{id}`: scope `{key}`: regex must be a string" )), }, - ("depth", v) if id == "undocumented-element" => match v.as_u64() { + ("depth", v) if id == RuleId::UndocumentedElement => match v.as_u64() { Some(d) if d >= 1 => { - setting.depth = Some(d.min(u32::MAX as u64) as u32) + setting.depth = Some(u32::try_from(d).unwrap_or(u32::MAX)) } _ => self.complaints.push(format!( "rule `{id}`: scope `{key}`: depth must be a positive integer" @@ -953,13 +1190,10 @@ impl Config { } // Overlay onto any seeded entry (a config severity flip keeps // the seeded style, and vice versa). - let entry = self - .rules - .get_mut(r.id) - .expect("seeded") - .scopes - .entry(key.to_string()) - .or_default(); + let Some(cfg) = self.rules.get_mut(&id) else { + return; + }; + let entry = cfg.scopes.entry(key.to_string()).or_default(); if setting.severity.is_some() { entry.severity = setting.severity; entry.seeded = false; @@ -972,8 +1206,13 @@ impl Config { } } - fn cfg(&self, id: &str) -> &RuleConfig { - self.rules.get(id).expect("every rule is seeded") + /// A configurable rule's effective configuration. Every rule of + /// [`RULES`] is seeded; only `lint-config`, which no pass asks + /// for, has none. + fn cfg(&self, id: RuleId) -> &RuleConfig { + self.rules + .get(&id) + .expect("every configurable rule is seeded") } } @@ -1000,6 +1239,7 @@ fn parse_style_spec(val: &serde_json::Value) -> Result { /// Re-spell `name` in a preset style: split into words on `_`, `-`, /// spaces, and lower→upper case boundaries, then recompose. `None` /// when the name yields no words. +#[must_use] pub fn convert_to_style(name: &str, style: &str) -> Option { let mut words: Vec = Vec::new(); let mut cur = String::new(); @@ -1065,6 +1305,10 @@ pub struct Edit { pub struct Fix { pub label: String, pub deletes: bool, + /// The fix changes what a declaration means (a keyword, a member's + /// visibility) rather than how it is spelled; hosts apply such fixes + /// only on explicit request, never in a fix-all sweep. + pub semantic: bool, pub edits: Vec, } @@ -1079,7 +1323,7 @@ pub struct Fix { /// applied automatically. #[derive(Clone, Debug)] pub struct Finding { - pub rule: &'static str, + pub rule: RuleId, pub severity: Severity, pub message: String, pub unit: Option, @@ -1090,7 +1334,7 @@ pub struct Finding { pub alternatives: Vec, } -fn finding(rule: &'static str, severity: Severity, message: String) -> Finding { +fn finding(rule: RuleId, severity: Severity, message: String) -> Finding { Finding { rule, severity, @@ -1150,33 +1394,51 @@ pub fn lint_units( let sources = sources.as_slice(); let mut out = Vec::new(); for c in &config.complaints { - out.push(finding("lint-config", Severity::Warn, c.clone())); + out.push(finding(RuleId::LintConfig, Severity::Warn, c.clone())); } - if config.cfg("naming-convention").enabled() { + if config.cfg(RuleId::NamingConvention).enabled() { naming_convention(resolved, config, &mut out); } - if config.cfg("undocumented-element").enabled() { + if config.cfg(RuleId::UndocumentedElement).enabled() { undocumented_element(resolved, config, &mut out); } - if config.cfg("untyped-usage").enabled() { + if config.cfg(RuleId::UntypedUsage).enabled() { untyped_usage(resolved, config, &mut out); } - if config.cfg("unused-parameter").enabled() { + if config.cfg(RuleId::UnusedParameter).enabled() { unused_parameter(resolved, config, &mut out); } - if config.cfg("unused-definition").enabled() { + if config.cfg(RuleId::UnusedDefinition).enabled() { unused_definition(resolved, config, &mut out); } - if config.cfg("unit-spelling").enabled() { + if config.cfg(RuleId::ImportVisibility).enabled() { + import_visibility(resolved, config, &mut out); + } + if config.cfg(RuleId::VisibilityBlockedReference).enabled() { + visibility_blocked_reference(resolved, config, sources, &mut out); + } + if config.cfg(RuleId::UsageKindMismatch).enabled() { + usage_kind_mismatch(resolved, config, sources, &mut out); + } + if config.cfg(RuleId::PortMemberReferential).enabled() { + port_member_referential(resolved, config, sources, &mut out); + } + if config.cfg(RuleId::InheritedNameShadow).enabled() { + inherited_name_shadow(resolved, config, sources, &mut out); + } + if config.cfg(RuleId::UnqualifiedEnumLiteral).enabled() { + unqualified_enum_literal(resolved, config, &mut out); + } + if config.cfg(RuleId::UnitSpelling).enabled() { unit_spelling(resolved, config, &mut out); } - if config.cfg("dimensional-consistency").enabled() { + if config.cfg(RuleId::DimensionalConsistency).enabled() { dimensional_consistency(resolved, config, &mut out); } - if config.cfg("qualified-names").enabled() { + if config.cfg(RuleId::QualifiedNames).enabled() { if sources.is_empty() { out.push(finding( - "lint-config", + RuleId::LintConfig, Severity::Warn, "rule `qualified-names` reads source text, which this host did not \ provide — no references were checked" @@ -1186,13 +1448,13 @@ pub fn lint_units( qualified_names(resolved, config, sources, &mut out); } } - if config.cfg("multiline-conditions").enabled() { + if config.cfg(RuleId::MultilineConditions).enabled() { multiline_conditions(resolved, config, &mut out); } - if config.cfg("indentation").enabled() { + if config.cfg(RuleId::Indentation).enabled() { if sources.is_empty() { out.push(finding( - "lint-config", + RuleId::LintConfig, Severity::Warn, "rule `indentation` reads source text, which this host did not provide — \ no lines were checked" @@ -1203,15 +1465,15 @@ pub fn lint_units( } } let generated_rules = [ - "generated-provenance-invalid", - "generated-provenance-baseline-outdated", - "generated-element-modified", + RuleId::GeneratedProvenanceInvalid, + RuleId::GeneratedProvenanceBaselineOutdated, + RuleId::GeneratedElementModified, ]; - if generated_rules.iter().any(|id| config.cfg(id).enabled()) { + if generated_rules.iter().any(|&id| config.cfg(id).enabled()) { if units.iter().any(|(_, name, _)| !name.is_empty()) { generated_guard(resolved, config, units, &mut out, None, false); - } else if generated_rules.iter().any(|id| { - let default = RULES.iter().find(|r| r.id == *id).map(|r| r.default); + } else if generated_rules.iter().any(|&id| { + let default = id.rule().map(|r| r.default); default.is_some_and(|d| config.cfg(id).base != d) }) { // Only an explicitly configured rule complains — the rules @@ -1219,7 +1481,7 @@ pub fn lint_units( // lint_with_sources) skipping defaults silently beats a // warning on every model without provenance. out.push(finding( - "lint-config", + RuleId::LintConfig, Severity::Warn, "the generated-provenance rules read unit names (the sidecar contract is \ spelled in them), which this host did not provide — no generated \ @@ -1229,10 +1491,10 @@ pub fn lint_units( } } out.sort_by(|a, b| { - (a.unit, a.span.map(|s| s.start), a.rule, &a.message).cmp(&( + (a.unit, a.span.map(|s| s.start), a.rule.id(), &a.message).cmp(&( b.unit, b.span.map(|s| s.start), - b.rule, + b.rule.id(), &b.message, )) }); @@ -1245,7 +1507,8 @@ pub fn lint_units( /// other). Only written names are checked (synthesized elements have /// no declaration site). Preset-style findings carry a `suggest`. fn naming_convention(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { - let cfg = config.cfg("naming-convention"); + let cfg = config.cfg(RuleId::NamingConvention); + let mut siblings = SiblingNames::default(); let elems: Vec = resolved.user_elements().collect(); for e in elems { let ty = resolved.element_type(e); @@ -1274,12 +1537,17 @@ fn naming_convention(resolved: &mut ResolvedModel, config: &Config, out: &mut Ve if pat.regex.is_match(&name) { continue; } + // No suggestion a sibling already carries: applying it would + // make every qualified reference to either element ambiguous + // (the edit engine drops such a rename), so the finding stays + // and the fix is left to the author. let suggest = pat .style .and_then(|style| convert_to_style(&name, style)) - .filter(|c| c != &name && pat.regex.is_match(c)); + .filter(|c| c != &name && pat.regex.is_match(c)) + .filter(|c| !siblings.carried_by_sibling(resolved, e, c)); let mut f = finding( - "naming-convention", + RuleId::NamingConvention, severity, format!("{family} name `{name}` should be {}", pat.describe), ); @@ -1291,13 +1559,57 @@ fn naming_convention(resolved: &mut ResolvedModel, config: &Config, out: &mut Ve } } +/// The names the owned members of each owner carry (effective and +/// short), indexed once per owner on first use — the clash check a +/// naming suggestion runs against its siblings, without re-reading +/// every sibling's names for every finding in one namespace. +#[derive(Default)] +struct SiblingNames { + by_owner: HashMap>>, +} + +impl SiblingNames { + /// Whether a member of `e`'s owner other than `e` carries `name` as + /// its effective or short name — the clash a rename of `e` to `name` + /// would create. + fn carried_by_sibling( + &mut self, + resolved: &mut ResolvedModel, + e: ElementRef, + name: &str, + ) -> bool { + let Some(owner) = resolved.owner(e) else { + return false; + }; + let names = self.by_owner.entry(owner).or_insert_with(|| { + let mut names: HashMap> = HashMap::new(); + for sib in resolved.owned_members(owner) { + // The names lookup finds a sibling by (declared, else the + // written naming reference), not the specification's + // effective name: a rename clashes with what resolves. + let lookup = resolved.element_lookup_name(sib); + let short = resolved + .element_declared_short_name(sib) + .map(str::to_string); + for carried in [lookup, short].into_iter().flatten() { + names.entry(carried).or_default().push(sib); + } + } + names + }); + names + .get(name) + .is_some_and(|holders| holders.iter().any(|&holder| holder != e)) + } +} + /// `undocumented-element`: definitions in scope without a /// documentation body — their own `doc` member or a comment written /// `about` them. Coverage defaults to top-level definitions; `depth` /// (rule-level or per-scope) extends into nested types, and scope /// severities tune each stereotype. fn undocumented_element(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { - let cfg = config.cfg("undocumented-element"); + let cfg = config.cfg(RuleId::UndocumentedElement); let documented: BTreeSet = resolved .annotation_notes() .into_iter() @@ -1340,7 +1652,7 @@ fn undocumented_element(resolved: &mut ResolvedModel, config: &Config, out: &mut .unwrap_or("") .to_string(); let mut f = finding( - "undocumented-element", + RuleId::UndocumentedElement, severity, format!("`{name}` has no documentation body (`doc /* … */`)"), ); @@ -1357,7 +1669,7 @@ fn undocumented_element(resolved: &mut ResolvedModel, config: &Config, out: &mut /// through the specialization). Enumeration literals and transitions /// are off by default; scopes tune every stereotype. fn untyped_usage(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { - let cfg = config.cfg("untyped-usage"); + let cfg = config.cfg(RuleId::UntypedUsage); let elems: Vec = resolved.user_elements().collect(); for e in elems { let ty = resolved.element_type(e); @@ -1378,7 +1690,7 @@ fn untyped_usage(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { + let severity = config.cfg(RuleId::ImportVisibility).severity("Import"); + if severity == Severity::Off { + return; + } + for (import, _, _) in resolved.imports_without_visibility() { + let Some(advice) = resolved.import_visibility_advice(import) else { + continue; + }; + let namespace = advice + .namespace + .as_deref() + .map(|n| format!("`{n}`")) + .unwrap_or_else(|| "the root namespace".to_string()); + let message = match advice.recommended { + "private" => format!( + "import declares no visibility; `private` suffices — nothing outside \ + {namespace} resolves through it" + ), + keyword => format!( + "import declares no visibility; `{keyword}` is required — {} reference(s) \ + outside {namespace} resolve through it", + advice.outside_sites.len() + ), + }; + let declare = |keyword: &str, semantic: bool| Fix { + label: format!("Make the import `{keyword}`"), + deletes: false, + semantic, + edits: vec![Edit { + unit: advice.unit, + span: Span { + start: advice.span.start, + end: advice.span.start, + }, + replacement: format!("{keyword} "), + }], + }; + let mut f = finding(RuleId::ImportVisibility, severity, message); + f.unit = Some(advice.unit); + f.span = Some(advice.span); + f.element = edit_target(resolved, import); + f.suggest = Some(advice.recommended.to_string()); + f.fix = Some(declare(advice.recommended, false)); + f.alternatives = ["private", "protected", "public"] + .into_iter() + .filter(|k| *k != advice.recommended) + .map(|k| declare(k, true)) + .collect(); + out.push(f); + } +} + +/// `visibility-blocked-reference`: an unresolved reference whose name +/// exists in the searched scope under a visibility it cannot see (see +/// `ResolvedModel::blocked_references`). The fix rewrites the member's +/// visibility keyword to `public`; `protected` is the alternative when +/// the reference reaches the member through a specialization. Both are +/// semantic. Source text is needed to find the keyword; without it the +/// finding stands with no fix. +fn visibility_blocked_reference( + resolved: &mut ResolvedModel, + config: &Config, + sources: &[(usize, &str)], + out: &mut Vec, +) { + let severity = config.cfg(RuleId::VisibilityBlockedReference).base; + if severity == Severity::Off { + return; + } + let text_of = |unit: usize| sources.iter().find(|(i, _)| *i == unit).map(|(_, t)| *t); + for b in resolved.blocked_references() { + let member = resolved + .element_qualified_name(b.member) + .unwrap_or_else(|| b.name.to_display_string()); + let mut f = finding( + RuleId::VisibilityBlockedReference, + severity, + format!( + "`{}` does not resolve — `{member}` exists but is {}", + b.spelling, b.visibility + ), + ); + f.unit = Some(b.unit); + f.span = Some(b.name.span); + f.element = edit_target(resolved, b.member); + // The keyword sits at the start of the member's extent. + let keyword = resolved.member_extent(b.member).and_then(|(unit, span)| { + let text = text_of(unit)?; + let rest = text.get(span.start as usize..)?; + rest.starts_with(b.visibility) + .then(|| (unit, span.start, span.start + b.visibility.len() as u32)) + }); + if let Some((unit, start, end)) = keyword { + let widen = |keyword: &str| Fix { + label: format!("make `{member}` {keyword}"), + deletes: false, + semantic: true, + edits: vec![Edit { + unit, + span: Span { start, end }, + replacement: keyword.to_string(), + }], + }; + f.suggest = Some("public".to_string()); + f.fix = Some(widen("public")); + if b.protected_suffices { + f.alternatives = vec![widen("protected")]; + } + } + out.push(f); + } +} + +/// The declaration keyword of a usage metaclass, as spelled in source. +fn usage_keyword(metaclass: &str) -> Option<&'static str> { + Some(match metaclass { + "AttributeUsage" => "attribute", + "PartUsage" => "part", + "ItemUsage" => "item", + "PortUsage" => "port", + "ActionUsage" => "action", + "StateUsage" => "state", + "ConstraintUsage" => "constraint", + "RequirementUsage" => "requirement", + "CalculationUsage" => "calc", + "ConnectionUsage" => "connection", + "InterfaceUsage" => "interface", + "OccurrenceUsage" => "occurrence", + "EnumerationUsage" => "enum", + "ViewUsage" => "view", + "ViewpointUsage" => "viewpoint", + "RenderingUsage" => "rendering", + "ConcernUsage" => "concern", + "CaseUsage" => "case", + "AnalysisCaseUsage" => "analysis", + "VerificationCaseUsage" => "verification", + "UseCaseUsage" => "use case", + "AllocationUsage" => "allocation", + "FlowUsage" => "flow", + "MetadataUsage" => "metadata", + _ => return None, + }) +} + +/// The usage keyword a definition metaclass belongs to, by the most +/// specific definition kind it conforms to (a requirement definition is +/// also a constraint definition; the specific kind wins). +fn definition_usage_keyword(metaclass: &str) -> Option<&'static str> { + use sysmlv2_model::check::metaclass_conforms as conforms; + for (def, keyword) in [ + ("ViewpointDefinition", "viewpoint"), + ("ConcernDefinition", "concern"), + ("RequirementDefinition", "requirement"), + ("ConstraintDefinition", "constraint"), + ("UseCaseDefinition", "use case"), + ("AnalysisCaseDefinition", "analysis"), + ("VerificationCaseDefinition", "verification"), + ("CaseDefinition", "case"), + ("CalculationDefinition", "calc"), + ("StateDefinition", "state"), + ("FlowDefinition", "flow"), + ("InterfaceDefinition", "interface"), + ("AllocationDefinition", "allocation"), + ("ConnectionDefinition", "connection"), + ("ViewDefinition", "view"), + ("RenderingDefinition", "rendering"), + ("ActionDefinition", "action"), + ("PartDefinition", "part"), + ("MetadataDefinition", "metadata"), + ("ItemDefinition", "item"), + ("PortDefinition", "port"), + ("OccurrenceDefinition", "occurrence"), + ("EnumerationDefinition", "attribute"), + ("AttributeDefinition", "attribute"), + ] { + if conforms(metaclass, def) { + return Some(keyword); + } + } + None +} + +/// Byte span of `keyword` as a whole word inside `text[start..end]`. +fn keyword_span(text: &str, start: u32, end: u32, keyword: &str) -> Option { + let head = text.get(start as usize..end as usize)?; + let mut from = 0; + while let Some(i) = head[from..].find(keyword) { + let at = from + i; + let word = |c: char| c.is_alphanumeric() || c == '_' || c == '\''; + let before_ok = at == 0 || !head[..at].chars().next_back().is_some_and(word); + let after_ok = !head[at + keyword.len()..].chars().next().is_some_and(word); + if before_ok && after_ok { + let s = start + at as u32; + return Some(Span { + start: s, + end: s + keyword.len() as u32, + }); + } + from = at + keyword.len(); + } + None +} + +/// The usage keyword token of `e`'s declaration in its unit's text: the +/// member extent up to the declared name (or the whole extent when +/// unnamed) is scanned for the keyword its metaclass spells. +fn usage_keyword_span( + resolved: &ResolvedModel, + e: ElementRef, + text: &str, +) -> Option<(Span, &'static str)> { + let keyword = usage_keyword(resolved.element_type(e))?; + let (_, extent) = resolved.member_extent(e)?; + let end = resolved + .declaration_site(e) + .map_or(extent.end, |(_, name)| name.start); + Some((keyword_span(text, extent.start, end, keyword)?, keyword)) +} + +/// Where `ref` goes in a member whose usage keyword starts at +/// `keyword_start`: before an `individual`, `snapshot` or `timeslice` +/// prefix or a `#` metadata prefix when one precedes the keyword (the +/// grammar reads `ref` first), else immediately before the keyword. +fn ref_insertion_point(text: &str, extent_start: u32, keyword_start: u32) -> u32 { + let mut at = keyword_start; + for prefix in ["individual", "snapshot", "timeslice"] { + if let Some(span) = keyword_span(text, extent_start, at, prefix) { + at = at.min(span.start); + } + } + if let Some(head) = text.get(extent_start as usize..at as usize) { + if let Some(i) = head.find('#') { + at = at.min(extent_start + i as u32); + } + } + at +} + +/// `usage-kind-mismatch`: the pairs the semantic check reports as `X must +/// be typed by Y`, with a semantic fix rewriting the usage keyword to the +/// definition's kind where that kind is known. +fn usage_kind_mismatch( + resolved: &mut ResolvedModel, + config: &Config, + sources: &[(usize, &str)], + out: &mut Vec, +) { + let severity = config.cfg(RuleId::UsageKindMismatch).base; + if severity == Severity::Off { + return; + } + let text_of = |unit: usize| sources.iter().find(|(i, _)| *i == unit).map(|(_, t)| *t); + for pair in sysmlv2_model::check::incompatible_typings(resolved) { + let usage_ty = resolved.element_type(pair.usage); + let target_ty = resolved.element_type(pair.target); + let target = resolved + .element_qualified_name(pair.target) + .unwrap_or_else(|| target_ty.to_string()); + let mut f = finding( + RuleId::UsageKindMismatch, + severity, + format!( + "{usage_ty} must be typed by {}; `{target}` is a {target_ty}", + pair.allowed + ), + ); + f.unit = Some(pair.unit); + f.span = Some(pair.span); + f.element = edit_target(resolved, pair.usage); + // An enumeration body holds only literals: no keyword to rewrite. + let in_enum = resolved + .owner(pair.usage) + .is_some_and(|o| resolved.element_type(o) == "EnumerationDefinition"); + let wanted = definition_usage_keyword(target_ty) + .filter(|k| Some(*k) != usage_keyword(usage_ty) && !in_enum); + if let (Some(wanted), Some(text)) = (wanted, text_of(pair.unit)) { + if let Some((span, current)) = usage_keyword_span(resolved, pair.usage, text) { + f.suggest = Some(wanted.to_string()); + f.fix = Some(Fix { + label: format!("change `{current}` to `{wanted}`"), + deletes: false, + semantic: true, + edits: vec![Edit { + unit: pair.unit, + span, + replacement: wanted.to_string(), + }], + }); + } + } + out.push(f); + } +} + +/// `port-member-referential`: a composite non-port usage owned by a port +/// definition or usage, with a fix inserting `ref` before its keyword. +fn port_member_referential( + resolved: &mut ResolvedModel, + config: &Config, + sources: &[(usize, &str)], + out: &mut Vec, +) { + let severity = config.cfg(RuleId::PortMemberReferential).base; + if severity == Severity::Off { + return; + } + let text_of = |unit: usize| sources.iter().find(|(i, _)| *i == unit).map(|(_, t)| *t); + let elems: Vec = resolved.user_elements().collect(); + for e in elems { + let ty = resolved.element_type(e); + if !sysmlv2_model::check::metaclass_conforms(ty, "Usage") + || ty == "PortUsage" + || resolved.is_composite(e) != Some(true) + { + continue; + } + let Some(owner) = resolved.owner(e) else { + continue; + }; + if !matches!(resolved.element_type(owner), "PortDefinition" | "PortUsage") { + continue; + } + let Some((unit, span)) = resolved + .declaration_site(e) + .or_else(|| resolved.member_extent(e)) + else { + continue; + }; + // The specification's name, else the written one: a usage named + // only through what it redefines is reported by that name — even + // when the redefinition did not resolve — rather than as "the + // usage". + let name = resolved + .element_effective_name(e) + .or_else(|| resolved.element_lookup_name(e)) + .map(|n| format!("`{n}`")) + .unwrap_or_else(|| "the usage".to_string()); + let mut f = finding( + RuleId::PortMemberReferential, + severity, + format!( + "{name} is a composite {ty} owned by a port; a port's non-port members must be referential" + ), + ); + f.unit = Some(unit); + f.span = Some(span); + f.element = edit_target(resolved, e); + if let Some(text) = text_of(unit) { + if let Some((kw, _)) = usage_keyword_span(resolved, e, text) { + let at = resolved.member_extent(e).map_or(kw.start, |(_, extent)| { + ref_insertion_point(text, extent.start, kw.start) + }); + f.fix = Some(Fix { + label: "make it referential (`ref`)".to_string(), + deletes: false, + semantic: false, + edits: vec![Edit { + unit, + span: Span { start: at, end: at }, + replacement: "ref ".to_string(), + }], + }); + } + } + out.push(f); + } +} + +/// `inherited-name-shadow`: the semantic check's inherited-name collisions +/// (`validateNamespaceDistinguishibility`), with a fix spelling the +/// redefinition for an owned member that may redefine the member it +/// hides (the collision carries the target spelling only then): +/// `attribute x : T` becomes `attribute :>> x : T` when the hidden member's +/// own name is the declared name and no short name is spelled; any other +/// identification (`attribute other : T`, `attribute : T`) gets +/// ` :>> target` right after it, keeping the declared name. +fn inherited_name_shadow( + resolved: &mut ResolvedModel, + config: &Config, + sources: &[(usize, &str)], + out: &mut Vec, +) { + let severity = config.cfg(RuleId::InheritedNameShadow).base; + if severity == Severity::Off { + return; + } + let text_of = |unit: usize| sources.iter().find(|(i, _)| *i == unit).map(|(_, t)| *t); + for c in sysmlv2_model::check::inherited_name_collisions(resolved) { + if resolved.is_library_element(c.element) { + continue; + } + let mut f = finding(RuleId::InheritedNameShadow, severity, c.message.clone()); + f.unit = Some(c.unit); + f.span = Some(c.span); + f.element = edit_target(resolved, c.element); + if let (Some(hidden), Some(target), Some(text)) = + (c.hidden, c.redefinition_target.as_deref(), text_of(c.unit)) + { + let declared = resolved.element_name(c.element).map(str::to_string); + let short = resolved + .element_declared_short_name(c.element) + .map(str::to_string); + let hidden_name = resolved.element_name(hidden).map(str::to_string); + let edit = if declared.is_some() && short.is_none() && hidden_name == declared { + Some((c.span, format!(":>> {target}"))) + } else if declared.is_some() { + Some(( + Span { + start: c.span.end, + end: c.span.end, + }, + format!(" :>> {target}"), + )) + } else { + // Only a short name: the span is the token inside `<…>`; + // the redefinition follows the closing bracket. + text.get(c.span.end as usize..) + .and_then(|rest| rest.find('>')) + .map(|i| { + let at = c.span.end + i as u32 + 1; + (Span { start: at, end: at }, format!(" :>> {target}")) + }) + }; + if let Some((span, replacement)) = edit { + f.suggest = Some(format!(":>> {target}")); + f.fix = Some(Fix { + label: format!("redefine the inherited `{}` (`:>>`)", c.name), + deletes: false, + semantic: true, + edits: vec![Edit { + unit: c.unit, + span, + replacement, + }], + }); + } + } + out.push(f); + } +} + +/// `unqualified-enum-literal`: an unresolved simple name matching exactly +/// one enumeration literal in the model, with a fix qualifying it. +fn unqualified_enum_literal(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { + let severity = config.cfg(RuleId::UnqualifiedEnumLiteral).base; + if severity == Severity::Off { + return; + } + let literals = resolved.elements_of_metaclass("EnumerationUsage"); + if literals.is_empty() { + return; + } + // Literal → its escaped name, user literals first: a user literal + // wins over a library one of the same name, and a library literal is + // offered only when no user literal matches. + let spelled: Vec<(ElementRef, String, bool)> = literals + .iter() + .filter_map(|&l| { + let name = resolved.element_name(l)?; + Some(( + l, + sysmlv2_syntax::ast::escape_name(name), + resolved.is_library_element(l), + )) + }) + .collect(); + for r in resolved.unresolved_references() { + if resolved.is_library_element(r.owner) + || r.spelling.contains("::") + || r.spelling.contains('.') + { + continue; + } + let matching: Vec = spelled + .iter() + .filter(|(_, name, _)| *name == r.spelling) + .map(|(l, _, _)| *l) + .collect(); + let user: Vec = matching + .iter() + .copied() + .filter(|l| !resolved.is_library_element(*l)) + .collect(); + let [literal] = (if user.is_empty() { + &matching[..] + } else { + &user[..] + }) else { + continue; + }; + let literal = *literal; + let name = r.spelling.clone(); + let Some(qualified) = resolved.element_qualified_name(literal) else { + continue; + }; + let Some(spelling) = resolved.element_reference_spelling(literal) else { + continue; + }; + let mut f = finding( + RuleId::UnqualifiedEnumLiteral, + severity, + format!( + "`{name}` does not resolve here; the enumeration literal `{qualified}` matches" + ), + ); + f.unit = Some(r.unit); + f.span = Some(r.span); + f.element = edit_target(resolved, literal); + f.suggest = Some(qualified.clone()); + f.fix = Some(Fix { + label: format!("qualify as `{qualified}`"), + deletes: false, + semantic: false, + edits: vec![Edit { + unit: r.unit, + span: r.span, + replacement: spelling, + }], + }); + out.push(f); + } +} + /// `unused-parameter`: an `in`/`inout` parameter of a callable user /// definition with no reference inside the definition's own body, /// per-context configurable (calc / constraint / action defs). The @@ -1419,7 +2260,16 @@ fn untyped_usage(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { - let cfg = config.cfg("unused-parameter"); + let cfg = config.cfg(RuleId::UnusedParameter); + // Reference sites by target, indexed once: `(unit, name span)` is + // all the in-body test reads. + let mut sites_by_target: HashMap> = HashMap::new(); + for s in resolved.reference_sites() { + sites_by_target + .entry(s.target) + .or_default() + .push((s.unit, s.name_span)); + } for scope in UNUSED_PARAM_SCOPES { let severity = cfg.severity(scope.key); if severity == Severity::Off { @@ -1441,10 +2291,10 @@ fn unused_parameter(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec { continue; } - let sites = resolved.references_to(p); - let used_in_body = sites.iter().any(|s| { + let sites = sites_by_target.get(&p).map_or(&[][..], Vec::as_slice); + let used_in_body = sites.iter().any(|&(unit, name_span)| { extent.is_some_and(|(u, sp)| { - s.unit == u && sp.start <= s.name_span.start && s.name_span.end <= sp.end + unit == u && sp.start <= name_span.start && name_span.end <= sp.end }) }); if used_in_body { @@ -1453,11 +2303,15 @@ fn unused_parameter(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec let Some((unit, span)) = resolved.declaration_site(p) else { continue; }; - let name = resolved.element_name(p).unwrap_or("_").to_string(); + let name = resolved + .element_effective_name(p) + .or_else(|| resolved.element_lookup_name(p)) + .unwrap_or_else(|| "_".to_string()); let (message, fix) = if sites.is_empty() { let fix = resolved.member_extent(p).map(|(u, sp)| Fix { label: format!("delete unused parameter `{name}`"), deletes: true, + semantic: false, edits: vec![Edit { unit: u, span: sp, @@ -1477,7 +2331,7 @@ fn unused_parameter(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec None, ) }; - let mut f = finding("unused-parameter", severity, message); + let mut f = finding(RuleId::UnusedParameter, severity, message); f.unit = Some(unit); f.span = Some(span); f.element = edit_target(resolved, p); @@ -1649,7 +2503,7 @@ fn spell_expression(factors: &[(String, i32)]) -> Option { fn unit_spelling(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { use sysmlv2_syntax::ast::{Expr, ExprKind}; use sysmlv2_syntax::visit::{Visit, walk_expr}; - let cfg = config.cfg("unit-spelling"); + let cfg = config.cfg(RuleId::UnitSpelling); struct Brackets<'a> { args: Vec<&'a Expr>, @@ -1750,7 +2604,7 @@ fn unit_spelling(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec ("a unit expression", "m/s"), }; let mut f = finding( - "unit-spelling", + RuleId::UnitSpelling, severity, format!( "unit spelled `{}` — this project spells compound units as {want_name} \ @@ -1821,6 +2676,7 @@ fn unit_spelling(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec Vec { use sysmlv2_model::eval::Value; let Some((scope, expr)) = resolved.value_expr(e) else { @@ -1850,6 +2712,9 @@ fn inferred_type_spellings(resolved: &mut ResolvedModel, e: ElementRef) -> Vec = Vec::new(); + // The wider numeric type an integral inference falls back to when + // a dependent value is not integral. + let mut fallback: Option = None; match &value { Value::Quantity(_, u) => { if let Some(unit_elem) = bracket_unit_ref(resolved, scope, &expr) { @@ -1861,25 +2726,119 @@ fn inferred_type_spellings(resolved: &mut ResolvedModel, e: ElementRef) -> Vec { + let real = resolved.resolve_qualified("ScalarValues::Real"); + if spells_real_literal(&expr) { + // `0.0` evaluates to an exact integer, but the author + // wrote a real. + targets.extend(real); + } else { + targets.extend(resolved.scalar_literal_type(&value)); + fallback = real; + } + } + v => targets.extend(resolved.scalar_literal_type(v)), + } + let dependents = dependent_values(resolved, e); + let admitted = |resolved: &mut ResolvedModel, t: ElementRef| { + dependents.iter().all(|(others, v)| { + let mut declared = others.clone(); + declared.push(t); + resolved.scalar_value_admitted(&declared, v) != Some(false) + }) + }; + let mut kept: Vec = Vec::new(); + for t in targets { + if admitted(resolved, t) { + kept.push(t); + } + } + if kept.is_empty() { + if let Some(t) = fallback.filter(|&t| admitted(resolved, t)) { + kept.push(t); + } + } + // Spelled for the unit the suggestion is written into. + let dialect = resolved + .declaration_site(e) + .and_then(|(unit, _)| resolved.unit_dialect(unit)); + let mut spellings: Vec = Vec::new(); + for t in kept { + if let Some(s) = resolved.type_spelling_at(dialect, scope, t) { + if !spellings.contains(&s) { + spellings.push(s); + } + } + } + spellings +} + +/// The values a typing written on `e` must admit, each with the other +/// declared types the check weighs alongside it: `e`'s own value +/// (nothing else declared — the fix writes `e`'s single typing), and +/// the value of every untyped feature redefining `e`, which borrows +/// the declared types of all its redefinition targets (`e`'s new +/// typing among them). Unevaluable values are skipped: the check +/// stays silent on them too. +fn dependent_values( + resolved: &mut ResolvedModel, + e: ElementRef, +) -> Vec<(Vec, sysmlv2_model::eval::Value)> { + let mut out = Vec::new(); + if let Ok(v) = resolved.evaluate(e) { + out.push((Vec::new(), v)); + } + for r in resolved.redefiners(e) { + if resolved.value_expr(r).is_none() || !resolved.typings(r).is_empty() { + continue; + } + let Ok(v) = resolved.evaluate(r) else { + continue; + }; + let mut others: Vec = Vec::new(); + for t in resolved.redefinition_targets(r) { + if t == e { + continue; + } + for ty in resolved.typings(t) { + if !others.contains(&ty) { + others.push(ty); } } } - v => targets.extend(resolved.scalar_literal_type(v)), + out.push((others, v)); } - let mut spellings: Vec = Vec::new(); - for t in targets { - if let Some(s) = resolved.type_spelling_at(scope, t) { - if !spellings.contains(&s) { - spellings.push(s); + out +} + +/// Whether the expression is written with a real literal anywhere +/// (`0.0`, `1e3`, `1/4000.0`) — the author's spelling of a number +/// that may still evaluate to an exact integer. +fn spells_real_literal(expr: &sysmlv2_syntax::ast::Expr) -> bool { + use sysmlv2_syntax::ast::{Expr, ExprKind, Literal}; + use sysmlv2_syntax::visit::{Visit, walk_expr}; + struct Finder(bool); + impl<'a> Visit<'a> for Finder { + fn visit_expr(&mut self, e: &'a Expr) { + if matches!(&e.kind, ExprKind::Literal(Literal::Real(_))) { + self.0 = true; + } + if !self.0 { + walk_expr(self, e); } } } - spellings + let mut v = Finder(false); + v.visit_expr(expr); + v.0 } /// The written unit reference of the value's first quantity bracket — @@ -1941,7 +2900,7 @@ fn alternates_clause(spellings: &[String]) -> String { /// unevaluable value stays silent, never a guess. fn dimensional_consistency(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { use sysmlv2_model::eval::Value; - let cfg = config.cfg("dimensional-consistency"); + let cfg = config.cfg(RuleId::DimensionalConsistency); let mismatch_sev = cfg.severity("mismatch"); // The untyped aspect's inventory default is warn — seeded, so it // holds while the rule is on and dies under `"off"`. @@ -1974,6 +2933,7 @@ fn dimensional_consistency(resolved: &mut ResolvedModel, config: &Config, out: & let declare = |s: &String| Fix { label: format!("declare the type `{s}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: unit_idx, span: Span { @@ -1984,7 +2944,7 @@ fn dimensional_consistency(resolved: &mut ResolvedModel, config: &Config, out: & }], }; let mut f = finding( - "dimensional-consistency", + RuleId::DimensionalConsistency, untyped_sev, format!( "attribute `{name}` declares no type — its value infers `{first}`{}", @@ -2048,6 +3008,7 @@ fn dimensional_consistency(resolved: &mut ResolvedModel, config: &Config, out: & let retype = |s: &String| Fix { label: format!("re-type as `{s}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: anchor_unit, span: anchor_span, @@ -2055,7 +3016,7 @@ fn dimensional_consistency(resolved: &mut ResolvedModel, config: &Config, out: & }], }; let mut f = finding( - "dimensional-consistency", + RuleId::DimensionalConsistency, mismatch_sev, format!( "attribute `{name}` is typed `{ty_name}` (dimension {}) but its value's \ @@ -2160,7 +3121,7 @@ fn split_spelling(text: &str) -> Option> { /// no import to anchor on (the finding then carries no fix — /// inventing a position inside an arbitrary namespace body is how a /// fix breaks a model). -fn import_anchor(resolved: &mut ResolvedModel, unit: usize, text: &str) -> Option<(u32, String)> { +fn import_anchor(resolved: &ResolvedModel, unit: usize, text: &str) -> Option<(u32, String)> { let last = resolved .reference_sites() .iter() @@ -2200,7 +3161,7 @@ fn qualified_names( sources: &[(usize, &str)], out: &mut Vec, ) { - let severity = config.cfg("qualified-names").base; + let severity = config.cfg(RuleId::QualifiedNames).base; let text_of = |unit: usize| sources.iter().find(|(i, _)| *i == unit).map(|(_, t)| *t); let user_units: BTreeSet = { let elems: Vec = resolved.user_elements().collect(); @@ -2250,7 +3211,7 @@ fn qualified_names( message: String, fix: Option, suggest: String| { - let mut f = finding("qualified-names", severity, message); + let mut f = finding(RuleId::QualifiedNames, severity, message); f.unit = Some(site.unit); f.span = Some(site.span); f.element = edit_target(resolved, site.target); @@ -2302,10 +3263,12 @@ fn qualified_names( if !adoptable { continue; } + // The specification's name, else the written one (a target + // reached by a written name is never anonymous here). let name = resolved - .element_name(target) - .unwrap_or("") - .to_string(); + .element_effective_name(target) + .or_else(|| resolved.element_lookup_name(target)) + .unwrap_or_else(|| "".to_string()); push( resolved, site, @@ -2317,6 +3280,7 @@ fn qualified_names( Some(Fix { label: format!("re-spell as `{majority}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: site.unit, span: site.span, @@ -2333,7 +3297,9 @@ fn qualified_names( for site in &sites { match style { QualifiedStyle::Qualified => { - let Some(full) = resolved.full_spelling(site.target) else { + let Some(full) = + resolved.full_spelling(resolved.unit_dialect(site.unit), site.target) + else { continue; }; if site.written == full { @@ -2345,6 +3311,7 @@ fn qualified_names( let fix = ok.then(|| Fix { label: format!("qualify as `{full}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: site.unit, span: site.span, @@ -2363,9 +3330,12 @@ fn qualified_names( ); } QualifiedStyle::Minimal => { - let Some(minimal) = - resolved.reference_spelling_at(site.scope, site.exclude, site.target) - else { + let Some(minimal) = resolved.reference_spelling_at( + resolved.unit_dialect(site.unit), + site.scope, + site.exclude, + site.target, + ) else { continue; }; if site.written == minimal || minimal.len() >= site.written.len() { @@ -2382,6 +3352,7 @@ fn qualified_names( Some(Fix { label: format!("re-spell as `{minimal}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: site.unit, span: site.span, @@ -2395,7 +3366,12 @@ fn qualified_names( let Some(name) = resolved.element_name(site.target).map(str::to_string) else { continue; }; - let simple = sysmlv2_syntax::ast::escape_name(&name); + // Replacement text is source for this unit: a reserved + // word of its dialect must stay quoted or the fix would + // not parse, and a word the dialect does not reserve + // stays bare so the formatter agrees with the fix. + let simple = + sysmlv2_syntax::name::spell_name_in(resolved.unit_dialect(site.unit), &name); if site.written == simple { continue; } @@ -2413,6 +3389,7 @@ fn qualified_names( Some(Fix { label: format!("re-spell as `{simple}`"), deletes: false, + semantic: false, edits: vec![Edit { unit: site.unit, span: site.span, @@ -2431,13 +3408,16 @@ fn qualified_names( if taken { continue; } - let Some(import_qn) = resolved.full_spelling(site.target) else { + let Some(import_qn) = + resolved.full_spelling(resolved.unit_dialect(site.unit), site.target) + else { continue; }; let fix = text_of(site.unit).and_then(|text| { import_anchor(resolved, site.unit, text).map(|(at, indent)| Fix { label: format!("import `{import_qn}` and re-spell as `{simple}`"), deletes: false, + semantic: false, edits: vec![ Edit { unit: site.unit, @@ -2487,7 +3467,7 @@ fn simple_reference(name: &str) -> sysmlv2_syntax::ast::QualifiedName { /// this rule's threshold via [`Config::format_chain_min`]). fn multiline_conditions(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { use sysmlv2_syntax::ast::{BinaryOp, Expr, ExprKind}; - let cfg = config.cfg("multiline-conditions"); + let cfg = config.cfg(RuleId::MultilineConditions); let min = config.chain_min; if min == 0 { return; @@ -2549,7 +3529,7 @@ fn multiline_conditions(resolved: &mut ResolvedModel, config: &Config, out: &mut continue; // already broken across lines } let mut f = finding( - "multiline-conditions", + RuleId::MultilineConditions, severity, format!( "a {n}-condition `{op}` chain on one line — one condition per line reads \ @@ -2580,7 +3560,7 @@ fn multiline_conditions(resolved: &mut ResolvedModel, config: &Config, out: &mut /// rounded to the nearest level, with a floor of one — an indented line /// never dedents to column 0 because its indentation was narrow. fn indentation(config: &Config, sources: &[(usize, &str)], out: &mut Vec) { - let severity = config.cfg("indentation").base; + let severity = config.cfg(RuleId::Indentation).base; if severity == Severity::Off { return; } @@ -2643,12 +3623,13 @@ fn indentation(config: &Config, sources: &[(usize, &str)], out: &mut Vec " ".repeat(levels * size), }; let span = Span::new(start, start + ws.len() as u32); - let mut f = finding("indentation", severity, message); + let mut f = finding(RuleId::Indentation, severity, message); f.unit = Some(unit); f.span = Some(span); f.fix = Some(Fix { label: format!("re-indent this line with {wanted}"), deletes: false, + semantic: false, edits: vec![Edit { unit, span, @@ -2665,7 +3646,14 @@ fn plural(n: usize) -> &'static str { } fn unused_definition(resolved: &mut ResolvedModel, config: &Config, out: &mut Vec) { - let cfg = config.cfg("unused-definition"); + let cfg = config.cfg(RuleId::UnusedDefinition); + // Every referenced element, collected once from the reference + // sites rather than by scanning them again per definition. + let referenced: HashSet = resolved + .reference_sites() + .iter() + .map(|s| s.target) + .collect(); let defs: Vec = resolved .user_elements() .filter(|e| resolved.element_type(*e).ends_with("Definition")) @@ -2675,7 +3663,7 @@ fn unused_definition(resolved: &mut ResolvedModel, config: &Config, out: &mut Ve if severity == Severity::Off { continue; } - if !resolved.references_to(def).is_empty() { + if referenced.contains(&def) { continue; } let Some((unit, span)) = resolved.declaration_site(def) else { @@ -2686,7 +3674,7 @@ fn unused_definition(resolved: &mut ResolvedModel, config: &Config, out: &mut Ve .unwrap_or("") .to_string(); let mut f = finding( - "unused-definition", + RuleId::UnusedDefinition, severity, format!( "`{name}` is never referenced in these units (closed world: outside \ @@ -2720,7 +3708,7 @@ pub const CANONICALIZER_SCHEMA_VERSION: u32 = 1; /// options that shape their fixes — never unrelated severities. One /// implementation serves record writers and this crate's verifier. pub fn canonicalization_digest(config: &Config) -> String { - let fix_policy = |id: &str, contexts: &[&str]| { + let fix_policy = |id: RuleId, contexts: &[&str]| { let cfg = config.cfg(id); if contexts.is_empty() { return ((cfg.base != Severity::Off) as u8).to_string(); @@ -2751,11 +3739,11 @@ pub fn canonicalization_digest(config: &Config) -> String { qualified-names={},{qualified_style};unit-spelling={},{unit_style};untyped-usage={}", CANONICALIZER_SCHEMA_VERSION, config.chain_min, - fix_policy("dimensional-consistency", &["mismatch", "untyped"]), - fix_policy("indentation", &[]), - fix_policy("qualified-names", &[]), - fix_policy("unit-spelling", &[]), - fix_policy("untyped-usage", &["AttributeUsage"]), + fix_policy(RuleId::DimensionalConsistency, &["mismatch", "untyped"]), + fix_policy(RuleId::Indentation, &[]), + fix_policy(RuleId::QualifiedNames, &[]), + fix_policy(RuleId::UnitSpelling, &[]), + fix_policy(RuleId::UntypedUsage, &["AttributeUsage"]), ); format!( "sha256:{}", @@ -2769,6 +3757,17 @@ const GEN_STATE_QN: &str = "TransformMeta::TransformState"; const GEN_SOURCE_QN: &str = "TransformMeta::TransformSource"; const STORE_KEY_PREFIX: &str = "provenance:"; +/// Prefix markers (`#TransformMeta::Generated …`, +/// `#TransformMeta::ProvenanceStore …`) are metadata usages with no +/// recorded typing — the owner's head text identifies them, exactly as +/// the materializer does. Compiled once per process. +static GENERATED_HEAD: LazyLock = LazyLock::new(|| { + Regex::new(r"^#\s*(TransformMeta\s*::\s*)?Generated\b").expect("static pattern") +}); +static STORE_HEAD: LazyLock = LazyLock::new(|| { + Regex::new(r"^#\s*(TransformMeta\s*::\s*)?ProvenanceStore\b").expect("static pattern") +}); + fn digest_shaped(v: &str) -> bool { v.len() == 71 && v.starts_with("sha256:") @@ -2812,7 +3811,7 @@ fn unwrap_formatted(formatted: &str) -> String { .unwrap_or(""); inner .iter() - .map(|l| l.strip_prefix(indent).unwrap_or(l.trim_start())) + .map(|l| l.strip_prefix(indent).unwrap_or_else(|| l.trim_start())) .collect::>() .join("\n") } @@ -2822,7 +3821,7 @@ fn unwrap_formatted(formatted: &str) -> String { /// the fixes, and a fix-relevant policy change reads as fingerprint /// drift before any byte comparison happens. Public so record writers /// and fixtures compute the exact bytes this crate verifies. -pub fn canonical_member_text(raw: &str, config: &Config) -> Result { +pub fn canonical_member_text(raw: &str, config: &Config) -> Result { let lf = raw.replace("\r\n", "\n"); let wrapped = format!("package __sysmlGeneratedGuard__ {{\n{lf}\n}}"); let formatted = sysmlv2_syntax::print::format_source_opts( @@ -2835,9 +3834,11 @@ pub fn canonical_member_text(raw: &str, config: &Config) -> Result>; + +/// What every stage of the generated-ownership guard reads: the three +/// rules' effective configurations, the unit names and texts the +/// sidecar contract is spelled in, and the record types. The types are +/// resolved once — asking for typings twice and re-rendering every +/// type's qualified name dominated large editor inventories (20k +/// metadata usages at the 10k-member gate). +struct GuardPass<'a> { + invalid_cfg: &'a RuleConfig, + outdated_cfg: &'a RuleConfig, + modified_cfg: &'a RuleConfig, + unit_names: std::collections::HashMap, + unit_texts: std::collections::HashMap, + provenance_type: Option, + exclusion_type: Option, + state_type: Option, + source_type: Option, +} + +impl<'a> GuardPass<'a> { + fn new( + config: &'a Config, + units: &[(usize, &'a str, &'a str)], + resolved: &mut ResolvedModel, + ) -> GuardPass<'a> { + GuardPass { + invalid_cfg: config.cfg(RuleId::GeneratedProvenanceInvalid), + outdated_cfg: config.cfg(RuleId::GeneratedProvenanceBaselineOutdated), + modified_cfg: config.cfg(RuleId::GeneratedElementModified), + unit_names: units.iter().map(|&(i, n, _)| (i, n)).collect(), + unit_texts: units.iter().map(|&(i, _, t)| (i, t)).collect(), + provenance_type: resolved.resolve_qualified(GEN_PROVENANCE_QN), + exclusion_type: resolved.resolve_qualified(GEN_EXCLUSION_QN), + state_type: resolved.resolve_qualified(GEN_STATE_QN), + source_type: resolved.resolve_qualified(GEN_SOURCE_QN), + } + } +} + +/// Every marker and record one pass over the model found, before any +/// audit has judged them. +struct GenScan { + marked_members: std::collections::HashSet, + marked_stores: std::collections::HashSet, + records: Vec, + states: Vec, +} + +/// What the ownership audits establish about a scan; each audit fills +/// its own fields, and the inventory projection and the target join +/// read all of them. +#[derive(Default)] +struct GuardAudits { + /// Whether each provenance store met its contract completely. + store_ok: std::collections::HashMap, + /// The content package each keyed store owns. + store_targets: std::collections::HashMap, + /// How many records claim each `(transform id, key, exclusion)`. + pair_counts: std::collections::HashMap<(String, String, bool), usize>, + /// Managed records by the member they claim. + owners_by_target: std::collections::HashMap>, + state_by_pair: StateIndex, + /// The `(store, transform id)` pairs managed provenance claims. + managed_pairs: std::collections::BTreeSet<(ElementRef, String)>, +} + +/// The head of a member's source text — enough of it to read the +/// prefix markers a typing-less metadata usage leaves behind. +fn guard_head( + resolved: &ResolvedModel, + unit_texts: &std::collections::HashMap, + e: ElementRef, +) -> Option { + let (unit, span) = resolved.member_extent(e)?; + let text = unit_texts.get(&unit)?; + let raw = text.get(span.start as usize..span.end as usize)?; + Some(raw.trim_start().chars().take(80).collect()) +} + +/// Where a finding about an element anchors: its declaration site, or +/// its whole member extent when it declares no name of its own. +fn guard_anchor(resolved: &ResolvedModel, e: ElementRef) -> Option<(usize, Span)> { + resolved + .declaration_site(e) + .or_else(|| resolved.member_extent(e)) +} + +/// One guard finding, anchored and attributed to its edit target. +fn guard_push( + out: &mut Vec, + rule: RuleId, + severity: Severity, + message: String, + anchor: Option<(usize, Span)>, + element: Option, +) { + let mut f = finding(rule, severity, message); + if let Some((unit, span)) = anchor { + f.unit = Some(unit); + f.span = Some(span); + } + f.element = element; + out.push(f); +} + +/// Exactly one state record for the pair, with its identity intact. +fn state_for_pair( + state_by_pair: &StateIndex, + states: &[GenState], + store: ElementRef, + id: &str, +) -> Option { + match state_by_pair + .get(&(store, id.to_string())) + .map(Vec::as_slice) + { + Some([only]) if states[*only].valid => Some(*only), + _ => None, + } +} + +/// One parsed inventory feeding all three rules: read the markers and +/// records once, audit ownership in stages, project the rows that +/// survive into the host's inventory, then classify baseline drift on +/// the members the audits cleared. fn generated_guard( resolved: &mut ResolvedModel, config: &Config, @@ -2992,58 +4121,35 @@ fn generated_guard( inventory: Option<&mut GeneratedInventory>, inventory_only: bool, ) { - let invalid_cfg = config.cfg("generated-provenance-invalid"); - let outdated_cfg = config.cfg("generated-provenance-baseline-outdated"); - let modified_cfg = config.cfg("generated-element-modified"); - let unit_names: std::collections::HashMap = - units.iter().map(|&(i, n, _)| (i, n)).collect(); - let unit_texts: std::collections::HashMap = - units.iter().map(|&(i, _, t)| (i, t)).collect(); - - // Resolve the two record types once. Asking for typings twice and - // re-rendering every type's qualified name dominated large editor - // inventories (20k metadata usages at the 10k-member gate). - let provenance_type = resolved.resolve_qualified(GEN_PROVENANCE_QN); - let exclusion_type = resolved.resolve_qualified(GEN_EXCLUSION_QN); - let state_type = resolved.resolve_qualified(GEN_STATE_QN); - let source_type = resolved.resolve_qualified(GEN_SOURCE_QN); - // Prefix markers (`#TransformMeta::Generated …`) are metadata - // usages with no recorded typing — identify them by the owner's - // head text, exactly as the materializer does. - let generated_head = regex_lite::Regex::new(r"^#\s*(TransformMeta\s*::\s*)?Generated\b") - .expect("static pattern"); - let store_head = regex_lite::Regex::new(r"^#\s*(TransformMeta\s*::\s*)?ProvenanceStore\b") - .expect("static pattern"); - let head_of = |resolved: &mut ResolvedModel, - unit_texts: &std::collections::HashMap, - e: ElementRef| - -> Option { - let (unit, span) = resolved.member_extent(e)?; - let text = unit_texts.get(&unit)?; - let raw = text.get(span.start as usize..span.end as usize)?; - Some(raw.trim_start().chars().take(80).collect()) - }; - let anchor_of = |resolved: &mut ResolvedModel, e: ElementRef| { - resolved - .declaration_site(e) - .or_else(|| resolved.member_extent(e)) - }; - let push = |out: &mut Vec, - rule: &'static str, - severity: Severity, - message: String, - anchor: Option<(usize, Span)>, - element: Option| { - let mut f = finding(rule, severity, message); - if let Some((unit, span)) = anchor { - f.unit = Some(unit); - f.span = Some(span); - } - f.element = element; - out.push(f); - }; + let pass = GuardPass::new(config, units, resolved); + let mut scan = scan_records(&pass, resolved); + let mut audits = GuardAudits::default(); + audit_stores(&pass, resolved, &scan, &mut audits, out); + audit_states(&pass, resolved, &mut scan.states, &mut audits, out); + audit_record_pairs(&pass, resolved, &mut scan.records, &mut audits, out); + audit_state_correspondence(&pass, resolved, &scan, &mut audits, out); + if let Some(inventory) = inventory { + fill_inventory(&pass, resolved, &scan, &audits, inventory); + } + if inventory_only { + return; + } + let claimed = audit_targets(&pass, resolved, config, &scan, &audits, out); + report_unclaimed_markers(&pass, resolved, &scan, &claimed, out); +} + +/// Collect markers, stores and records: every metadata usage, sorted +/// into provenance records, exclusions, state records, and the bare +/// prefix markers whose owner's head text is all that identifies them. +fn scan_records(pass: &GuardPass, resolved: &mut ResolvedModel) -> GenScan { + let unit_texts: &std::collections::HashMap = &pass.unit_texts; + let (provenance_type, exclusion_type, state_type, source_type) = ( + pass.provenance_type, + pass.exclusion_type, + pass.state_type, + pass.source_type, + ); - // ---- collect markers, stores, records ---- let user_elements: Vec = resolved.user_elements().collect(); let usages: Vec = user_elements .iter() @@ -3067,7 +4173,7 @@ fn generated_guard( // Attribute name/value pairs of one metadata usage — the shared // extraction records, states, and state sources all read through. fn metadata_fields( - resolved: &mut ResolvedModel, + resolved: &ResolvedModel, owned_by: &std::collections::HashMap>, unit_texts: &std::collections::HashMap, e: ElementRef, @@ -3149,7 +4255,7 @@ fn generated_guard( if is_state { let mut st = GenState { el: u, - anchor: anchor_of(resolved, u), + anchor: guard_anchor(resolved, u), store: resolved.owner(u), transform_id: None, transformer_path: None, @@ -3159,7 +4265,7 @@ fn generated_guard( sources: Vec::new(), valid: false, }; - for (name, value) in metadata_fields(resolved, &owned_by, &unit_texts, u) { + for (name, value) in metadata_fields(resolved, &owned_by, unit_texts, u) { match name.as_str() { "transformId" => st.transform_id = Some(value), "transformerPath" => st.transformer_path = Some(value), @@ -3171,7 +4277,7 @@ fn generated_guard( _ => {} } } - st.sources = metadata_sources(resolved, &owned_by, &unit_texts, source_type, u); + st.sources = metadata_sources(resolved, &owned_by, unit_texts, source_type, u); states.push(st); continue; } @@ -3179,10 +4285,10 @@ fn generated_guard( // A typing-less usage may be a prefix marker; the owner's // head text decides. if let Some(owner) = resolved.owner(u) { - if let Some(head) = head_of(resolved, &unit_texts, owner) { - if generated_head.is_match(&head) { + if let Some(head) = guard_head(resolved, unit_texts, owner) { + if GENERATED_HEAD.is_match(&head) { marked_members.insert(owner); - } else if store_head.is_match(&head) { + } else if STORE_HEAD.is_match(&head) { marked_stores.insert(owner); } } @@ -3192,7 +4298,7 @@ fn generated_guard( let mut rec = GenRecord { el: u, exclusion: is_excl, - anchor: anchor_of(resolved, u), + anchor: guard_anchor(resolved, u), transform_id: None, key: None, source: None, @@ -3213,7 +4319,7 @@ fn generated_guard( let Some((_, expr)) = resolved.value_expr(a) else { continue; }; - let Some((unit, _)) = anchor_of(resolved, a) else { + let Some((unit, _)) = guard_anchor(resolved, a) else { continue; }; let Some(text) = unit_texts.get(&unit) else { @@ -3237,29 +4343,60 @@ fn generated_guard( } } if rec.exclusion { - rec.sources = metadata_sources(resolved, &owned_by, &unit_texts, source_type, u); + rec.sources = metadata_sources(resolved, &owned_by, unit_texts, source_type, u); } records.push(rec); } - // ---- store contract audit ---- - let mut store_ok: std::collections::HashMap = Default::default(); - let mut store_targets: std::collections::HashMap = Default::default(); - for store in marked_stores + GenScan { + marked_members, + marked_stores, + records, + states, + } +} + +/// The store contract: a package holding provenance records carries the +/// store marker, sits at the top level of the sidecar unit derived from +/// its target, and keys itself by a short name that resolves. +fn audit_stores( + pass: &GuardPass, + resolved: &mut ResolvedModel, + scan: &GenScan, + audits: &mut GuardAudits, + out: &mut Vec, +) { + let invalid_cfg = pass.invalid_cfg; + let unit_names: &std::collections::HashMap = &pass.unit_names; + let GenScan { + marked_stores, + records, + .. + } = scan; + let GuardAudits { + store_ok, + store_targets, + .. + } = audits; + + // One audit per store, in a stable order: a store several records + // share must not be judged twice, and its findings must land in the + // same order every pass. + let stores: std::collections::BTreeSet = marked_stores .iter() .copied() .chain(records.iter().filter_map(|r| r.store)) - .collect::>() - { + .collect(); + for store in stores { let severity = invalid_cfg.severity(resolved.element_type(store)); - let anchor = anchor_of(resolved, store); + let anchor = guard_anchor(resolved, store); let element = edit_target(resolved, store); let fail = |out: &mut Vec, detail: String, ok: &mut bool| { *ok = false; if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, detail, anchor, @@ -3273,7 +4410,9 @@ fn generated_guard( .unwrap_or_else(|| "".into()); let marked = marked_stores.contains(&store); let ty = resolved.element_type(store).to_string(); - let short = resolved.element_short_name(store).map(str::to_string); + let short = resolved + .element_declared_short_name(store) + .map(str::to_string); let top_level = match resolved.owner(store) { None => true, Some(parent) => { @@ -3350,23 +4489,32 @@ fn generated_guard( } store_ok.insert(store, ok); } +} + +/// One TransformState record per `(store, transform id)`. The state +/// record is the only home of transformer-level facts; managed +/// provenance resolves through it. Missing or duplicate state is +/// corruption under the clean-break protocol: findings here, and the +/// affected rows never reach the inventory. +fn audit_states( + pass: &GuardPass, + resolved: &mut ResolvedModel, + states: &mut [GenState], + audits: &mut GuardAudits, + out: &mut Vec, +) { + let invalid_cfg = pass.invalid_cfg; + let state_by_pair = &mut audits.state_by_pair; - // ---- state audit (AA7h0): one TransformState per (store, id) ---- - // The state record is the only home of transformer-level facts; - // managed provenance resolves through it. Missing or duplicate - // state is corruption under the clean-break protocol: findings - // here, and the affected rows never reach the inventory. - let mut state_by_pair: std::collections::HashMap<(ElementRef, String), Vec> = - Default::default(); for (i, st) in states.iter_mut().enumerate() { let severity = invalid_cfg.severity(resolved.element_type(st.el)); let element = edit_target(resolved, st.el); let mut problems = Vec::new(); let Some(id) = st.transform_id.clone().filter(|id| !id.is_empty()) else { if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, "TransformState record lacks its transformId".into(), st.anchor, @@ -3429,9 +4577,9 @@ fn generated_guard( st.valid = problems.is_empty(); if severity != Severity::Off { for detail in problems { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, detail, st.anchor, @@ -3448,9 +4596,9 @@ fn generated_guard( let st = &states[i]; let severity = invalid_cfg.severity(resolved.element_type(st.el)); if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!("duplicate TransformState records for `{id}`"), st.anchor, @@ -3459,35 +4607,37 @@ fn generated_guard( } } } - // Exactly one state for the pair, with its identity intact. - let state_for_pair = - |state_by_pair: &std::collections::HashMap<(ElementRef, String), Vec>, - store: ElementRef, - id: &str| - -> Option { - match state_by_pair - .get(&(store, id.to_string())) - .map(Vec::as_slice) - { - Some([only]) if states[*only].valid => Some(*only), - _ => None, - } - }; +} + +/// Pair maps and the duplicate/conflict audit: a record's identity +/// fields, an exclusion's own source facts, and the rule that one +/// `(transform id, key)` has at most one claimant of each kind and one +/// generated member at most one owner. +fn audit_record_pairs( + pass: &GuardPass, + resolved: &mut ResolvedModel, + records: &mut [GenRecord], + audits: &mut GuardAudits, + out: &mut Vec, +) { + let invalid_cfg = pass.invalid_cfg; + let GuardAudits { + pair_counts, + owners_by_target, + .. + } = audits; - // ---- pair maps + duplicate / conflict audit ---- let mut prov_by_pair: std::collections::HashMap<(String, String), usize> = Default::default(); let mut excl_pairs: std::collections::HashSet<(String, String)> = Default::default(); - let mut pair_counts: std::collections::HashMap<(String, String, bool), usize> = - Default::default(); for (i, rec) in records.iter_mut().enumerate() { let anchor = rec.anchor; let severity = invalid_cfg.severity(resolved.element_type(rec.el)); let element = edit_target(resolved, rec.el); let (Some(id), Some(key)) = (rec.transform_id.clone(), rec.key.clone()) else { if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, "provenance record lacks its transformId/key identity fields".into(), anchor, @@ -3542,9 +4692,9 @@ fn generated_guard( rec.valid = problems.is_empty(); if severity != Severity::Off { for detail in problems { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, detail, anchor, @@ -3559,9 +4709,9 @@ fn generated_guard( .or_default() += 1; if rec.exclusion { if !excl_pairs.insert(pair.clone()) && severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!("duplicate exclusions for ({id}, {key})"), anchor, @@ -3571,9 +4721,9 @@ fn generated_guard( } else if let Some(prev) = prov_by_pair.insert(pair.clone(), i) { let _ = prev; if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!("duplicate provenance claims for ({id}, {key})"), anchor, @@ -3587,9 +4737,9 @@ fn generated_guard( let rec = &records[prov_by_pair[pair]]; let severity = invalid_cfg.severity(resolved.element_type(rec.el)); if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "both a provenance record and an exclusion exist for ({}, {})", @@ -3605,8 +4755,6 @@ fn generated_guard( // A generated member has exactly one provenance owner, independent // of transform id. Two records with different pairs are still two // writers for the same bytes and therefore unsafe to guard. - let mut owners_by_target: std::collections::HashMap> = - Default::default(); for (i, rec) in records.iter().enumerate() { if !rec.exclusion && rec.targets.len() == 1 { owners_by_target.entry(rec.targets[0]).or_default().push(i); @@ -3621,9 +4769,9 @@ fn generated_guard( let member_spelled = resolved .element_qualified_name(member) .unwrap_or_else(|| "".into()); - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "generated member `{member_spelled}` is claimed by multiple provenance records" @@ -3634,8 +4782,23 @@ fn generated_guard( } } } +} + +/// State and managed records answer for each other: every pair managed +/// provenance claims has a state record, and every state record has +/// managed provenance. +fn audit_state_correspondence( + pass: &GuardPass, + resolved: &mut ResolvedModel, + scan: &GenScan, + audits: &mut GuardAudits, + out: &mut Vec, +) { + let invalid_cfg = pass.invalid_cfg; + let records = &scan.records; + let states = &scan.states; + let state_by_pair = &audits.state_by_pair; - // ---- state ↔ managed-record correspondence (AA7h0) ---- let mut managed_pairs: std::collections::BTreeSet<(ElementRef, String)> = Default::default(); let mut first_managed_rec: std::collections::HashMap<(ElementRef, String), usize> = Default::default(); @@ -3656,9 +4819,9 @@ fn generated_guard( let rec = &records[first_managed_rec[&(*store, id.clone())]]; let severity = invalid_cfg.severity(resolved.element_type(rec.el)); if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "managed provenance for `{id}` has no TransformState record — the sidecar predates the state protocol or was hand-edited; delete it and rerun the transformer" @@ -3675,9 +4838,9 @@ fn generated_guard( let st = &states[indices[0]]; let severity = invalid_cfg.severity(resolved.element_type(st.el)); if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!("TransformState for `{id}` has no managed provenance records"), st.anchor, @@ -3685,186 +4848,237 @@ fn generated_guard( ); } } + audits.managed_pairs = managed_pairs; +} - if let Some(inventory) = inventory { - for rec in &records { - let (Some(transform_id), Some(key), Some(store)) = - (rec.transform_id.as_ref(), rec.key.as_ref(), rec.store) - else { - continue; - }; - if store_ok.get(&store) != Some(&true) { - continue; - } - if !rec.valid { - continue; - } - let pair = (transform_id.clone(), key.clone(), rec.exclusion); - if pair_counts.get(&pair) != Some(&1) - || pair_counts.contains_key(&(transform_id.clone(), key.clone(), !rec.exclusion)) - { - continue; - } - let target_package = store_targets.get(&store).copied(); - let malformed_digest = [ - rec.row_digest.as_deref(), - rec.spelling_digest.as_deref(), - rec.structure_digest.as_deref(), - rec.policy_digest.as_deref(), - ] - .into_iter() - .flatten() - .any(|value| !digest_shaped(value)); - if malformed_digest { - continue; +/// Project the rows every audit cleared into the host's inventory: +/// guarded member ranges, adopted exclusions, targetless tombstones, +/// and the state records behind them. +fn fill_inventory( + pass: &GuardPass, + resolved: &mut ResolvedModel, + scan: &GenScan, + audits: &GuardAudits, + inventory: &mut GeneratedInventory, +) { + let unit_names = &pass.unit_names; + let unit_texts = &pass.unit_texts; + let GenScan { + marked_members, + records, + states, + .. + } = scan; + let GuardAudits { + store_ok, + store_targets, + pair_counts, + owners_by_target, + state_by_pair, + managed_pairs, + } = audits; + + for rec in records { + let (Some(transform_id), Some(key), Some(store)) = + (rec.transform_id.as_ref(), rec.key.as_ref(), rec.store) + else { + continue; + }; + if store_ok.get(&store) != Some(&true) { + continue; + } + if !rec.valid { + continue; + } + let pair = (transform_id.clone(), key.clone(), rec.exclusion); + if pair_counts.get(&pair) != Some(&1) + || pair_counts.contains_key(&(transform_id.clone(), key.clone(), !rec.exclusion)) + { + continue; + } + let target_package = store_targets.get(&store).copied(); + let malformed_digest = [ + rec.row_digest.as_deref(), + rec.spelling_digest.as_deref(), + rec.structure_digest.as_deref(), + rec.policy_digest.as_deref(), + ] + .into_iter() + .flatten() + .any(|value| !digest_shaped(value)); + if malformed_digest { + continue; + } + // AA7h0: a managed row's transformer-level facts resolve + // through the pair's unique TransformState — no state, no + // row (the correspondence audit already named why). + let state = if rec.exclusion { + None + } else { + match state_for_pair(state_by_pair, states, store, transform_id) { + Some(i) => Some(&states[i]), + None => continue, } - // AA7h0: a managed row's transformer-level facts resolve - // through the pair's unique TransformState — no state, no - // row (the correspondence audit already named why). - let state = if rec.exclusion { - None - } else { - match state_for_pair(&state_by_pair, store, transform_id) { - Some(i) => Some(&states[i]), - None => continue, - } - }; - let source_facts = match state { - Some(state) => &state.sources, - None => &rec.sources, - }; - let sources: Vec = source_facts - .iter() - .filter_map(|source| { - Some(GeneratedStateSource { - alias: source.alias.clone()?, - source_ref: source.source_ref.clone()?, - input_digest: source.input_digest.clone(), - row_count: source.row_count, - }) + }; + let source_facts = match state { + Some(state) => &state.sources, + None => &rec.sources, + }; + let sources: Vec = source_facts + .iter() + .filter_map(|source| { + Some(GeneratedStateSource { + alias: source.alias.clone()?, + source_ref: source.source_ref.clone()?, + input_digest: source.input_digest.clone(), + row_count: source.row_count, }) - .collect(); - if rec.exclusion && rec.targets.is_empty() { - inventory.tombstones.push(GeneratedTombstone { - key: key.clone(), - transform_id: transform_id.clone(), - source: sources.first().map(|source| source.source_ref.clone()), - sources, - transformer_path: rec.path.clone(), - record_id: resolved.element_id(rec.el).to_string(), - }); - continue; - } - if rec.targets.len() != 1 { - continue; - } - let member = rec.targets[0]; - if target_package.is_none() - || resolved.owner(member) != target_package - || (rec.exclusion && marked_members.contains(&member)) - || (!rec.exclusion && !marked_members.contains(&member)) - || (!rec.exclusion - && owners_by_target - .get(&member) - .is_none_or(|owners| owners.len() != 1)) - || (!rec.exclusion && resolved.element_short_name(member) != Some(key.as_str())) - { - continue; - } - let Some((unit, extent)) = resolved.member_extent(member) else { - continue; - }; - let (Some(text), Some(_name)) = (unit_texts.get(&unit), unit_names.get(&unit)) else { - continue; - }; - let Some(raw) = text.get(extent.start as usize..extent.end as usize) else { - continue; - }; - let row = GeneratedRange { - unit, - start: extent.start, - end: extent.end, + }) + .collect(); + if rec.exclusion && rec.targets.is_empty() { + inventory.tombstones.push(GeneratedTombstone { key: key.clone(), transform_id: transform_id.clone(), - // Managed rows resolve through the state record (the - // first source is the row-level column); exclusions - // stay self-contained by ratified design. source: sources.first().map(|source| source.source_ref.clone()), sources, - transformer_path: match state { - Some(st) => st.transformer_path.clone(), - None => rec.path.clone(), - }, - member_qn: resolved.element_qualified_name(member), - member_id: resolved.element_id(member).to_string(), + transformer_path: rec.path.clone(), record_id: resolved.element_id(rec.el).to_string(), - raw: raw.to_string(), - excluded: rec.exclusion, - row_digest: rec.row_digest.clone(), - }; - if rec.exclusion { - inventory.excluded.push(row); - } else { - inventory.members.push(row); - } - } - for ((store, id), indices) in state_by_pair.iter() { - let [only] = indices.as_slice() else { - continue; // duplicates already found; no surface row - }; - if store_ok.get(store) != Some(&true) || !managed_pairs.contains(&(*store, id.clone())) - { - continue; - } - let st = &states[*only]; - if !st.valid { - continue; - } - inventory.states.push(GeneratedState { - transform_id: id.clone(), - transformer_path: st.transformer_path.clone().unwrap_or_default(), - script_digest: st.script_digest.clone(), - forced_schema_drift: st.forced, - sources: st - .sources - .iter() - .filter_map(|source| { - Some(GeneratedStateSource { - alias: source.alias.clone()?, - source_ref: source.source_ref.clone()?, - input_digest: source.input_digest.clone(), - row_count: source.row_count, - }) - }) - .collect(), - target_qn: store_targets - .get(store) - .and_then(|t| resolved.element_qualified_name(*t)), - record_id: resolved.element_id(st.el).to_string(), }); + continue; } - inventory.states.sort_by(|a, b| { - a.target_qn - .cmp(&b.target_qn) - .then(a.transform_id.cmp(&b.transform_id)) - }); - let by_position = |a: &GeneratedRange, b: &GeneratedRange| { - a.unit.cmp(&b.unit).then(a.start.cmp(&b.start)) + if rec.targets.len() != 1 { + continue; + } + let member = rec.targets[0]; + if target_package.is_none() + || resolved.owner(member) != target_package + || (rec.exclusion && marked_members.contains(&member)) + || (!rec.exclusion && !marked_members.contains(&member)) + || (!rec.exclusion + && owners_by_target + .get(&member) + .is_none_or(|owners| owners.len() != 1)) + || (!rec.exclusion + && resolved.element_declared_short_name(member) != Some(key.as_str())) + { + continue; + } + let Some((unit, extent)) = resolved.member_extent(member) else { + continue; + }; + let (Some(text), Some(_name)) = (unit_texts.get(&unit), unit_names.get(&unit)) else { + continue; + }; + let Some(raw) = text.get(extent.start as usize..extent.end as usize) else { + continue; + }; + let row = GeneratedRange { + unit, + start: extent.start, + end: extent.end, + key: key.clone(), + transform_id: transform_id.clone(), + // Managed rows resolve through the state record (the + // first source is the row-level column); exclusions + // stay self-contained by ratified design. + source: sources.first().map(|source| source.source_ref.clone()), + sources, + transformer_path: match state { + Some(st) => st.transformer_path.clone(), + None => rec.path.clone(), + }, + member_qn: resolved.element_qualified_name(member), + member_id: resolved.element_id(member).to_string(), + record_id: resolved.element_id(rec.el).to_string(), + raw: raw.to_string(), + excluded: rec.exclusion, + row_digest: rec.row_digest.clone(), }; - inventory.members.sort_by(by_position); - inventory.excluded.sort_by(by_position); - inventory - .tombstones - .sort_by(|a, b| a.transform_id.cmp(&b.transform_id).then(a.key.cmp(&b.key))); + if rec.exclusion { + inventory.excluded.push(row); + } else { + inventory.members.push(row); + } } - if inventory_only { - return; + for ((store, id), indices) in state_by_pair.iter() { + let [only] = indices.as_slice() else { + continue; // duplicates already found; no surface row + }; + if store_ok.get(store) != Some(&true) || !managed_pairs.contains(&(*store, id.clone())) { + continue; + } + let st = &states[*only]; + if !st.valid { + continue; + } + inventory.states.push(GeneratedState { + transform_id: id.clone(), + transformer_path: st.transformer_path.clone().unwrap_or_default(), + script_digest: st.script_digest.clone(), + forced_schema_drift: st.forced, + sources: st + .sources + .iter() + .filter_map(|source| { + Some(GeneratedStateSource { + alias: source.alias.clone()?, + source_ref: source.source_ref.clone()?, + input_digest: source.input_digest.clone(), + row_count: source.row_count, + }) + }) + .collect(), + target_qn: store_targets + .get(store) + .and_then(|t| resolved.element_qualified_name(*t)), + record_id: resolved.element_id(st.el).to_string(), + }); } + inventory.states.sort_by(|a, b| { + a.target_qn + .cmp(&b.target_qn) + .then(a.transform_id.cmp(&b.transform_id)) + }); + let by_position = + |a: &GeneratedRange, b: &GeneratedRange| a.unit.cmp(&b.unit).then(a.start.cmp(&b.start)); + inventory.members.sort_by(by_position); + inventory.excluded.sort_by(by_position); + inventory + .tombstones + .sort_by(|a, b| a.transform_id.cmp(&b.transform_id).then(a.key.cmp(&b.key))); +} + +/// Join records to their targets, audit the baseline fields, and +/// classify drift: fingerprint first, then structure, then canonical +/// bytes, then raw spelling. Answers the members a record claims. +fn audit_targets( + pass: &GuardPass, + resolved: &mut ResolvedModel, + config: &Config, + scan: &GenScan, + audits: &GuardAudits, + out: &mut Vec, +) -> std::collections::HashSet { + let invalid_cfg = pass.invalid_cfg; + let outdated_cfg = pass.outdated_cfg; + let modified_cfg = pass.modified_cfg; + let unit_texts = &pass.unit_texts; + let GenScan { + marked_members, + records, + states, + .. + } = scan; + let GuardAudits { + store_targets, + owners_by_target, + state_by_pair, + .. + } = audits; - // ---- record → target joins, baseline audit, drift classification ---- let policy = canonicalization_digest(config); let mut claimed: std::collections::HashSet = Default::default(); - for rec in &records { + for rec in records { let severity = invalid_cfg.severity(resolved.element_type(rec.el)); let anchor = rec.anchor; let element = edit_target(resolved, rec.el); @@ -3874,9 +5088,9 @@ fn generated_guard( .unwrap_or_else(|| "".into()); if rec.exclusion { if rec.targets.len() > 1 && severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "exclusion `{spelled}` annotates {} members — at most one adopted member is allowed", @@ -3892,9 +5106,9 @@ fn generated_guard( // it targets still reads as marker-only corruption too. for t in &rec.targets { if marked_members.contains(t) && severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "exclusion `{spelled}` targets a member still carrying the \ @@ -3910,9 +5124,9 @@ fn generated_guard( let package = resolved .element_qualified_name(target_package) .unwrap_or_else(|| "".into()); - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "exclusion `{spelled}` targets a member outside its store package `{package}`" @@ -3927,9 +5141,9 @@ fn generated_guard( } if rec.targets.len() != 1 { if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "provenance record `{spelled}` annotates {} members — exactly one \ @@ -3949,9 +5163,9 @@ fn generated_guard( .unwrap_or_else(|| "".into()); if !marked_members.contains(&member) { if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "provenance record `{spelled}` annotates `{member_spelled}`, which \ @@ -3969,9 +5183,9 @@ fn generated_guard( let package = resolved .element_qualified_name(target_package) .unwrap_or_else(|| "".into()); - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "provenance record `{spelled}` targets a member outside its store package `{package}`" @@ -3991,12 +5205,14 @@ fn generated_guard( } if let (Some(key), Some(short)) = ( rec.key.as_deref(), - resolved.element_short_name(member).map(str::to_string), + resolved + .element_declared_short_name(member) + .map(str::to_string), ) { if key != short && severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "provenance record for key `{key}` annotates a member whose short \ @@ -4020,9 +5236,9 @@ fn generated_guard( if !digest_shaped(v) { malformed = true; if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!("record `{spelled}` has a malformed {label}"), anchor, @@ -4044,9 +5260,9 @@ fn generated_guard( ) else { let outdated = outdated_cfg.severity(resolved.element_type(member)); if outdated != Severity::Off { - push( + guard_push( out, - "generated-provenance-baseline-outdated", + RuleId::GeneratedProvenanceBaselineOutdated, outdated, format!( "provenance for `{member_spelled}` predates the structure/policy \ @@ -4062,7 +5278,7 @@ fn generated_guard( // Drift classification: fingerprint first, then // structure, then canonical bytes, then raw spelling. let drift = modified_cfg.severity(resolved.element_type(member)); - let member_anchor = anchor_of(resolved, member); + let member_anchor = guard_anchor(resolved, member); let member_element = edit_target(resolved, member); let Some((unit, extent)) = resolved.member_extent(member) else { continue; @@ -4075,9 +5291,9 @@ fn generated_guard( }; if policy_digest != policy { if drift != Severity::Off { - push( + guard_push( out, - "generated-element-modified", + RuleId::GeneratedElementModified, drift, format!( "canonicalization policy changed since `{member_spelled}` was \ @@ -4094,9 +5310,9 @@ fn generated_guard( match current_structure { Err(_) => { if drift != Severity::Off { - push( + guard_push( out, - "generated-element-modified", + RuleId::GeneratedElementModified, drift, format!( "generated member `{member_spelled}` was modified — it no \ @@ -4116,7 +5332,7 @@ fn generated_guard( rec.store .zip(rec.transform_id.as_deref()) .and_then(|(store, id)| { - state_for_pair(&state_by_pair, store, id).map(|i| &states[i]) + state_for_pair(state_by_pair, states, store, id).map(|i| &states[i]) }); let provenance = match state_facts.and_then(|st| { st.sources @@ -4127,9 +5343,9 @@ fn generated_guard( Some((s, p)) => format!(" (synced from {s} by {p})"), None => String::new(), }; - push( + guard_push( out, - "generated-element-modified", + RuleId::GeneratedElementModified, drift, format!( "generated member `{member_spelled}` was modified — structure \ @@ -4155,9 +5371,9 @@ fn generated_guard( // Equal structure and policy with disagreeing canonical // bytes cannot happen against an honest baseline. if severity != Severity::Off { - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "record for `{member_spelled}` has a corrupt baseline: canonical \ @@ -4176,9 +5392,9 @@ fn generated_guard( sysmlv2_syntax::print::indent_unit(base, unit_text), ); if raw.replace("\r\n", "\n") != expected && drift != Severity::Off { - push( + guard_push( out, - "generated-element-modified", + RuleId::GeneratedElementModified, drift, format!( "generated member `{member_spelled}` formatting drifted from the \ @@ -4189,9 +5405,22 @@ fn generated_guard( ); } } + claimed +} + +/// A member carrying the Generated marker that no provenance record +/// claims is corruption, never silently hand-written text. +fn report_unclaimed_markers( + pass: &GuardPass, + resolved: &mut ResolvedModel, + scan: &GenScan, + claimed: &std::collections::HashSet, + out: &mut Vec, +) { + let invalid_cfg = pass.invalid_cfg; + let marked_members = &scan.marked_members; - // ---- marker-only members: corruption, never silently hand-written ---- - for member in &marked_members { + for member in marked_members { if claimed.contains(member) { continue; } @@ -4202,15 +5431,15 @@ fn generated_guard( let spelled = resolved .element_qualified_name(*member) .unwrap_or_else(|| "".into()); - push( + guard_push( out, - "generated-provenance-invalid", + RuleId::GeneratedProvenanceInvalid, severity, format!( "`{spelled}` carries the Generated marker but no provenance record claims \ it — managed ownership is corrupt; resync, repair, or adopt explicitly" ), - anchor_of(resolved, *member), + guard_anchor(resolved, *member), edit_target(resolved, *member), ); } diff --git a/crates/sysmlv2-lint/tests/generated.rs b/crates/sysmlv2-lint/tests/generated.rs index b622394..5811c8b 100644 --- a/crates/sysmlv2-lint/tests/generated.rs +++ b/crates/sysmlv2-lint/tests/generated.rs @@ -2,9 +2,10 @@ //! classes classify distinctly, every ownership-corruption shape is //! found, and clean models stay silent. +use std::fmt::Write as _; use sysmlv2_lint::{ - Config, Finding, Severity, canonical_member_text, canonicalization_digest, generated_inventory, - lint_units, + Config, Finding, LintError, Severity, canonical_member_text, canonicalization_digest, + generated_inventory, lint_units, }; use sysmlv2_model::structure::{member_structure_digest, sha256_hex}; use sysmlv2_parser::json::ResolvedModel; @@ -63,7 +64,7 @@ fn run(sources: &[(&str, &str)], config: &Config) -> Vec { fn guard_findings(sources: &[(&str, &str)], config: &Config) -> Vec { run(sources, config) .into_iter() - .filter(|f| f.rule.starts_with("generated-")) + .filter(|f| f.rule.id().starts_with("generated-")) .collect() } @@ -134,13 +135,10 @@ fn fields(b: &Baseline, with_baseline: bool) -> String { let mut out = String::new(); out.push_str("\t\ttransformId = \"sync\";\n"); out.push_str("\t\tkey = \"R-1\";\n"); - out.push_str(&format!("\t\tspellingDigest = \"{}\";\n", b.text_digest)); + writeln!(out, "\t\tspellingDigest = \"{}\";", b.text_digest).unwrap(); if with_baseline { - out.push_str(&format!( - "\t\tstructureDigest = \"{}\";\n", - b.structure_digest - )); - out.push_str(&format!("\t\tpolicyDigest = \"{}\";\n", b.policy)); + writeln!(out, "\t\tstructureDigest = \"{}\";", b.structure_digest).unwrap(); + writeln!(out, "\t\tpolicyDigest = \"{}\";", b.policy).unwrap(); } out } @@ -905,3 +903,17 @@ fn row_digest_and_state_digests_surface() { Some(input_digest.as_str()) ); } + +/// A member whose text does not parse on its own has no canonical form, +/// and says so by kind: the guard skips its baseline comparison rather +/// than guessing at bytes. +#[test] +fn a_member_that_does_not_parse_has_no_canonical_text() { + let err = canonical_member_text("part def Broken { {{{", &Config::default()) + .expect_err("does not parse"); + assert!(matches!(err, LintError::UnparseableMember(_)), "{err:?}"); + assert!( + err.to_string().starts_with("member does not parse: "), + "{err}" + ); +} diff --git a/crates/sysmlv2-lint/tests/lint.rs b/crates/sysmlv2-lint/tests/lint.rs index 9099aa3..fea84ec 100644 --- a/crates/sysmlv2-lint/tests/lint.rs +++ b/crates/sysmlv2-lint/tests/lint.rs @@ -1,7 +1,10 @@ //! Rule-level gates: hit/miss per rule, severity config, scope maps, //! style presets, config complaints, fix shapes, determinism. -use sysmlv2_lint::{Config, Finding, Severity, convert_to_style, lint, lint_with_sources}; +use std::fmt::Write as _; +use sysmlv2_lint::{ + Config, Finding, LintError, RULES, RuleId, Severity, convert_to_style, lint, lint_with_sources, +}; use sysmlv2_parser::json::ResolvedModel; use sysmlv2_parser::model::Model; @@ -363,6 +366,38 @@ fn naming_convention_bad_specs_complain_and_keep_defaults() { ); } +/// A converted name a sibling already carries is not suggested: the +/// rename would leave two members of one namespace sharing a name. +/// The finding itself stays. +#[test] +fn naming_convention_withholds_suggestions_a_sibling_already_carries() { + let src = "package P { + part def Wheel; + part def wheel; + part def <'Axle'> spindle; + part def axle; + part def brake_disc; +} +"; + let findings = run(&[("a.sysml", src)], &Config::default()); + let naming: Vec<&Finding> = findings + .iter() + .filter(|f| f.rule == "naming-convention") + .collect(); + let by_target = |qn: &str| { + naming + .iter() + .find(|f| f.element.as_deref() == Some(qn)) + .unwrap_or_else(|| panic!("no finding for {qn}: {naming:?}")) + }; + assert_eq!(by_target("P::wheel").suggest, None); + assert_eq!(by_target("P::axle").suggest, None); + assert_eq!( + by_target("P::brake_disc").suggest.as_deref(), + Some("BrakeDisc") + ); +} + #[test] fn style_conversion_covers_the_presets() { for (name, style, want) in [ @@ -911,3 +946,935 @@ fn indentation_bad_options_complain_and_keep_the_defaults() { 3 ); } + +// --------------------------------------------------------------------------- +// import-visibility: the keyword an import's dependents require +// --------------------------------------------------------------------------- + +const IMPORT_LIB: &str = "package Lib { part def Thing; }\n"; + +fn import_visibility_finding(sources: &[(&str, &str)]) -> Finding { + let findings: Vec = run(sources, &Config::default()) + .into_iter() + .filter(|f| f.rule == "import-visibility") + .collect(); + assert_eq!(findings.len(), 1, "{findings:?}"); + findings.into_iter().next().unwrap() +} + +#[test] +fn import_visibility_recommends_private_when_only_the_importer_uses_it() { + // A nested package resolves through the enclosing package's import + // lexically, so it does not need the import to be visible. + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ( + "p.sysml", + "package P {\n import Lib::*;\n part a : Thing;\n package Child { part c : Thing; }\n}\n", + ), + ]); + assert_eq!(f.severity, Severity::Info); + assert!(f.message.contains("`private` suffices"), "{}", f.message); + assert!(f.message.contains("`P`"), "{}", f.message); + let fix = f.fix.as_ref().expect("computed fix"); + assert_eq!(fix.label, "Make the import `private`"); + assert!(!fix.semantic && !fix.deletes); + assert_eq!(fix.edits.len(), 1); + assert_eq!(fix.edits[0].unit, 1); + assert_eq!(fix.edits[0].replacement, "private "); + assert_eq!(fix.edits[0].span.start, fix.edits[0].span.end); + // The keyword lands where the member starts: `private import Lib::*;`. + assert_eq!(fix.edits[0].span.start, "package P {\n ".len() as u32); + let labels: Vec<&str> = f.alternatives.iter().map(|a| a.label.as_str()).collect(); + assert_eq!( + labels, + ["Make the import `protected`", "Make the import `public`"] + ); + assert!(f.alternatives.iter().all(|a| a.semantic)); +} + +#[test] +fn import_visibility_recommends_public_when_an_outside_reference_depends_on_it() { + // `P::Thing` reaches Lib::Thing only through P's import: a private + // keyword would break Q. + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ("p.sysml", "package P { import Lib::*; }\n"), + ("q.sysml", "package Q { part b : P::Thing; }\n"), + ]); + assert!( + f.message.contains("`public` is required") && f.message.contains("1 reference(s)"), + "{}", + f.message + ); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `public`"); + assert_eq!(f.suggest.as_deref(), Some("public")); +} + +#[test] +fn import_visibility_recommends_protected_for_a_type_used_by_its_specializations() { + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ( + "p.sysml", + "package P {\n part def Base { import Lib::*; }\n part def Sub :> Base { part t : Thing; }\n}\n", + ), + ]); + assert!( + f.message.contains("`protected` is required"), + "{}", + f.message + ); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `protected`"); +} + +#[test] +fn reference_sites_record_the_imports_they_resolved_through() { + let mut model = Model::new(); + model.add_source("lib.sysml".to_string(), IMPORT_LIB); + model.add_source( + "p.sysml".to_string(), + "package P { import Lib::*; part a : Thing; part b : Lib::Thing; }\n", + ); + let resolved = ResolvedModel::build(&model); + let imports = resolved.imports_without_visibility(); + assert_eq!(imports.len(), 1); + let import = imports[0].0; + let sites: Vec<_> = resolved + .reference_sites() + .iter() + .filter(|s| s.unit == 1 && s.kind == "type") + .map(|s| (s.span.start, s.via_imports.clone())) + .collect(); + assert_eq!(sites.len(), 2, "{sites:?}"); + // `Thing` resolved through the import, lexically (full access); + // `Lib::Thing` did not. + assert_eq!( + sites[0].1, + [(import, sysmlv2_parser::json::AccessMode::Any)] + ); + assert!(sites[1].1.is_empty(), "{sites:?}"); +} + +#[test] +fn import_visibility_sees_re_exports_membership_imports_and_import_targets() { + // A namespace import of P re-exports P's bare import: the walk into + // P ran under public access, so `private` would break Q. + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ("p.sysml", "package P { import Lib::*; }\n"), + ( + "q.sysml", + "package Q { private import P::*; part b : Thing; }\n", + ), + ]); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `public`"); + // A membership import records like a namespace import. + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ( + "p.sysml", + "package P { import Lib::Thing; part a : Thing; }\n", + ), + ]); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `private`"); + // An import whose own target resolves only through another import + // depends on that import, even when the import cache was filled by + // an earlier lookup in the same scope. + let f = import_visibility_finding(&[ + ("a.sysml", "package A { package B { part def C; } }\n"), + ("p.sysml", "package P { import A::*; }\n"), + ( + "q.sysml", + "package Q { part z : Nope; private import P::*; private import B::*; part c : C; }\n", + ), + ]); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `public`"); +} + +#[test] +fn import_visibility_stays_quiet_on_an_unresolved_import() { + let findings: Vec = run( + &[("p.sysml", "package P { import Nope::*; }\n")], + &Config::default(), + ) + .into_iter() + .filter(|f| f.rule == "import-visibility") + .collect(); + assert!(findings.is_empty(), "{findings:?}"); +} + +// --------------------------------------------------------------------------- +// visibility-blocked-reference: a private member behind an unresolved name +// --------------------------------------------------------------------------- + +const BLOCKED: &str = "package P { + constraint def MaxTime { private port maxTime; } + part def Req { + constraint c : MaxTime; + attribute limit; + bind c.maxTime = limit; + } +} +"; + +fn run_with_sources(sources: &[(&str, &str)], config: &Config) -> Vec { + let mut model = Model::new(); + for (name, src) in sources { + model.add_source(name.to_string(), src); + } + let mut resolved = ResolvedModel::build(&model); + let texts: Vec<(usize, &str)> = sources + .iter() + .enumerate() + .map(|(i, (_, s))| (i, *s)) + .collect(); + lint_with_sources(&mut resolved, config, &texts) +} + +#[test] +fn visibility_blocked_reference_offers_to_widen_the_member() { + let findings: Vec = run_with_sources(&[("a.sysml", BLOCKED)], &Config::default()) + .into_iter() + .filter(|f| f.rule == "visibility-blocked-reference") + .collect(); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = &findings[0]; + assert_eq!( + f.message, + "`c.maxTime` does not resolve — `P::MaxTime::maxTime` exists but is private" + ); + assert_eq!(f.element.as_deref(), Some("P::MaxTime::maxTime")); + let fix = f.fix.as_ref().expect("widening fix"); + assert_eq!(fix.label, "make `P::MaxTime::maxTime` public"); + assert!(fix.semantic); + assert_eq!(fix.edits.len(), 1); + let e = &fix.edits[0]; + assert_eq!( + &BLOCKED[e.span.start as usize..e.span.end as usize], + "private" + ); + assert_eq!(e.replacement, "public"); + // `Req` does not specialize `MaxTime`, so `protected` would not help. + assert!(f.alternatives.is_empty(), "{:?}", f.alternatives); + // Applying the fix makes the reference resolve. + let fixed = format!( + "{}public{}", + &BLOCKED[..e.span.start as usize], + &BLOCKED[e.span.end as usize..] + ); + let again = run_with_sources(&[("a.sysml", &fixed)], &Config::default()); + assert!( + again + .iter() + .all(|f| f.rule != "visibility-blocked-reference"), + "{again:?}" + ); + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), &fixed); + let resolved = ResolvedModel::build(&model); + assert!(resolved.unresolved_references().is_empty()); +} + +#[test] +fn visibility_blocked_reference_covers_inherited_and_qualified_members() { + let src = "package P { + part def Base { private attribute v; } + part def Sub :> Base { attribute :>> v = 1; } + part def Other { attribute w = Base::v; } +} +"; + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), src); + let resolved = ResolvedModel::build(&model); + let blocked = resolved.blocked_references(); + let names: Vec<&str> = blocked.iter().map(|b| b.spelling.as_str()).collect(); + assert_eq!(names, ["v", "Base::v"], "{blocked:?}"); + assert!(blocked.iter().all(|b| b.visibility == "private")); + // The redefinition reaches `v` through the specialization, so + // `protected` suffices there; the qualified reference from `Other` + // needs `public`. + assert_eq!( + blocked + .iter() + .map(|b| b.protected_suffices) + .collect::>(), + [true, false] + ); + let findings = rule_findings_in(src, "visibility-blocked-reference"); + let alternatives: Vec = findings.iter().map(|f| f.alternatives.len()).collect(); + assert_eq!(alternatives, [1, 0], "{findings:?}"); + // A plain absent name is not blocked. + let mut model = Model::new(); + model.add_source("b.sysml".to_string(), "package Q { part x : Nope; }"); + assert!(ResolvedModel::build(&model).blocked_references().is_empty()); +} + +fn rule_findings_in(src: &str, rule: &str) -> Vec { + run_with_sources(&[("a.sysml", src)], &Config::default()) + .into_iter() + .filter(|f| f.rule == rule) + .collect() +} + +#[test] +fn visibility_blocked_reference_reports_protected_members_and_skips_deeper_paths() { + // A protected member reached from outside any specialization. + let src = "package P { + part def T { protected attribute m; } + part def U { attribute x = T::m; } +} +"; + let findings = rule_findings_in(src, "visibility-blocked-reference"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = &findings[0]; + assert!( + f.message.ends_with("exists but is protected"), + "{}", + f.message + ); + assert_eq!(f.fix.as_ref().unwrap().label, "make `P::T::m` public"); + assert!(f.alternatives.is_empty()); + // A path through two hidden members: widening the last one alone + // would not make the reference resolve, so nothing is offered. + let deep = "package A { private package B { private part def C; } } +package Q { part u : A::B::C; } +"; + assert!(rule_findings_in(deep, "visibility-blocked-reference").is_empty()); + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), deep); + let resolved = ResolvedModel::build(&model); + assert!(resolved.blocked_references().is_empty()); + assert_eq!(resolved.unresolved_references().len(), 1); +} + +#[test] +fn visibility_probes_never_change_what_resolves() { + // Q's reference is resolved first and its probe is the first lookup + // to touch B's scope; B's own import must still fail to resolve + // (Hidden is private to Outer) and `h : H` stay unresolved. + // `c` is reachable from `B` only through that import, so the probe's + // lookup of `c` must consult (and would otherwise fill) B's import + // cache. + let src = "package Q { part u : A::B::c; } +package Outer { private package Hidden { part def H; part def c; } } +package A { private package B { import Outer::Hidden::*; part h : H; } } +"; + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), src); + let resolved = ResolvedModel::build(&model); + let unresolved: Vec = resolved + .unresolved_references() + .iter() + .map(|u| u.spelling.clone()) + .collect(); + assert!(unresolved.contains(&"H".to_string()), "{unresolved:?}"); + assert!( + unresolved.contains(&"Outer::Hidden".to_string()), + "{unresolved:?}" + ); + assert!( + unresolved.contains(&"A::B::c".to_string()), + "{unresolved:?}" + ); +} + +// --------------------------------------------------------------------------- +// M32d: kind and referential fixes +// --------------------------------------------------------------------------- + +fn rule_findings(sources: &[(&str, &str)], rule: &str) -> Vec { + run_with_sources(sources, &Config::default()) + .into_iter() + .filter(|f| f.rule == rule) + .collect() +} + +fn apply_fix(text: &str, fix: &sysmlv2_lint::Fix) -> String { + let mut out = text.to_string(); + let mut edits = fix.edits.clone(); + edits.sort_by_key(|e| std::cmp::Reverse(e.span.start)); + for e in edits { + out.replace_range(e.span.start as usize..e.span.end as usize, &e.replacement); + } + out +} + +#[test] +fn usage_kind_mismatch_rewrites_the_usage_keyword() { + let src = "package P {\n port def Pd;\n part def A {\n private attribute p : Pd;\n }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "usage-kind-mismatch"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = &findings[0]; + assert_eq!( + f.message, + "AttributeUsage must be typed by DataType; `P::Pd` is a PortDefinition" + ); + assert_eq!(f.element.as_deref(), Some("P::A::p")); + let fix = f.fix.as_ref().expect("keyword fix"); + assert_eq!(fix.label, "change `attribute` to `port`"); + assert!(fix.semantic); + assert_eq!( + &src[fix.edits[0].span.start as usize..fix.edits[0].span.end as usize], + "attribute" + ); + let fixed = apply_fix(src, fix); + assert!(fixed.contains("private port p : Pd;"), "{fixed}"); + assert!(rule_findings(&[("a.sysml", &fixed)], "usage-kind-mismatch").is_empty()); + // A compatible typing is not a finding. + let ok = "package P { part def A; item def I; part def B { part a : A; part i : I; } }\n"; + assert!(rule_findings(&[("b.sysml", ok)], "usage-kind-mismatch").is_empty()); + // The most specific definition kind names the keyword: a requirement + // definition is also a constraint definition, a calculation + // definition also an action definition. + let specific = "package P {\n requirement def R;\n calc def C;\n part def A { attribute r : R; attribute c : C; }\n}\n"; + let labels: Vec = rule_findings(&[("c.sysml", specific)], "usage-kind-mismatch") + .iter() + .filter_map(|f| f.fix.as_ref().map(|x| x.label.clone())) + .collect(); + assert_eq!( + labels, + [ + "change `attribute` to `requirement`", + "change `attribute` to `calc`" + ] + ); + // Severity is informational: the semantic check already errors. + assert_eq!(findings[0].severity, Severity::Info); +} + +#[test] +fn port_member_referential_inserts_ref() { + let src = "package P {\n item def Cmd;\n part def A {\n port q {\n item cmd : Cmd;\n ref item ok : Cmd;\n }\n }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "port-member-referential"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = &findings[0]; + assert_eq!(f.element.as_deref(), Some("P::A::q::cmd")); + let fix = f.fix.as_ref().expect("ref fix"); + assert!(!fix.semantic && !fix.deletes); + let fixed = apply_fix(src, fix); + assert!(fixed.contains(" ref item cmd : Cmd;"), "{fixed}"); + assert!(rule_findings(&[("a.sysml", &fixed)], "port-member-referential").is_empty()); + // A port definition's own members, prefixes before the keyword, and + // `ref` placed before `individual` (the grammar reads it first). + let more = "package P {\n item def Cmd;\n port def Pd {\n private abstract item a : Cmd;\n individual item i : Cmd;\n in item p : Cmd;\n }\n}\n"; + let findings = rule_findings(&[("b.sysml", more)], "port-member-referential"); + let fixed: Vec = findings + .iter() + .map(|f| apply_fix(more, f.fix.as_ref().unwrap())) + .collect(); + assert_eq!(fixed.len(), 2, "{findings:?}"); + assert!( + fixed[0].contains("private abstract ref item a : Cmd;"), + "{}", + fixed[0] + ); + assert!( + fixed[1].contains("ref individual item i : Cmd;"), + "{}", + fixed[1] + ); + assert_eq!(findings[0].severity, Severity::Info); +} + +#[test] +fn unqualified_enum_literal_qualifies_a_unique_match() { + let src = "package P {\n enum def Mode { TRACK; SLEW; }\n part def A {\n attribute m : Mode;\n constraint valid { m == TRACK }\n }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "unqualified-enum-literal"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = &findings[0]; + assert_eq!(f.suggest.as_deref(), Some("P::Mode::TRACK")); + let fix = f.fix.as_ref().expect("qualify fix"); + assert_eq!(fix.label, "qualify as `P::Mode::TRACK`"); + let fixed = apply_fix(src, fix); + assert!(fixed.contains("m == P::Mode::TRACK"), "{fixed}"); + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), &fixed); + assert!( + ResolvedModel::build(&model) + .unresolved_references() + .is_empty() + ); + // Two literals of that name: no fix, no finding. + let two = "package P {\n enum def A { X; }\n enum def B { X; }\n part def C { attribute v = X; }\n}\n"; + assert!(rule_findings(&[("b.sysml", two)], "unqualified-enum-literal").is_empty()); + // A restricted-name literal is matched by its escaped spelling and + // spliced as reference text that re-parses. + let restricted = "package P {\n enum def State { 'Not Accepted'; Accepted; }\n part def A { attribute s = 'Not Accepted'; }\n}\n"; + let findings = rule_findings(&[("c.sysml", restricted)], "unqualified-enum-literal"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let fixed = apply_fix(restricted, findings[0].fix.as_ref().unwrap()); + assert!( + fixed.contains("attribute s = P::State::'Not Accepted';"), + "{fixed}" + ); + let mut model = Model::new(); + model.add_source("c.sysml".to_string(), &fixed); + assert!( + ResolvedModel::build(&model) + .unresolved_references() + .is_empty() + ); +} + +#[test] +fn unresolved_references_survive_a_referential_check() { + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), "package P { part x : Nope; }"); + let mut resolved = ResolvedModel::build(&model); + let diags = sysmlv2_parser::check::validate_model_with(&mut resolved, &model); + assert_eq!(diags.len(), 1); + assert_eq!(resolved.unresolved_references().len(), 1); +} + +// --- typing fixes verified against the value and its redefiners --- + +/// A stand-in for the library's scalar types: the inference resolves +/// `ScalarValues::` and the semantic check classifies declared +/// types by these names, so no library load is needed. +const SCALARS: &str = "package ScalarValues {\n attribute def Boolean;\n attribute def String;\n \ + attribute def Real;\n attribute def Integer :> Real;\n}\n"; + +const TYPING_ON: &str = + r#"{ "rules": { "untyped-usage": "warn", "dimensional-consistency": "warn" } }"#; + +/// Lint `src` beside the scalar stand-ins with both typing rules on. +fn typing_findings(src: &str) -> Vec { + run_with_sources( + &[("scalars.sysml", SCALARS), ("a.sysml", src)], + &Config::from_json(TYPING_ON).unwrap(), + ) + .into_iter() + .filter(|f| f.unit == Some(1)) + .collect() +} + +/// The semantic-check diagnostic count for `src` beside the scalar +/// stand-ins — what a typing fix must not raise. +fn check_count(src: &str) -> usize { + let mut model = Model::new(); + model.add_source("scalars.sysml".to_string(), SCALARS); + model.add_source("a.sysml".to_string(), src); + let mut resolved = ResolvedModel::build(&model); + sysmlv2_parser::check::validate_model_with(&mut resolved, &model).len() +} + +/// Apply every preferred fix of `findings` to `src` (single-unit). +/// Identical edits collapse, as they do in every host's fix-all: both +/// typing rules write the same insert for one attribute. +fn apply_all_fixes(src: &str, findings: &[Finding]) -> String { + let mut edits: Vec<&sysmlv2_lint::Edit> = findings + .iter() + .filter_map(|f| f.fix.as_ref()) + .flat_map(|fx| fx.edits.iter()) + .collect(); + edits.sort_by_key(|e| std::cmp::Reverse(e.span.start)); + edits.dedup_by(|a, b| a.span == b.span && a.replacement == b.replacement); + let mut out = src.to_string(); + for e in edits { + out.replace_range(e.span.start as usize..e.span.end as usize, &e.replacement); + } + out +} + +#[test] +fn typing_fix_is_withheld_when_a_redefiner_contradicts_the_inferred_type() { + // `s = "0"` reads as a String, but the untyped redefiner assigns a + // number and would borrow the new typing: the semantic check would + // report it, so neither rule offers the typing. + let src = "package P {\n private import ScalarValues::*;\n \ + part def D { attribute s = \"0\"; }\n \ + part d : D { attribute :>> s = 5; }\n}\n"; + let findings = typing_findings(src); + let untyped: Vec<&Finding> = findings + .iter() + .filter(|f| f.rule == "untyped-usage") + .collect(); + assert_eq!(untyped.len(), 1, "{findings:?}"); + assert!(untyped[0].message.contains("`s`"), "{}", untyped[0].message); + assert!( + untyped[0].fix.is_none() && untyped[0].suggest.is_none(), + "{untyped:?}" + ); + assert!(untyped[0].alternatives.is_empty()); + assert!( + findings.iter().all(|f| f.rule != "dimensional-consistency"), + "{findings:?}" + ); + // Nothing to apply; the check stays where it was. + assert_eq!( + check_count(&apply_all_fixes(src, &findings)), + check_count(src) + ); +} + +#[test] +fn integral_value_infers_real_when_a_redefiner_is_not_integral() { + // `n = 0` alone reads as an Integer; the redefiner's `0.2` could + // never conform to that, and both values conform to Real. + let src = "package P {\n private import ScalarValues::*;\n \ + part def D { attribute n = 0; }\n \ + part d : D { attribute :>> n = 0.2; }\n}\n"; + let findings = typing_findings(src); + let by_rule = |rule: &str| { + findings + .iter() + .find(|f| f.rule == rule) + .unwrap_or_else(|| panic!("{rule} finding in {findings:?}")) + }; + assert_eq!(by_rule("untyped-usage").suggest.as_deref(), Some("Real")); + let d = by_rule("dimensional-consistency"); + assert_eq!(d.suggest.as_deref(), Some("Real")); + assert!(d.message.contains("infers `Real`"), "{}", d.message); + assert!(d.alternatives.is_empty(), "{:?}", d.alternatives); + let fixed = apply_all_fixes(src, &findings); + assert!(fixed.contains("attribute n : Real = 0;"), "{fixed}"); + assert_eq!(check_count(&fixed), check_count(src), "{fixed}"); +} + +#[test] +fn real_literal_spelling_infers_real_even_when_integral() { + // `0.0` evaluates to an exact zero; the author wrote a real. A bare + // `2` stays an Integer. + let src = "package P {\n private import ScalarValues::*;\n \ + attribute z = 0.0;\n attribute k = 2;\n attribute q = 1/4000.0;\n}\n"; + let findings = typing_findings(src); + let suggest = |name: &str| { + findings + .iter() + .find(|f| { + f.rule == "dimensional-consistency" && f.message.contains(&format!("`{name}`")) + }) + .and_then(|f| f.suggest.clone()) + }; + assert_eq!(suggest("z").as_deref(), Some("Real")); + assert_eq!(suggest("k").as_deref(), Some("Integer")); + assert_eq!(suggest("q").as_deref(), Some("Real")); + let fixed = apply_all_fixes(src, &findings); + assert!( + fixed.contains("attribute z : Real = 0.0;") && fixed.contains("attribute k : Integer = 2;"), + "{fixed}" + ); + assert_eq!(check_count(&fixed), check_count(src), "{fixed}"); +} + +#[test] +fn integer_inference_survives_integral_redefiners() { + // Redefiners that keep to integers do not widen the inference; a + // redefiner typed on its own is not the borrowing kind and does + // not count either. + let src = "package P {\n private import ScalarValues::*;\n \ + part def D { attribute n = 0; }\n \ + part d : D { attribute :>> n = 7; }\n \ + part e : D { attribute :>> n : Real = 0.5; }\n}\n"; + let findings = typing_findings(src); + let f = findings + .iter() + .find(|f| f.rule == "dimensional-consistency") + .expect("inference finding"); + assert_eq!(f.suggest.as_deref(), Some("Integer"), "{}", f.message); + let fixed = apply_all_fixes(src, &findings); + assert_eq!(check_count(&fixed), check_count(src), "{fixed}"); +} + +#[test] +fn import_visibility_recommends_public_for_dependents_reaching_through_a_chain() { + // Q sees Lib::Thing only through P's import (re-exported by Q's own + // import of P): the dependent lives outside P, so `private` would + // hide the member it resolves through. + let f = import_visibility_finding(&[ + ("lib.sysml", IMPORT_LIB), + ("p.sysml", "package P { import Lib::*; }\n"), + ( + "q.sysml", + "package Q { private import P::*; part b : Thing; }\n", + ), + ]); + assert!( + f.message.contains("`public` is required") && f.message.contains("outside `P`"), + "{}", + f.message + ); + assert_eq!(f.suggest.as_deref(), Some("public")); + assert_eq!(f.fix.as_ref().unwrap().label, "Make the import `public`"); + let private = f + .alternatives + .iter() + .find(|a| a.label == "Make the import `private`") + .expect("private rewrite"); + assert!(private.semantic); +} + +#[test] +fn inherited_name_shadow_spells_the_redefinition() { + let src = "package P {\n attribute def Real;\n attribute def SwitchStatus { attribute downlinkPort : Real; }\n attribute def M1 :> SwitchStatus { attribute downlinkPort : Real[6]; }\n attribute def Lan { attribute m1 : M1; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 2, "{findings:?}"); + let owned = findings + .iter() + .find(|f| f.element.as_deref() == Some("P::M1::downlinkPort")) + .expect("owned collision"); + assert_eq!(owned.severity, Severity::Info); + let fix = owned.fix.as_ref().expect("redefinition fix"); + assert!(fix.semantic && !fix.deletes); + assert_eq!(fix.label, "redefine the inherited `downlinkPort` (`:>>`)"); + let fixed = apply_fix(src, fix); + assert!( + fixed + .contains("attribute def M1 :> SwitchStatus { attribute :>> downlinkPort : Real[6]; }"), + "{fixed}" + ); + assert!(rule_findings(&[("a.sysml", &fixed)], "inherited-name-shadow").is_empty()); + // The inheriting usage carries the finding without a fix: nothing to + // redefine on its side. + let both = findings + .iter() + .find(|f| f.element.as_deref() == Some("P::Lan::m1")) + .expect("inherited-twice collision"); + assert!(both.fix.is_none()); + assert!( + both.message + .starts_with("`downlinkPort` is inherited from both `M1` and `SwitchStatus`") + ); +} + +#[test] +fn inherited_name_shadow_keeps_a_differently_spelled_name() { + let src = "package P {\n attribute def Real;\n attribute def A { attribute x : Real; }\n attribute def B :> A { attribute other : Real; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 1, "{findings:?}"); + let fixed = apply_fix(src, findings[0].fix.as_ref().expect("fix")); + assert!( + fixed.contains("attribute other :>> x : Real;"), + "{fixed}" + ); + assert!(rule_findings(&[("a.sysml", &fixed)], "inherited-name-shadow").is_empty()); +} + +#[test] +fn inherited_name_shadow_withholds_a_contradicting_redefinition() { + // A type the hidden feature's type does not admit, an explicit + // multiplicity that differs, and a nested definition: findings without + // fixes rather than repairs the checker would then reject. + let src = "package P {\n attribute def Real;\n attribute def Text;\n attribute def A { attribute x : Real; attribute y : Real[1]; part def N; }\n attribute def B :> A { attribute x : Text; attribute y : Real[6]; part def N; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 3, "{findings:?}"); + assert!(findings.iter().all(|f| f.fix.is_none()), "{findings:?}"); +} + +#[test] +fn inherited_name_shadow_withholds_redefinitions_the_checker_rejects() { + // An end hidden by a non-end, a direction the hidden one does not + // admit, a bound value overridden, a variant hidden: findings without + // fixes (`validateRedefinitionEndConformance`, + // `validateRedefinitionDirectionConformance`, + // `validateFeatureValueOverriding`, variant membership). Parameters + // and connector ends are not among them: those are redefined by + // position and never collide. + let src = "package P {\n attribute def Real;\n part def A;\n part def X { in attribute x : Real; end part e : A; }\n part def Y :> X { out attribute x : Real; part e : A; }\n attribute def V { attribute v : Real = 1; }\n attribute def W :> V { attribute v : Real = 2; }\n variation part def E { variant part e : A; }\n part def F :> E { part e : A; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + let mut elements: Vec<&str> = findings + .iter() + .filter_map(|f| f.element.as_deref()) + .collect(); + elements.sort_unstable(); + assert_eq!( + elements, + ["P::F::e", "P::W::v", "P::Y::e", "P::Y::x"], + "{findings:?}" + ); + assert!(findings.iter().all(|f| f.fix.is_none()), "{findings:?}"); + assert!( + findings.iter().all(|f| f + .message + .ends_with("rename it, or redefine it (`:>>`) with a conforming declaration")), + "{findings:?}" + ); +} + +#[test] +fn inherited_name_shadow_admits_conforming_redefinitions() { + // `inout` admits any direction, a default value may be overridden, + // and nested multiplicities conform. (An end hidden by an end is + // redefined by position and never collides.) + let src = "package P {\n attribute def Real;\n part def A;\n part def X { inout attribute x : Real; end part e : A; }\n part def Y :> X { in attribute x : Real; end part e : A; }\n attribute def V { attribute v : Real default 1; attribute w : Real[0..10]; }\n attribute def W :> V { attribute v : Real = 2; attribute w : Real[2..5]; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 3, "{findings:?}"); + let mut fixed = src.to_string(); + let mut in_order: Vec<&sysmlv2_lint::Finding> = findings.iter().collect(); + in_order.sort_by_key(|f| std::cmp::Reverse(f.span.unwrap().start)); + for f in in_order { + fixed = apply_fix(&fixed, f.fix.as_ref().expect("fix")); + } + assert!( + fixed.contains("part def Y :> X { in attribute :>> x : Real; end part e : A; }"), + "{fixed}" + ); + assert!( + fixed.contains("attribute :>> v : Real = 2; attribute :>> w : Real[2..5];"), + "{fixed}" + ); + assert!(rule_findings(&[("a.sysml", &fixed)], "inherited-name-shadow").is_empty()); +} + +#[test] +fn inherited_name_shadow_targets_the_nearest_of_a_chain_by_qualified_name() { + // `C::x` hides both `B::x` and `A::x`; the fix redefines the nearer, + // qualified — the simple name is ambiguous there — and together with + // the fix on `B::x` the model comes out clean. + let src = "package P {\n attribute def Real;\n part def A { attribute x : Real; }\n part def B :> A { attribute x : Real; }\n part def C :> B { attribute x : Real; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 2, "{findings:?}"); + let mut fixed = src.to_string(); + let mut in_order: Vec<&sysmlv2_lint::Finding> = findings.iter().collect(); + in_order.sort_by_key(|f| std::cmp::Reverse(f.span.unwrap().start)); + for f in in_order { + fixed = apply_fix(&fixed, f.fix.as_ref().expect("fix")); + } + assert!( + fixed.contains("part def B :> A { attribute :>> x : Real; }"), + "{fixed}" + ); + assert!( + fixed.contains("part def C :> B { attribute :>> P::B::x : Real; }"), + "{fixed}" + ); + assert!(rule_findings(&[("a.sysml", &fixed)], "inherited-name-shadow").is_empty()); + // Unrelated bases: redefining either leaves the other, so no fix. + let src = "package P {\n attribute def Real;\n part def A { attribute x : Real; }\n part def Z { attribute x : Real; }\n part def C :> A, Z { attribute x : Real; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 1, "{findings:?}"); + assert!(findings[0].fix.is_none(), "{findings:?}"); +} + +#[test] +fn inherited_name_shadow_targets_the_hidden_member_by_its_own_name() { + // The collision is on the hidden member's short name; the + // redefinition names it by its declared name. An owned member with + // only a short name gets the redefinition after the bracket. + let src = "package P {\n attribute def Real;\n attribute def A { attribute long : Real; }\n attribute def B :> A { attribute x : Real; }\n attribute def C :> A { attribute : Real; }\n}\n"; + let findings = rule_findings(&[("a.sysml", src)], "inherited-name-shadow"); + assert_eq!(findings.len(), 2, "{findings:?}"); + let mut fixed = src.to_string(); + for f in findings.iter().rev() { + fixed = apply_fix(&fixed, f.fix.as_ref().expect("fix")); + } + assert!( + fixed.contains("attribute def B :> A { attribute x :>> long : Real; }"), + "{fixed}" + ); + assert!( + fixed.contains("attribute def C :> A { attribute :>> long : Real; }"), + "{fixed}" + ); + assert!(rule_findings(&[("a.sysml", &fixed)], "inherited-name-shadow").is_empty()); +} + +/// A flat package of thousands of definitions lints in linear time: the +/// reference index and the per-owner sibling-name index are built once +/// per pass, never once per definition or finding. +#[test] +fn flat_package_of_thousands_of_definitions_lints_quickly() { + const N: usize = 2_000; + let mut src = String::from("package P {\n"); + for i in 0..N { + // Every name is off the PascalCase convention, so each definition + // yields a naming finding whose suggestion is checked against its + // siblings; odd definitions specialize their predecessor, so + // exactly the even ones are referenced. + if i % 2 == 1 { + writeln!(src, " part def item_{i} :> item_{};", i - 1).unwrap(); + } else { + writeln!(src, " part def item_{i};").unwrap(); + } + } + src.push_str("}\n"); + let config = Config::from_json(r#"{ "rules": { "unused-definition": "warn" } }"#).unwrap(); + let mut model = Model::new(); + model.add_source("a.sysml".to_string(), &src); + let mut resolved = ResolvedModel::build(&model); + let started = std::time::Instant::now(); + let findings = lint(&mut resolved, &config); + let elapsed = started.elapsed(); + let naming: Vec<&Finding> = findings + .iter() + .filter(|f| f.rule == "naming-convention") + .collect(); + let unused = findings + .iter() + .filter(|f| f.rule == "unused-definition") + .count(); + assert_eq!(naming.len(), N); + assert_eq!(unused, N / 2); + assert!( + naming + .iter() + .all(|f| f.suggest.as_deref().is_some_and(|s| s.starts_with("Item"))), + "every naming finding carries its converted suggestion" + ); + assert!( + elapsed < std::time::Duration::from_secs(1), + "lint pass over {N} definitions took {elapsed:?}" + ); +} + +/// The rule inventory and the id enum are one table: every configurable +/// id has an inventory entry, every inventory entry parses back to the +/// variant it was written with, and no spelling is claimed twice. A +/// misspelled id can no longer reach a lookup, so the inventory is what +/// has to stay in step. +#[test] +fn every_rule_id_matches_exactly_one_inventory_entry() { + let mut seen: Vec<&str> = Vec::new(); + for id in RuleId::ALL { + assert_eq!(id.to_string(), id.id(), "`Display` is the wire spelling"); + assert_eq!( + id.id().parse::().expect("its own spelling parses"), + *id + ); + assert!(!seen.contains(&id.id()), "duplicate spelling `{id}`"); + seen.push(id.id()); + let entries = RULES.iter().filter(|r| r.id == *id).count(); + let want = usize::from(*id != RuleId::LintConfig); + assert_eq!(entries, want, "`{id}` has {entries} inventory entries"); + assert_eq!(id.rule().is_some(), want == 1); + } + assert_eq!( + RULES.len() + 1, + RuleId::ALL.len(), + "only `lint-config` is extra" + ); +} + +/// An id no rule carries is rejected once, by name: reading it fails +/// with the unknown-rule error, and config naming it complains about the +/// id rather than about whatever value was written beside it. +#[test] +fn an_unknown_rule_id_is_reported_as_the_unknown_id() { + let err = "no-such-rule".parse::().expect_err("not a rule"); + assert_eq!(err.to_string(), "unknown lint rule `no-such-rule`"); + let cfg = Config::from_json(r#"{ "rules": { "no-such-rule": "loud" } }"#).unwrap(); + let findings = run(&[("a.sysml", CALC)], &cfg); + assert_eq!(findings.len(), 1, "{findings:?}"); + assert_eq!(findings[0].rule, "lint-config"); + assert_eq!(findings[0].message, "unknown lint rule `no-such-rule`"); +} + +/// Configuration fails outright only when the text is not JSON at all; +/// anything readable reports through findings instead, so a host can +/// tell "I could not read your file" from "your file says something +/// odd" without matching on message text. +#[test] +fn only_unreadable_config_is_an_error() { + let Err(err) = Config::from_json("{ this is not json") else { + panic!("text that is not JSON has no configuration"); + }; + assert!(matches!(err, LintError::ConfigNotJson(_)), "{err:?}"); + assert!(err.to_string().starts_with("config is not JSON: "), "{err}"); + let _boxed: Box = Box::new(err); + let cfg = Config::from_json(r#"{ "rules": { "indentation": { "size": "wide" } } }"#) + .expect("readable JSON"); + let findings = run(&[("a.sysml", CALC)], &cfg); + assert_eq!(findings.len(), 1, "{findings:?}"); + assert_eq!(findings[0].rule, "lint-config"); +} diff --git a/crates/sysmlv2-lint/tests/qualified.rs b/crates/sysmlv2-lint/tests/qualified.rs index 970da42..743f10f 100644 --- a/crates/sysmlv2-lint/tests/qualified.rs +++ b/crates/sysmlv2-lint/tests/qualified.rs @@ -10,11 +10,16 @@ use sysmlv2_parser::model::Model; /// Lint `src` (one unit) with source text against the vendored /// standard library. fn run(src: &str, config: &Config) -> Vec { + run_in("t.sysml", src, config) +} + +/// [`run`] for a unit named `name` (the extension selects the dialect). +fn run_in(name: &str, src: &str, config: &Config) -> Vec { let mut model = Model::new(); model .load_library_dir(&sysmlv2_testkit::library_dir()) .expect("library"); - model.add_source("t.sysml", src); + model.add_source(name, src); let mut resolved = ResolvedModel::build(&model); let unit = resolved.reference_sites().last().expect("sites").unit; lint_with_sources(&mut resolved, config, &[(unit, src)]) @@ -214,3 +219,58 @@ fn necessary_qualification_is_not_inconsistency() { assert!(f.fix.is_some(), "{f:?}"); } } + +/// A reserved word used as a name stays quoted in every suggested +/// spelling: the written `'part'::'view'` *is* the full spelling (no +/// finding), the full and minimal re-spellings quote, and the fix +/// parses. +#[test] +fn reserved_word_names_stay_quoted_in_suggestions() { + let src = "package 'part' {\n part def 'view';\n part a : 'part'::'view';\n \ + part b : 'view';\n}\n"; + let findings = run( + src, + &cfg(r#"{ "rules": { "qualified-names": { "severity": "warn", "style": "qualified" } } }"#), + ); + let q = qualified(&findings); + assert_eq!(q.len(), 1, "{findings:?}"); + assert_eq!(q[0].suggest.as_deref(), Some("'part'::'view'")); + let fixed = apply_fix(src, q[0]); + assert!(fixed.contains("part b : 'part'::'view';"), "{fixed}"); + let mut model = Model::new(); + let unit = model.add_source("t.sysml", &fixed); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + + let findings = run( + src, + &cfg(r#"{ "rules": { "qualified-names": { "severity": "warn", "style": "minimal" } } }"#), + ); + let q = qualified(&findings); + assert_eq!(q.len(), 1, "{findings:?}"); + assert_eq!(q[0].suggest.as_deref(), Some("'view'")); +} + +/// The unit's dialect governs a suggested spelling: a word only the +/// other dialect reserves stays bare, so the written text is already +/// the full spelling (no finding) and a fix never fights the formatter. +#[test] +fn dialect_governs_suggested_spellings() { + let qualified_style = + cfg(r#"{ "rules": { "qualified-names": { "severity": "warn", "style": "qualified" } } }"#); + // `part` is a SysML word only: bare in KerML. + let kerml = "package part {\n classifier x;\n feature f : part::x;\n}\n"; + let findings = run_in("t.kerml", kerml, &qualified_style); + assert!(qualified(&findings).is_empty(), "{findings:?}"); + // `classifier` is a KerML word only: bare in SysML. + let sysml = "package classifier {\n part def x;\n part f : classifier::x;\n}\n"; + let findings = run_in("t.sysml", sysml, &qualified_style); + assert!(qualified(&findings).is_empty(), "{findings:?}"); + // And the same KerML reference under the minimal style shortens to + // the bare word, which is what the KerML formatter prints. + let minimal_style = + cfg(r#"{ "rules": { "qualified-names": { "severity": "warn", "style": "minimal" } } }"#); + let findings = run_in("t.kerml", kerml, &minimal_style); + let q = qualified(&findings); + assert_eq!(q.len(), 1, "{findings:?}"); + assert_eq!(q[0].suggest.as_deref(), Some("x")); +} diff --git a/crates/sysmlv2-lsp/Cargo.toml b/crates/sysmlv2-lsp/Cargo.toml index b7f0503..b7075c9 100644 --- a/crates/sysmlv2-lsp/Cargo.toml +++ b/crates/sysmlv2-lsp/Cargo.toml @@ -19,6 +19,7 @@ sysmlv2-solve.workspace = true lsp-server.workspace = true lsp-types.workspace = true crossbeam-channel.workspace = true +serde.workspace = true serde_json.workspace = true [dev-dependencies] diff --git a/crates/sysmlv2-lsp/src/autofix.rs b/crates/sysmlv2-lsp/src/autofix.rs index 5a19e44..111c37e 100644 --- a/crates/sysmlv2-lsp/src/autofix.rs +++ b/crates/sysmlv2-lsp/src/autofix.rs @@ -27,6 +27,8 @@ //! repair text — which the suffix path realizes as a snippet stop //! (see `item_edits` in `nav`) and the insertion path gets for free. +use crate::position::offset32; + /// What a completion accept should additionally fix. pub(crate) struct Repairs { /// Appended to the completion's inserted text. @@ -124,7 +126,7 @@ pub(crate) fn statement_repairs( let at = last_closer_end .or(semicolon_at) .or(chain_end) - .map(|i| offset + i as u32) + .map(|i| offset + offset32(i)) .unwrap_or(offset); Some(Repairs { suffix: String::new(), @@ -195,18 +197,22 @@ fn open_brackets(stmt: &str) -> Option { #[cfg(test)] mod tests { - use super::statement_repairs; + use super::{offset32, statement_repairs}; fn repairs(text: &str, cursor: &str) -> Option<(String, Option<(u32, String)>)> { - let offset = (text.find(cursor).expect("cursor") + cursor.len()) as u32; - let stmt_start = text[..offset as usize] - .rfind([';', '{', '}']) - .map(|i| i + 1) - .unwrap_or(0) as u32; - let prefix_end = text[..offset as usize] - .rfind(|c: char| !(c.is_ascii_alphanumeric() || c == '_')) - .map(|i| i + 1) - .unwrap_or(0) as u32; + let offset = offset32(text.find(cursor).expect("cursor") + cursor.len()); + let stmt_start = offset32( + text[..offset as usize] + .rfind([';', '{', '}']) + .map(|i| i + 1) + .unwrap_or(0), + ); + let prefix_end = offset32( + text[..offset as usize] + .rfind(|c: char| !(c.is_ascii_alphanumeric() || c == '_')) + .map(|i| i + 1) + .unwrap_or(0), + ); statement_repairs(text, stmt_start, prefix_end, offset).map(|r| (r.suffix, r.insert)) } @@ -221,7 +227,7 @@ mod tests { let text = "package P {\n attribute g = 9.8 [m]\n}\n"; let (suffix, insert) = repairs(text, "[m").expect("repairs"); assert_eq!(suffix, ""); - let at = text.find("m]").unwrap() as u32 + 2; + let at = offset32(text.find("m]").unwrap()) + 2; assert_eq!(insert, Some((at, ";".to_string()))); } @@ -230,7 +236,7 @@ mod tests { let text = "package P {\n attribute g = 9.8 [m;\n}\n"; let (suffix, insert) = repairs(text, "[m").expect("repairs"); assert_eq!(suffix, ""); - let at = text.find(';').unwrap() as u32; + let at = offset32(text.find(';').unwrap()); assert_eq!(insert, Some((at, "]".to_string()))); } @@ -247,7 +253,7 @@ mod tests { let text = "package P {\n attribute v = fuelTank.over.volume\n}\n"; let (suffix, insert) = repairs(text, "over").expect("repairs"); assert_eq!(suffix, ""); - let at = text.find(".volume").unwrap() as u32 + 7; + let at = offset32(text.find(".volume").unwrap()) + 7; assert_eq!(insert, Some((at, ";".to_string()))); } @@ -256,7 +262,7 @@ mod tests { let text = "package P {\n attribute v = a[b.chain]\n}\n"; let (suffix, insert) = repairs(text, "a[b").expect("repairs"); assert_eq!(suffix, ""); - let at = text.find("chain]").unwrap() as u32 + 6; + let at = offset32(text.find("chain]").unwrap()) + 6; assert_eq!(insert, Some((at, ";".to_string()))); } @@ -295,7 +301,7 @@ mod tests { // prefix_end sits before the quote (the completion's replace // range absorbs it), so the scan never sees a dangling string. let text = "package P {\n attribute g = 9.8 ['m\n}\n"; - let offset = (text.find("['m").unwrap() + 3) as u32; + let offset = offset32(text.find("['m").unwrap() + 3); let r = statement_repairs(text, 12, offset - 2, offset).expect("repairs"); assert_eq!(r.suffix, "];"); } diff --git a/crates/sysmlv2-lsp/src/autoimport.rs b/crates/sysmlv2-lsp/src/autoimport.rs index 22e62de..dd50243 100644 --- a/crates/sysmlv2-lsp/src/autoimport.rs +++ b/crates/sysmlv2-lsp/src/autoimport.rs @@ -15,7 +15,8 @@ //! redundant, never wrong: the qualified target resolves from the root //! namespace regardless. -use sysmlv2_parser::ast::{Import, Member, MemberKind, Name, SourceUnit, Visibility, escape_name}; +use crate::position::offset32; +use sysmlv2_parser::ast::{Dialect, Import, Member, MemberKind, Name, SourceUnit, Visibility}; use sysmlv2_parser::span::Span; /// One namespace body on the cursor's ancestor chain. @@ -31,6 +32,9 @@ struct Scope<'a> { /// word being completed (the phantom declaration guard). pub(crate) struct AutoImport<'a> { text: &'a str, + /// The unit's dialect: the reserved-word table an inserted import + /// path must respect. + dialect: Dialect, scopes: Vec>, partial: Span, } @@ -60,6 +64,7 @@ impl<'a> AutoImport<'a> { } AutoImport { text, + dialect: unit.dialect, scopes, partial, } @@ -108,7 +113,7 @@ impl<'a> AutoImport<'a> { /// before the first substantive member as a `private import` (the /// non-re-exporting default). fn insertion(&self, qualified: &str) -> (u32, String) { - let path = escape_qualified(qualified); + let path = escape_qualified(self.dialect, qualified); let scope = self .scopes .iter() @@ -160,7 +165,7 @@ impl<'a> AutoImport<'a> { .take_while(|c| *c == ' ' || *c == '\t') .collect(); ( - line_start as u32, + offset32(line_start), format!("{indent}private import {path};\n"), ) } @@ -271,13 +276,11 @@ fn path_matches(p: &str, t: &str) -> bool { p == t || p.ends_with(&format!("::{t}")) || t.ends_with(&format!("::{p}")) } -/// A root-qualified path in textual notation, restricted names quoted. -pub(crate) fn escape_qualified(qualified: &str) -> String { - qualified - .split("::") - .map(escape_name) - .collect::>() - .join("::") +/// A root-qualified path in the textual notation of `dialect`: +/// restricted names and the dialect's reserved words quoted, so the +/// import statement parses and the formatter keeps it. +pub(crate) fn escape_qualified(dialect: Dialect, qualified: &str) -> String { + sysmlv2_parser::name::spell_path(Some(dialect), qualified.split("::")) } /// The byte range a completion for `name` should replace. The partial @@ -298,12 +301,12 @@ pub(crate) fn replace_range_for(text: &str, partial_start: u32, offset: u32, nam if text[..start].ends_with('\'') { start -= 1; } - Span::new(start as u32, offset) + Span::new(offset32(start), offset) } #[cfg(test)] mod tests { - use super::AutoImport; + use super::{AutoImport, offset32}; use sysmlv2_parser::span::Span; /// Cursor at the end of `cursor`'s first occurrence; the partial @@ -318,8 +321,8 @@ mod tests { let auto = AutoImport::new( text, &parse.unit, - at as u32, - Span::new(word_start as u32, at as u32), + offset32(at), + Span::new(offset32(word_start), offset32(at)), ); auto.import_edit(name, qualified) } diff --git a/crates/sysmlv2-lsp/src/lib.rs b/crates/sysmlv2-lsp/src/lib.rs index 3b4a8a3..6147f31 100644 --- a/crates/sysmlv2-lsp/src/lib.rs +++ b/crates/sysmlv2-lsp/src/lib.rs @@ -14,11 +14,13 @@ //! The entry points are [`run_stdio`] (the `sysmlv2 lsp` verb) and [`run`] //! over an arbitrary [`Connection`] (the in-process test harness). -// lsp-types mandates `Uri` map keys (WorkspaceEdit::changes, the -// document store); the type is never mutated while keyed. -#![allow(clippy::mutable_key_type)] +// Every span in the toolkit is a `u32` byte range, so document +// offsets and lengths cross between `usize` and `u32` constantly; the +// conversion goes through `position::offset32`, which says so once and +// refuses rather than wrapping. +#![warn(clippy::cast_possible_truncation)] -use lsp_server::{Connection, ErrorCode, Message, Notification, Request, Response}; +use lsp_server::{Connection, ErrorCode, Message, Notification, Request, RequestId, Response}; use lsp_types::notification::{ DidChangeTextDocument, DidCloseTextDocument, DidOpenTextDocument, Notification as _, PublishDiagnostics, @@ -35,13 +37,19 @@ use lsp_types::{ PublishDiagnosticsParams, ServerCapabilities, ServerInfo, TextDocumentSyncCapability, TextDocumentSyncKind, TextEdit, Uri, }; -use std::collections::HashMap; +use serde::de::DeserializeOwned; +use std::collections::{BTreeMap, HashMap, HashSet}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use sysmlv2_parser::ast::Dialect; use sysmlv2_parser::check; use sysmlv2_parser::parser::{parse_kerml_source, parse_source}; mod autofix; mod autoimport; +// lsp-types mandates `Uri` map keys (`WorkspaceEdit::changes`, the +// document store), and `Uri` has interior mutability; nothing here +// mutates one while it is a key. +#[allow(clippy::mutable_key_type)] mod nav; mod outline; mod position; @@ -49,7 +57,7 @@ mod push; pub mod tokens; mod worker; -pub use outline::document_symbols; +pub use outline::{document_symbols, spell_name, spell_symbols}; pub use position::{Encoding, Mapper}; pub use push::PushServer; @@ -81,6 +89,12 @@ pub fn run_with_library( /// [`run_with_library`] with a configurable workspace-tier debounce (the /// test harness shortens it). +/// +/// The syntax tier parses on the loop's own thread, and the parser's +/// nesting bound assumes a stack sized for it, which a host's thread is +/// not: the loop runs on a thread that reserves one +/// ([`sysmlv2_parser::parser::on_parsing_stack`]). The workspace tier +/// reserves the same size on the worker it spawns. pub fn run_with_options( connection: Connection, library: Option, @@ -115,15 +129,42 @@ pub fn run_with_options( nav.set_hide_redundant_value_hints(hide_redundant_value_hints(&init).unwrap_or(true)); nav.set_infer_unit_types(infer_unit_types(&init).unwrap_or(true)); nav.set_snippet_completions(snippet_completions(&init)); - Server { + let client = connection.sender.clone(); + let server = Server { connection, encoding, - docs: HashMap::new(), + docs: BTreeMap::new(), nav, worker, root, - } - .main_loop() + reported: HashSet::new(), + }; + sysmlv2_parser::parser::on_parsing_stack( + "sysmlv2-lsp", + |err| say_the_stack_was_refused(&client, err), + move || server.main_loop(), + ) +} + +/// Tell the client's log that the loop's stack could not be reserved. +/// +/// The session still serves: the loop runs on the thread the host started +/// it on, which holds a fraction of the nesting the parser accepts. What +/// it cannot survive is a document nested past that — the descent runs +/// the stack out, and the overflow ends the whole server, with no +/// diagnostic, no unwind and no session left to show a popup in. So this +/// goes to the log, where it is there to be read afterwards. +fn say_the_stack_was_refused(client: &crossbeam_channel::Sender, err: &std::io::Error) { + let _ = client.send(Message::Notification(Notification::new( + lsp_types::notification::LogMessage::METHOD.to_string(), + lsp_types::LogMessageParams { + typ: lsp_types::MessageType::ERROR, + message: format!( + "could not reserve the stack the parser's nesting bound assumes: {err}. \ + A deeply nested document may end this server without a diagnostic." + ), + }, + ))); } /// `initializationOptions.hideRedundantValueHints`: suppress @@ -194,10 +235,12 @@ pub(crate) fn capabilities(encoding: Encoding) -> ServerCapabilities { code_action_kinds: Some(vec![ lsp_types::CodeActionKind::QUICKFIX, lsp_types::CodeActionKind::SOURCE, + lsp_types::CodeActionKind::SOURCE_FIX_ALL, lsp_types::CodeActionKind::SOURCE_ORGANIZE_IMPORTS, lsp_types::CodeActionKind::new("source.sortImports"), lsp_types::CodeActionKind::REFACTOR_EXTRACT, lsp_types::CodeActionKind::REFACTOR_INLINE, + lsp_types::CodeActionKind::new("refactor.move"), ]), ..Default::default() }, @@ -234,17 +277,80 @@ pub(crate) fn capabilities(encoding: Encoding) -> ServerCapabilities { /// One open document: the full current text plus the client's version /// counter (echoed back on diagnostics so stale publishes are discarded). pub(crate) struct Document { - pub(crate) text: String, + /// Shared: a document's text is snapshotted into every workspace + /// job and out of the document store on most requests (to escape + /// the borrow the model build takes), which on a large unit made + /// per-keystroke copies of the whole file. + pub(crate) text: std::sync::Arc, pub(crate) version: i32, } +/// `sysmlv2/splitPlan`: plan a package's split into one unit per nested +/// package (the file tree, collisions and renames), for an editor's +/// wizard. Params: [`SplitRequestParams`]; result: the plan. +pub const SPLIT_PLAN_METHOD: &str = "sysmlv2/splitPlan"; +/// `sysmlv2/split`: the same plan with its annotated workspace edit +/// (file creations and the root rewrite under one change annotation +/// naming the split). Refusals answer `RequestFailed` with the reason. +pub const SPLIT_METHOD: &str = "sysmlv2/split"; + +/// Parameters of [`SPLIT_PLAN_METHOD`] and [`SPLIT_METHOD`]. +#[derive(serde::Deserialize, Debug)] +#[serde(rename_all = "camelCase")] +pub struct SplitRequestParams { + /// The open document `position` points into; unused with `package`. + #[serde(default)] + pub text_document: Option, + /// The package under this position's name. + #[serde(default)] + pub position: Option, + /// The package by qualified name (quoted segments allowed); takes + /// precedence over `position`. + #[serde(default)] + pub package: Option, + #[serde(default)] + pub naming: SplitNamingParam, + /// The uri prefix the new units are named under; by default the + /// root unit's uri without its extension. + #[serde(default)] + pub directory: Option, +} + +/// File naming of a split request. +#[derive(serde::Deserialize, Debug, Clone, Copy, Default, PartialEq, Eq)] +#[serde(rename_all = "lowercase")] +pub enum SplitNamingParam { + /// The package name as written. + #[default] + Keep, + /// Letters, digits, `.`, `_` and `-` only. + Slug, +} + +enum SplitRefusal { + /// Malformed or incomplete parameters. + Params(String), + /// A well-formed request the model refuses (not a package, nothing + /// nested, a failed dry run). + Refused(String), +} + pub(crate) struct Server { pub(crate) connection: Connection, pub(crate) encoding: Encoding, - pub(crate) docs: HashMap, + /// Ordered, so the unit order every tier derives from it is the + /// same run to run: unit indexes, the resolver's "first declaration + /// wins" tie-break on an ambiguity, and the order of workspace + /// symbols all follow it, and a hash order made them drift between + /// the background worker and navigation on the same model. + pub(crate) docs: BTreeMap, pub(crate) nav: nav::Nav, pub(crate) worker: worker::Worker, pub(crate) root: Option, + /// Client-facing failure messages already sent, so a failure that + /// recurs per keystroke is announced once (see + /// [`Server::show_message_once`]). + pub(crate) reported: HashSet, } impl Server { @@ -264,40 +370,67 @@ impl Server { Ok(()) } + /// Answer one request. A request the server cannot serve as asked + /// — unknown method, malformed parameters, an answer the model + /// panicked computing — is answered with the matching error; only + /// a closed transport is an `Err` here. pub(crate) fn handle_request(&mut self, req: Request) -> Result<(), Error> { - let response = match req.method.as_str() { + let (id, method) = (req.id.clone(), req.method.clone()); + // A panic deep in the model, evaluator or solver would + // otherwise take the whole session down with one request. The + // server's own state may be part-updated afterwards, so the + // caveat `AssertUnwindSafe` waives is real — but a stale cache + // an edit invalidates beats a dead editor. + let response = match catch_unwind(AssertUnwindSafe(|| self.respond(req))) { + Ok(Ok(response) | Err(response)) => response, + Err(payload) => { + let reason = panic_reason(payload.as_ref()); + self.show_message_once( + lsp_types::MessageType::ERROR, + format!("{method} failed: {reason}"), + ); + Response::new_err( + id, + ErrorCode::InternalError as i32, + format!("{method}: {reason}"), + ) + } + }; + self.report_nav_failures(); + self.connection.sender.send(Message::Response(response))?; + Ok(()) + } + + /// The response to one request. `Err` carries the response to a + /// request whose parameters did not deserialize ([`cast`]'s + /// `InvalidParams`), so a handler bails with `?` and the request + /// is still answered. + fn respond(&mut self, req: Request) -> Result { + Ok(match req.method.as_str() { Formatting::METHOD => { - let params: DocumentFormattingParams = serde_json::from_value(req.params)?; + let (id, params): (_, DocumentFormattingParams) = cast(req)?; let (edits, refusal) = self.format(¶ms.text_document.uri); if let Some(message) = refusal { // A silent no-op reads as "formatting is broken" — // say why the document was left alone, and answer // null (refused) rather than [] (nothing to do) so // clients can tell the cases apart. - self.connection - .sender - .send(Message::Notification(Notification::new( - lsp_types::notification::ShowMessage::METHOD.to_string(), - lsp_types::ShowMessageParams { - typ: lsp_types::MessageType::WARNING, - message, - }, - )))?; - Response::new_ok(req.id, serde_json::Value::Null) + self.show_message(lsp_types::MessageType::WARNING, message); + Response::new_ok(id, serde_json::Value::Null) } else { - Response::new_ok(req.id, edits) + Response::new_ok(id, edits) } } DocumentSymbolRequest::METHOD => { - let params: DocumentSymbolParams = serde_json::from_value(req.params)?; - Response::new_ok(req.id, self.symbols(¶ms.text_document.uri)) + let (id, params): (_, DocumentSymbolParams) = cast(req)?; + Response::new_ok(id, self.symbols(¶ms.text_document.uri)) } SemanticTokensFullRequest::METHOD => { - let params: lsp_types::SemanticTokensParams = serde_json::from_value(req.params)?; - Response::new_ok(req.id, self.semantic_tokens(¶ms.text_document.uri)) + let (id, params): (_, lsp_types::SemanticTokensParams) = cast(req)?; + Response::new_ok(id, self.semantic_tokens(¶ms.text_document.uri)) } GotoDefinition::METHOD => { - let p: lsp_types::GotoDefinitionParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::GotoDefinitionParams) = cast(req)?; let d = &p.text_document_position_params; let loc = self .offset_of(&d.text_document.uri, d.position) @@ -305,10 +438,10 @@ impl Server { self.nav .definition(&self.docs, &d.text_document.uri, o, self.encoding) }); - Response::new_ok(req.id, loc.map(lsp_types::GotoDefinitionResponse::Scalar)) + Response::new_ok(id, loc.map(lsp_types::GotoDefinitionResponse::Scalar)) } References::METHOD => { - let p: lsp_types::ReferenceParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::ReferenceParams) = cast(req)?; let d = &p.text_document_position; let locs = self .offset_of(&d.text_document.uri, d.position) @@ -321,10 +454,10 @@ impl Server { self.encoding, ) }); - Response::new_ok(req.id, locs) + Response::new_ok(id, locs) } DocumentHighlightRequest::METHOD => { - let p: lsp_types::DocumentHighlightParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::DocumentHighlightParams) = cast(req)?; let d = &p.text_document_position_params; let hl = self .offset_of(&d.text_document.uri, d.position) @@ -333,10 +466,10 @@ impl Server { .references(&self.docs, &d.text_document.uri, o, true, self.encoding) .map(|locs| nav::highlights_in(locs, &d.text_document.uri)) }); - Response::new_ok(req.id, hl) + Response::new_ok(id, hl) } HoverRequest::METHOD => { - let p: lsp_types::HoverParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::HoverParams) = cast(req)?; let d = &p.text_document_position_params; let hover = self .offset_of(&d.text_document.uri, d.position) @@ -353,10 +486,10 @@ impl Server { range: Some(range), }) }); - Response::new_ok(req.id, hover) + Response::new_ok(id, hover) } Rename::METHOD => { - let p: lsp_types::RenameParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::RenameParams) = cast(req)?; let d = &p.text_document_position; let result = match self.offset_of(&d.text_document.uri, d.position) { Some(o) => self.nav.rename( @@ -373,44 +506,44 @@ impl Server { // The cached session advanced past the client's // text; resync via the client's didChange. self.nav.invalidate(); - Response::new_ok(req.id, Some(edit)) + Response::new_ok(id, Some(edit)) } Err(msg) => { self.nav.invalidate(); - Response::new_err(req.id, ErrorCode::RequestFailed as i32, msg) + Response::new_err(id, ErrorCode::RequestFailed as i32, msg) } } } Completion::METHOD => { - let p: lsp_types::CompletionParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::CompletionParams) = cast(req)?; let d = &p.text_document_position; let offset = self.offset_of(&d.text_document.uri, d.position); let items = self.nav .completions(&self.docs, &d.text_document.uri, offset, self.encoding); - Response::new_ok(req.id, Some(lsp_types::CompletionResponse::Array(items))) + Response::new_ok(id, Some(lsp_types::CompletionResponse::Array(items))) } InlayHintRequest::METHOD => { - let p: lsp_types::InlayHintParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::InlayHintParams) = cast(req)?; let hints = self .nav .inlay_hints(&self.docs, &p.text_document.uri, self.encoding); - Response::new_ok(req.id, Some(hints)) + Response::new_ok(id, Some(hints)) } CodeLensRequest::METHOD => { - let p: lsp_types::CodeLensParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::CodeLensParams) = cast(req)?; let lenses = self .nav .code_lenses(&self.docs, &p.text_document.uri, self.encoding); - Response::new_ok(req.id, Some(lenses)) + Response::new_ok(id, Some(lenses)) } CodeActionRequest::METHOD => { - let p: lsp_types::CodeActionParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::CodeActionParams) = cast(req)?; let actions = self.code_actions(&p); - Response::new_ok(req.id, Some(actions)) + Response::new_ok(id, Some(actions)) } WorkspaceSymbolRequest::METHOD => { - let p: lsp_types::WorkspaceSymbolParams = serde_json::from_value(req.params)?; + let (id, p): (_, lsp_types::WorkspaceSymbolParams) = cast(req)?; let mut out = Vec::new(); for (uri, doc) in &self.docs { let parse = match dialect_of(uri) { @@ -421,24 +554,58 @@ impl Server { let symbols = outline::document_symbols(&parse.unit, &doc.text, &mapper); nav::flatten_symbols(&symbols, uri, &p.query, &mut out); } - Response::new_ok(req.id, Some(out)) + Response::new_ok(id, Some(out)) + } + SPLIT_PLAN_METHOD | SPLIT_METHOD => { + let with_edit = req.method == SPLIT_METHOD; + let (id, p): (_, SplitRequestParams) = cast(req)?; + match self.split_request(p, with_edit) { + Ok(v) => Response::new_ok(id, v), + Err(SplitRefusal::Params(m)) => { + Response::new_err(id, ErrorCode::InvalidParams as i32, m) + } + Err(SplitRefusal::Refused(m)) => { + Response::new_err(id, ErrorCode::RequestFailed as i32, m) + } + } } + #[cfg(test)] + PANIC_METHOD => panic!("{PANIC_REASON}"), _ => Response::new_err( req.id, ErrorCode::MethodNotFound as i32, format!("unsupported method: {}", req.method), ), - }; - self.connection.sender.send(Message::Response(response))?; - Ok(()) + }) } + /// Handle one notification. A malformed one — or one whose + /// handling panics — is reported and dropped: notifications have + /// no reply to carry the error, and one bad message must not end + /// the session. pub(crate) fn handle_notification(&mut self, n: Notification) -> Result<(), Error> { + let method = n.method.clone(); + match catch_unwind(AssertUnwindSafe(|| self.dispatch_notification(n))) { + Ok(result) => result, + Err(payload) => { + let reason = panic_reason(payload.as_ref()); + self.show_message_once( + lsp_types::MessageType::ERROR, + format!("{method} failed: {reason}"), + ); + Ok(()) + } + } + } + + fn dispatch_notification(&mut self, n: Notification) -> Result<(), Error> { match n.method.as_str() { DidOpenTextDocument::METHOD => { - let p: DidOpenTextDocumentParams = serde_json::from_value(n.params)?; + let Some(p): Option = self.notification_params(n) else { + return Ok(()); + }; let doc = Document { - text: p.text_document.text, + text: p.text_document.text.into(), version: p.text_document.version, }; self.publish_diagnostics(&p.text_document.uri, &doc)?; @@ -446,13 +613,16 @@ impl Server { self.schedule_workspace(); } DidChangeTextDocument::METHOD => { - let p: DidChangeTextDocumentParams = serde_json::from_value(n.params)?; + let Some(p): Option = self.notification_params(n) + else { + return Ok(()); + }; // Full sync: the last change carries the whole new text. let Some(change) = p.content_changes.into_iter().last() else { return Ok(()); }; let doc = Document { - text: change.text, + text: change.text.into(), version: p.text_document.version, }; self.publish_diagnostics(&p.text_document.uri, &doc)?; @@ -460,17 +630,93 @@ impl Server { self.schedule_workspace(); } DidCloseTextDocument::METHOD => { - let p: DidCloseTextDocumentParams = serde_json::from_value(n.params)?; + let Some(p): Option = self.notification_params(n) + else { + return Ok(()); + }; self.docs.remove(&p.text_document.uri); // Clear the document's diagnostics from the editor. self.send_diagnostics(&p.text_document.uri, Vec::new(), None)?; self.schedule_workspace(); } + #[cfg(test)] + PANIC_METHOD => panic!("{PANIC_REASON}"), _ => {} // initialized, $/cancelRequest, …: nothing to do } Ok(()) } + /// A notification's parameters; a malformed notification logs the + /// problem to the client and yields `None`. + fn notification_params(&self, n: Notification) -> Option

{ + match serde_json::from_value(n.params) { + Ok(p) => Some(p), + Err(e) => { + self.log_message( + lsp_types::MessageType::WARNING, + format!("{}: invalid params: {e}", n.method), + ); + None + } + } + } + + /// Pass on what navigation could not do and had no channel of its + /// own to say — an unreadable library leaves hover, definition, + /// references and rename answering nothing at all. + fn report_nav_failures(&mut self) { + for report in self.nav.take_reports() { + // What the user has to act on is an error; the rest is + // background for whoever reads the log. + if report.show { + self.show_message_once(lsp_types::MessageType::ERROR, report.message); + } else { + self.log_message_once(lsp_types::MessageType::WARNING, report.message); + } + } + } + + /// [`Self::log_message`] the first time this exact message comes + /// up; see [`Self::show_message_once`]. + fn log_message_once(&mut self, typ: lsp_types::MessageType, message: String) { + if self.reported.insert(message.clone()) { + self.log_message(typ, message); + } + } + + /// [`Self::show_message`] the first time this exact message comes + /// up. A failure that recurs — a request that panics on every + /// hover, a library that stays unreadable — would otherwise put a + /// popup on screen per keystroke. + fn show_message_once(&mut self, typ: lsp_types::MessageType, message: String) { + if self.reported.insert(message.clone()) { + self.show_message(typ, message); + } + } + + /// `window/showMessage` to the client. A closed transport is not + /// reported here: the loop ends at its next receive. + fn show_message(&self, typ: lsp_types::MessageType, message: String) { + let _ = self + .connection + .sender + .send(Message::Notification(Notification::new( + lsp_types::notification::ShowMessage::METHOD.to_string(), + lsp_types::ShowMessageParams { typ, message }, + ))); + } + + /// `window/logMessage` to the client (its output channel). + fn log_message(&self, typ: lsp_types::MessageType, message: String) { + let _ = self + .connection + .sender + .send(Message::Notification(Notification::new( + lsp_types::notification::LogMessage::METHOD.to_string(), + lsp_types::LogMessageParams { typ, message }, + ))); + } + /// Syntax-tier diagnostics: parse + body-context validation, /// no model, no cross-file coupling. fn publish_diagnostics(&self, uri: &Uri, doc: &Document) -> Result<(), Error> { @@ -528,30 +774,34 @@ impl Server { Dialect::Sysml => parse_source(&doc.text), }; let mapper = Mapper::new(&doc.text, self.encoding); - Some(DocumentSymbolResponse::Nested(outline::document_symbols( - &parse.unit, - &doc.text, - &mapper, - ))) + let mut symbols = outline::document_symbols(&parse.unit, &doc.text, &mapper); + outline::spell_symbols(&mut symbols); + Some(DocumentSymbolResponse::Nested(symbols)) } /// Hand the workspace tier a fresh snapshot of the open documents. fn schedule_workspace(&self) { + // By uri, the order navigation assembles its own sources in: + // the two tiers answer over the same model, and a unit order + // that differed between them would decide an ambiguity one way + // in a diagnostic and the other way in a definition. + let mut docs: Vec<(String, i32, std::sync::Arc)> = self + .docs + .iter() + .map(|(u, d)| (u.to_string(), d.version, d.text.clone())) + .collect(); + docs.sort_by(|a, b| a.0.cmp(&b.0)); self.worker.schedule(worker::Job { - docs: self - .docs - .iter() - .map(|(u, d)| (u.to_string(), d.version, d.text.clone())) - .collect(), + docs, root: self.root.clone(), }); } - /// Code actions: quickfixes riding published diagnostics - /// (remove an unused import — the diagnostic's range is the removal - /// span) plus the explicit source action collapsing qualified names - /// to their minimal spelling (only offered when the - /// client asks for source actions, since it costs a model pass). + /// Code actions: one provider per kind, in the order a client + /// renders them — the quickfixes riding published diagnostics + /// first (each provider looks at the diagnostics it knows), then + /// the lint's fixes, the import source actions, the refactorings, + /// and last the source actions that cost a committing model pass. fn code_actions( &mut self, params: &lsp_types::CodeActionParams, @@ -559,221 +809,452 @@ impl Server { let uri = ¶ms.text_document.uri; let mut out = Vec::new(); for d in ¶ms.context.diagnostics { - if d.message == worker::UNUSED_IMPORT_MESSAGE { - let mut changes = HashMap::new(); - changes.insert( - uri.clone(), - vec![TextEdit { - range: d.range, - new_text: String::new(), - }], - ); - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title: "Remove unused import".to_string(), - kind: Some(lsp_types::CodeActionKind::QUICKFIX), - diagnostics: Some(vec![d.clone()]), - edit: Some(lsp_types::WorkspaceEdit { - changes: Some(changes), - ..Default::default() - }), - ..Default::default() - }, - )); - } - // Unresolved references: intent-dependent suggestions — - // near-miss respellings ("Did you mean …?") and, when the - // qualifier names a workspace enum, declaring the missing - // literal. The name is re-read from the document at the - // diagnostic's start, so clients with approximate ranges - // still get exact edits. - if d.message.starts_with("unresolved reference `") { - if let Some(offset) = self.offset_of(uri, d.range.start) { - let fixes = - self.nav - .unresolved_reference_fixes(&self.docs, uri, offset, self.encoding); - for (title, target_uri, edit, preferred) in fixes { - let mut changes = HashMap::new(); - changes.insert(target_uri, vec![edit]); - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title, - kind: Some(lsp_types::CodeActionKind::QUICKFIX), - diagnostics: Some(vec![d.clone()]), - is_preferred: preferred.then_some(true), - edit: Some(lsp_types::WorkspaceEdit { - changes: Some(changes), - ..Default::default() - }), - ..Default::default() - }, - )); - } + self.unused_import_fix(uri, d, &mut out); + self.unresolved_reference_fixes(uri, d, &mut out); + self.import_visibility_fixes(uri, d, &mut out); + } + self.lint_fix_actions(params, &mut out); + if requested(params, "source.organizeImports") { + self.optimize_imports_action(uri, &mut out); + } + if requested(params, "source.sortImports") { + self.sort_imports_action(uri, &mut out); + } + self.refactor_actions(params, &mut out); + // Minimizing qualified names is a committing model pass: only an + // explicit "source" request runs it, never a `source.fixAll` + // on-save sweep (which would also discard the session and the + // lint cache). + if requested(params, "source") { + self.minimize_names_action(&mut out); + } + out + } + + /// The unused-private-import quickfix riding its own diagnostic — + /// the diagnostic's range is the removal span. + fn unused_import_fix( + &self, + uri: &Uri, + d: &lsp_types::Diagnostic, + out: &mut Vec, + ) { + if d.message != worker::UNUSED_IMPORT_MESSAGE { + return; + } + out.push(quick_fix( + "Remove unused import".to_string(), + d, + one_file_edit( + uri, + vec![TextEdit { + range: d.range, + new_text: String::new(), + }], + ), + false, + )); + } + + /// Unresolved references: intent-dependent suggestions — near-miss + /// respellings ("Did you mean …?") and, when the qualifier names a + /// workspace enum, declaring the missing literal. The name is + /// re-read from the document at the diagnostic's start, so clients + /// with approximate ranges still get exact edits. + #[allow(clippy::mutable_key_type)] // see the note on `mod nav` + fn unresolved_reference_fixes( + &mut self, + uri: &Uri, + d: &lsp_types::Diagnostic, + out: &mut Vec, + ) { + if !d.message.starts_with("unresolved reference `") { + return; + } + let Some(offset) = self.offset_of(uri, d.range.start) else { + return; + }; + let fixes = self + .nav + .unresolved_reference_fixes(&self.docs, uri, offset, self.encoding); + for (title, target_uri, edit, preferred) in fixes { + let mut changes = HashMap::new(); + changes.insert(target_uri, vec![edit]); + out.push(quick_fix( + title, + d, + lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }, + preferred, + )); + } + } + + /// The mandatory-visibility finding: one action per legal keyword. + /// The keyword the import's dependents require leads (computed from + /// the reference sites that resolve through it); without a model, + /// `private` — the conservative default, since public re-exports. + fn import_visibility_fixes( + &mut self, + uri: &Uri, + d: &lsp_types::Diagnostic, + out: &mut Vec, + ) { + if !d + .message + .starts_with("an import must declare an explicit visibility") + { + return; + } + let advice = self + .offset_of(uri, d.range.start) + .and_then(|offset| self.nav.import_visibility_advice(&self.docs, uri, offset)); + let recommended = advice.as_ref().map_or("private", |a| a.recommended); + let mut keywords = vec![recommended]; + keywords.extend( + ["private", "public", "protected"] + .into_iter() + .filter(|k| *k != recommended), + ); + for vis in keywords { + let edits = vec![TextEdit { + range: lsp_types::Range { + start: d.range.start, + end: d.range.start, + }, + new_text: format!("{vis} "), + }]; + let title = match &advice { + Some(a) if vis == a.recommended && a.outside_sites.is_empty() => { + format!("Make the import `{vis}` (nothing outside uses it)") } + Some(a) if vis == a.recommended => format!( + "Make the import `{vis}` ({} reference(s) beyond the importing \ + namespace resolve through it)", + a.outside_sites.len() + ), + _ => format!("Make the import `{vis}`"), + }; + out.push(quick_fix( + title, + d, + one_file_edit(uri, edits), + vis == recommended, + )); + } + } + + /// Lint fixes: the finding under each lint diagnostic in the + /// request as quick fixes (a semantic or deleting fix labeled as + /// such and never preferred, alternatives unpreferred), beside each + /// one the rule-wide "fix every finding of this rule", and on + /// `source.fixAll` one edit applying every safe fix of the + /// document, each fix whole or not at all, that does not overlap an + /// earlier one. The syntax tier's own visibility quick fix already + /// covers a bare import when that diagnostic is in the request, so + /// the lint twin steps aside there. + fn lint_fix_actions( + &mut self, + params: &lsp_types::CodeActionParams, + out: &mut Vec, + ) { + let uri = ¶ms.text_document.uri; + let lint_diags: Vec<&lsp_types::Diagnostic> = params + .context + .diagnostics + .iter() + .filter(|d| d.source.as_deref() == Some("sysmlv2 lint")) + .collect(); + let wants_fix_all = requested(params, "source.fixAll"); + if lint_diags.is_empty() && !wants_fix_all { + return; + } + let fixes = self.nav.lint_fixes(&self.docs, uri, self.encoding); + let syntax_visibility_at = |start: lsp_types::Position| { + params.context.diagnostics.iter().any(|d| { + d.range.start == start + && d.message + .starts_with("an import must declare an explicit visibility") + }) + }; + let mut rule_wide_offered: std::collections::HashSet = + std::collections::HashSet::new(); + for d in &lint_diags { + let Some(lsp_types::NumberOrString::String(code)) = &d.code else { + continue; + }; + if code == "import-visibility" && syntax_visibility_at(d.range.start) { + continue; } - // The mandatory-visibility finding: offer each legal - // keyword, `private` first (the conservative default — - // public re-exports). - if d.message - .starts_with("an import must declare an explicit visibility") + let mut fixed = false; + for f in fixes + .iter() + .filter(|f| f.rule == code && f.range.start == d.range.start) { - for vis in ["private", "public", "protected"] { - let mut changes = HashMap::new(); - changes.insert( - uri.clone(), - vec![TextEdit { - range: lsp_types::Range { - start: d.range.start, - end: d.range.start, - }, - new_text: format!("{vis} "), - }], - ); - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title: format!("Make the import {vis}"), - kind: Some(lsp_types::CodeActionKind::QUICKFIX), - diagnostics: Some(vec![d.clone()]), - is_preferred: (vis == "private").then_some(true), - edit: Some(lsp_types::WorkspaceEdit { - changes: Some(changes), - ..Default::default() - }), - ..Default::default() - }, - )); + fixed = true; + let mut push = |title: String, + semantic: bool, + edit: &lsp_types::WorkspaceEdit, + preferred: bool| { + let title = if semantic { + format!("{title} (rewrites the declaration)") + } else if f.deletes { + format!("{title} (deletes model text)") + } else { + title + }; + out.push(quick_fix(title, d, edit.clone(), preferred)); + }; + push( + f.label.clone(), + f.semantic, + &f.edit, + !f.semantic && !f.deletes, + ); + for (label, semantic, edit) in &f.alternatives { + push(label.clone(), *semantic, edit, false); } } + if fixed && rule_wide_offered.insert(code.clone()) { + self.rule_wide_fix_actions(uri, d, code, out); + } } - // Kind-filter semantics: an action is requested when an `only` - // entry equals its kind or is a dot-separated ancestor of it - // (`source` requests `source.organizeImports`; the reverse does - // not hold). - let requested = |kind: &str| -> bool { - params.context.only.as_ref().is_some_and(|ks| { - ks.iter().any(|k| { - let k = k.as_str(); - kind == k - || (kind.starts_with(k) && kind.as_bytes().get(k.len()) == Some(&b'.')) - }) - }) + if wants_fix_all { + // Each fix whole or not at all: a fix that touches another + // document, or whose edits collide with what is already + // kept, is left for a quick fix. + let (changes, n) = merge_fixes( + fixes + .iter() + .filter(|f| !f.semantic && !f.deletes) + .map(|f| &f.edit), + Some(uri), + ); + if n > 0 { + out.push(source_action( + format!("Fix all auto-fixable lint findings ({n})"), + lsp_types::CodeActionKind::SOURCE_FIX_ALL, + lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }, + )); + } + } + } + + /// Beside a finding's own fix: every finding of its rule at once, + /// in this document and across the workspace (each finding's + /// primary fix, whole or not at all; the user chose the rule, so + /// semantic and deleting fixes go in, labeled). Offered only where + /// there is more than the one finding to fix. + fn rule_wide_fix_actions( + &mut self, + uri: &Uri, + d: &lsp_types::Diagnostic, + code: &str, + out: &mut Vec, + ) { + let rule_fixes = self + .nav + .lint_rule_fixes(&self.docs, uri, self.encoding, code); + let suffix = if rule_fixes.iter().any(|f| f.semantic) { + " (rewrites the declarations)" + } else if rule_fixes.iter().any(|f| f.deletes) { + " (deletes model text)" + } else { + "" + }; + let mut rule_wide = |title: String, changes: HashMap>| { + out.push(lsp_types::CodeActionOrCommand::CodeAction( + lsp_types::CodeAction { + title, + kind: Some(lsp_types::CodeActionKind::QUICKFIX), + diagnostics: Some(vec![d.clone()]), + edit: Some(lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }), + ..Default::default() + }, + )); }; + let (in_file, n_file) = merge_fixes(rule_fixes.iter().map(|f| &f.edit), Some(uri)); + if n_file >= 2 { + rule_wide( + format!("Fix all {n_file} `{code}` findings in this file{suffix}"), + in_file, + ); + } + let (everywhere, n_all) = merge_fixes(rule_fixes.iter().map(|f| &f.edit), None); + let files = everywhere.len(); + if n_all > n_file && files >= 2 { + rule_wide( + format!("Fix all {n_all} `{code}` findings across {files} files{suffix}"), + everywhere, + ); + } + } - // "Optimize imports" (source.organizeImports): drop the unused - // private imports, keep everything else — order included. - if requested("source.organizeImports") { - if let Some(edits) = self.nav.optimize_imports(&self.docs, uri, self.encoding) { - if !edits.is_empty() { - let mut changes = HashMap::new(); - changes.insert(uri.clone(), edits); - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title: "Optimize imports".to_string(), - kind: Some(lsp_types::CodeActionKind::SOURCE_ORGANIZE_IMPORTS), - edit: Some(lsp_types::WorkspaceEdit { - changes: Some(changes), - ..Default::default() - }), - ..Default::default() - }, - )); - } - } + /// "Optimize imports" (`source.organizeImports`): drop the unused + /// private imports, keep everything else — order included. + fn optimize_imports_action( + &mut self, + uri: &Uri, + out: &mut Vec, + ) { + let Some(edits) = self.nav.optimize_imports(&self.docs, uri, self.encoding) else { + return; + }; + if edits.is_empty() { + return; } + out.push(source_action( + "Optimize imports".to_string(), + lsp_types::CodeActionKind::SOURCE_ORGANIZE_IMPORTS, + one_file_edit(uri, edits), + )); + } - // "Sort imports" (source.sortImports): alphabetize contiguous - // import runs; a syntax-tier reshuffle, no model pass. - if requested("source.sortImports") { - if let Some(doc) = self.docs.get(uri) { - let edits = nav::sort_import_edits( - &doc.text, - matches!(dialect_of(uri), Dialect::Kerml), - self.encoding, - ); - if !edits.is_empty() { - let mut changes = HashMap::new(); - changes.insert(uri.clone(), edits); - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title: "Sort imports".to_string(), - kind: Some(lsp_types::CodeActionKind::new("source.sortImports")), - edit: Some(lsp_types::WorkspaceEdit { - changes: Some(changes), - ..Default::default() - }), - ..Default::default() - }, - )); - } - } + /// "Sort imports" (`source.sortImports`): alphabetize contiguous + /// import runs; a syntax-tier reshuffle, no model pass. + fn sort_imports_action(&self, uri: &Uri, out: &mut Vec) { + let Some(doc) = self.docs.get(uri) else { + return; + }; + let edits = nav::sort_import_edits( + &doc.text, + matches!(dialect_of(uri), Dialect::Kerml), + self.encoding, + ); + if edits.is_empty() { + return; } + out.push(source_action( + "Sort imports".to_string(), + lsp_types::CodeActionKind::new("source.sortImports"), + one_file_edit(uri, edits), + )); + } - // Refactorings: offered on the unfiltered request (the - // lightbulb / context menu sends no `only`) and under `refactor` - // kind filters — the same ancestor semantics as the source - // actions, so `refactor` requests both members of the pair. - // Eligibility gates run first and are cheap; the dry-run that - // computes the edit only happens for admitted cursors, and it - // leaves the session untouched (no invalidation). + /// Refactorings: offered on the unfiltered request (the lightbulb / + /// context menu sends no `only`) and under `refactor` kind filters + /// — the same ancestor semantics as the source actions, so + /// `refactor` requests every member of the set. Eligibility gates + /// run first and are cheap; the dry run that computes the edit only + /// happens for admitted cursors, and it leaves the session + /// untouched (no invalidation). + fn refactor_actions( + &mut self, + params: &lsp_types::CodeActionParams, + out: &mut Vec, + ) { + let uri = ¶ms.text_document.uri; let unfiltered = params.context.only.is_none(); - if unfiltered || requested("refactor.extract") { - if let Some(offset) = self.offset_of(uri, params.range.start) { - if let Some((title, edit)) = - self.nav - .refactor_extract_action(&self.docs, uri, offset, self.encoding) - { - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title, - kind: Some(lsp_types::CodeActionKind::REFACTOR_EXTRACT), - edit: Some(edit), - ..Default::default() - }, - )); - } + let Some(offset) = self.offset_of(uri, params.range.start) else { + return; + }; + if unfiltered || requested(params, "refactor.extract") { + if let Some((title, edit)) = + self.nav + .refactor_extract_action(&self.docs, uri, offset, self.encoding) + { + out.push(refactoring( + title, + lsp_types::CodeActionKind::REFACTOR_EXTRACT, + edit, + )); } } - if unfiltered || requested("refactor.inline") { - if let Some(offset) = self.offset_of(uri, params.range.start) { - if let Some((title, edit)) = - self.nav - .refactor_inline_action(&self.docs, uri, offset, self.encoding) - { - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title, - kind: Some(lsp_types::CodeActionKind::REFACTOR_INLINE), - edit: Some(edit), - ..Default::default() - }, - )); - } + if unfiltered || requested(params, "refactor.move") { + for (title, edit) in self + .nav + .split_actions(&self.docs, uri, offset, self.encoding) + { + out.push(refactoring( + title, + lsp_types::CodeActionKind::new("refactor.move"), + edit, + )); } } + if unfiltered || requested(params, "refactor.inline") { + if let Some((title, edit)) = + self.nav + .refactor_inline_action(&self.docs, uri, offset, self.encoding) + { + out.push(refactoring( + title, + lsp_types::CodeActionKind::REFACTOR_INLINE, + edit, + )); + } + } + } - let wants_source = params - .context - .only - .as_ref() - .is_some_and(|kinds| kinds.iter().any(|k| k.as_str().starts_with("source"))); - if wants_source { - if let Ok(edit) = self.nav.minimize(&self.docs, self.encoding) { - self.nav.invalidate(); - if edit.changes.as_ref().is_some_and(|c| !c.is_empty()) { - out.push(lsp_types::CodeActionOrCommand::CodeAction( - lsp_types::CodeAction { - title: "Minimize qualified names".to_string(), - kind: Some(lsp_types::CodeActionKind::SOURCE), - edit: Some(edit), - ..Default::default() - }, - )); + /// "Minimize qualified names": collapse every qualified name to its + /// minimal spelling. A committing model pass, so the session and + /// the lint cache go either way. + fn minimize_names_action(&mut self, out: &mut Vec) { + let edit = self.nav.minimize(&self.docs, self.encoding); + self.nav.invalidate(); + let Ok(edit) = edit else { + return; + }; + if edit.changes.as_ref().is_some_and(|c| !c.is_empty()) { + out.push(source_action( + "Minimize qualified names".to_string(), + lsp_types::CodeActionKind::SOURCE, + edit, + )); + } + } + + /// The editor's split wizard: plan (and, for `sysmlv2/split`, the + /// annotated edit of) a package's split under the requested naming + /// scheme and directory. The package is the declaration under + /// `position` in `textDocument` (which must be open) or the + /// qualified `package` name. + fn split_request( + &mut self, + p: SplitRequestParams, + with_edit: bool, + ) -> Result { + let target = match (p.package, p.position, p.text_document) { + (Some(name), _, _) => nav::SplitTarget::Package(name), + (None, Some(pos), Some(doc)) => { + let offset = self.offset_of(&doc.uri, pos).ok_or_else(|| { + SplitRefusal::Params(format!("{} is not an open document", doc.uri.as_str())) + })?; + nav::SplitTarget::Offset { + uri: doc.uri, + offset, } - } else { - self.nav.invalidate(); } - } - out + (None, Some(_), None) => { + return Err(SplitRefusal::Params( + "a position needs its textDocument".to_string(), + )); + } + (None, None, _) => { + return Err(SplitRefusal::Params( + "a split request names a package or a position".to_string(), + )); + } + }; + let options = sysmlv2_transform::SplitOptions { + naming: match p.naming { + SplitNamingParam::Keep => sysmlv2_transform::SplitNaming::Keep, + SplitNamingParam::Slug => sysmlv2_transform::SplitNaming::Slug, + }, + directory: p.directory, + ..Default::default() + }; + self.nav + .split_request(&self.docs, &target, options, with_edit, self.encoding) + .map_err(SplitRefusal::Refused) } /// A position's byte offset in an open document. @@ -807,21 +1288,16 @@ impl Server { /// caller to surface; an already-formatted document returns an empty /// edit list. Formatter style is fixed (4-space indent) — the /// request's `FormattingOptions` are deliberately not consulted. - fn format(&self, uri: &Uri) -> (Vec, Option) { - let Some(doc) = self.docs.get(uri) else { + fn format(&mut self, uri: &Uri) -> (Vec, Option) { + if !self.docs.contains_key(uri) { return (Vec::new(), None); - }; + } // Project style: the `multiline-conditions` rule's `min` option // in the workspace's sysmlint.json carries the chain threshold // (0 = keep chains inline); absent or unreadable config keeps // the formatter's default. - let chain_min = self - .root - .as_ref() - .and_then(|r| std::fs::read_to_string(r.join("sysmlint.json")).ok()) - .and_then(|text| sysmlv2_lint::Config::from_json(&text).ok()) - .map(|c| c.format_chain_min()) - .unwrap_or(Some(sysmlv2_parser::print::FORMAT_CHAIN_MIN)); + let chain_min = self.nav.lint_config().format_chain_min(); + let doc = &self.docs[uri]; let opts = sysmlv2_parser::print::PrintOptions { multiline_chains: chain_min, ..Default::default() @@ -838,7 +1314,7 @@ impl Server { )), ) } - Ok(formatted) if formatted == doc.text => (Vec::new(), None), + Ok(formatted) if formatted == *doc.text => (Vec::new(), None), Ok(formatted) => { let mapper = Mapper::new(&doc.text, self.encoding); ( @@ -853,11 +1329,271 @@ impl Server { } } +/// A method whose handling panics, so the tests can pin what a +/// panicking handler does: answer the request, say so, keep serving. +#[cfg(test)] +pub(crate) const PANIC_METHOD: &str = "sysmlv2/panicForTest"; +#[cfg(test)] +pub(crate) const PANIC_REASON: &str = "the handler gave up"; + +/// The message a session failure deserves at the client, if any. A +/// unit that does not parse is the ordinary state of a document being +/// typed — the syntax tier already shows those errors, and repeating +/// them here would drown the real news — but a library that cannot be +/// read, or a payload that does not decode, leaves whole tiers +/// silently empty with nothing said. +fn session_failure(e: &sysmlv2_transform::SessionError) -> Option { + match e { + sysmlv2_transform::SessionError::Parse { .. } => None, + e => Some(e.to_string()), + } +} + +/// Something a tier could not do, with no channel of its own to say so: +/// `show` puts it in front of the user — a library that cannot be read +/// leaves every model-backed answer empty until it is fixed — and +/// anything else goes to the client's log. +pub(crate) struct Report { + pub(crate) show: bool, + pub(crate) message: String, +} + +impl Report { + /// The report a session failure deserves, if it deserves one (see + /// [`session_failure`]). `library`: the failure came from loading + /// the configured standard library, which the user has to fix. + pub(crate) fn for_session_failure( + e: &sysmlv2_transform::SessionError, + library: bool, + ) -> Option { + let message = session_failure(e)?; + Some(Report { + show: library, + message: match library { + true => format!("the standard library could not be read: {message}"), + false => format!("the model could not be built: {message}"), + }, + }) + } +} + +/// The message a caught panic carried, for the client-facing report. +/// Payloads that are neither `&str` nor `String` have no message to +/// show. +pub(crate) fn panic_reason(payload: &(dyn std::any::Any + Send)) -> String { + payload + .downcast_ref::<&str>() + .map(|s| (*s).to_string()) + .or_else(|| payload.downcast_ref::().cloned()) + .unwrap_or_else(|| "internal error".to_string()) +} + +/// A request's id and deserialized parameters, or the `InvalidParams` +/// response answering a request whose parameters do not deserialize +/// (an oddly encoded uri, a null in a required field, a fuzzed +/// message) — the request is answered and the session goes on. +fn cast(req: Request) -> Result<(RequestId, P), Response> { + let Request { id, method, params } = req; + match serde_json::from_value(params) { + Ok(p) => Ok((id, p)), + Err(e) => Err(Response::new_err( + id, + ErrorCode::InvalidParams as i32, + format!("{method}: invalid params: {e}"), + )), + } +} + /// Dialect by file extension: `.kerml` is KerML, everything else SysML. -fn dialect_of(uri: &Uri) -> Dialect { - if uri.path().as_str().ends_with(".kerml") { +pub(crate) fn dialect_of(uri: &Uri) -> Dialect { + if is_kerml(uri.path().as_str()) { Dialect::Kerml } else { Dialect::Sysml } } + +/// Whether a unit name, path or uri names a KerML file. The extension +/// decides which grammar a unit is read with, and case is not part of +/// it: a file system that preserves case but matches without it hands +/// back `Model.KerML` as readily as `model.kerml`, and reading that as +/// SysML would report the whole file as broken. +pub(crate) fn is_kerml(path: &str) -> bool { + ends_with_extension(path, b".kerml") +} + +/// Whether a file name is a model unit — `.sysml` or `.kerml`, in +/// whatever case it is spelled (see [`is_kerml`]). +pub(crate) fn is_model_file(name: &str) -> bool { + ends_with_extension(name, b".sysml") || is_kerml(name) +} + +/// `path` ends with `extension`, ignoring ASCII case. Compared over +/// bytes: a name is not guaranteed to have a character boundary six +/// bytes from its end. +fn ends_with_extension(path: &str, extension: &[u8]) -> bool { + let bytes = path.as_bytes(); + bytes + .len() + .checked_sub(extension.len()) + .is_some_and(|at| bytes[at..].eq_ignore_ascii_case(extension)) +} + +/// Kind-filter semantics: an action is requested when an `only` entry +/// equals its kind or is a dot-separated ancestor of it (`source` +/// requests `source.organizeImports`; the reverse does not hold). +fn requested(params: &lsp_types::CodeActionParams, kind: &str) -> bool { + params.context.only.as_ref().is_some_and(|ks| { + ks.iter().any(|k| { + let k = k.as_str(); + kind == k || (kind.starts_with(k) && kind.as_bytes().get(k.len()) == Some(&b'.')) + }) + }) +} + +/// A workspace edit confined to one document. +#[allow(clippy::mutable_key_type)] // see the note on `mod nav` +fn one_file_edit(uri: &Uri, edits: Vec) -> lsp_types::WorkspaceEdit { + let mut changes = HashMap::new(); + changes.insert(uri.clone(), edits); + lsp_types::WorkspaceEdit { + changes: Some(changes), + ..Default::default() + } +} + +/// A quick fix riding the diagnostic it answers, so the client offers +/// it at that diagnostic's lightbulb. +fn quick_fix( + title: String, + diagnostic: &lsp_types::Diagnostic, + edit: lsp_types::WorkspaceEdit, + preferred: bool, +) -> lsp_types::CodeActionOrCommand { + lsp_types::CodeActionOrCommand::CodeAction(lsp_types::CodeAction { + title, + kind: Some(lsp_types::CodeActionKind::QUICKFIX), + diagnostics: Some(vec![diagnostic.clone()]), + is_preferred: preferred.then_some(true), + edit: Some(edit), + ..Default::default() + }) +} + +/// A source action: whole-document, tied to no diagnostic. +fn source_action( + title: String, + kind: lsp_types::CodeActionKind, + edit: lsp_types::WorkspaceEdit, +) -> lsp_types::CodeActionOrCommand { + lsp_types::CodeActionOrCommand::CodeAction(lsp_types::CodeAction { + title, + kind: Some(kind), + edit: Some(edit), + ..Default::default() + }) +} + +/// A refactoring offered at the cursor. +fn refactoring( + title: String, + kind: lsp_types::CodeActionKind, + edit: lsp_types::WorkspaceEdit, +) -> lsp_types::CodeActionOrCommand { + lsp_types::CodeActionOrCommand::CodeAction(lsp_types::CodeAction { + title, + kind: Some(kind), + edit: Some(edit), + ..Default::default() + }) +} + +/// Merge whole lint fixes into one set of changes: a fix whose edits +/// collide with what is already kept — or, under `only`, that touches any +/// other document — is left out whole, for its own quick fix. Identical +/// edits (two findings inserting the same text at one spot) count once. +/// Returns the changes per document, each sorted, and how many fixes +/// went in. +#[allow(clippy::mutable_key_type)] // see the note on `mod nav` +fn merge_fixes<'a>( + fixes: impl Iterator, + only: Option<&Uri>, +) -> (HashMap>, usize) { + let overlaps = |e: &TextEdit, k: &TextEdit| { + (e.range.start < k.range.end && k.range.start < e.range.end) + || (e.range.start == k.range.start + && e.range.end == e.range.start + && k.range.end == k.range.start + && e.new_text != k.new_text) + }; + let mut kept: HashMap> = HashMap::new(); + let mut applied = 0usize; + for fix in fixes { + let Some(changes) = fix.changes.as_ref() else { + continue; + }; + if changes.is_empty() || only.is_some_and(|u| changes.keys().any(|k| k != u)) { + continue; + } + let fresh: Vec<(&Uri, Vec)> = changes + .iter() + .map(|(u, edits)| { + let have = kept.get(u); + let mut edits: Vec = edits + .iter() + .filter(|e| !have.is_some_and(|h| h.contains(e))) + .cloned() + .collect(); + edits.sort_by_key(|e| (e.range.start, e.range.end)); + (u, edits) + }) + .collect(); + let collides = fresh.iter().any(|(u, edits)| { + kept.get(*u) + .is_some_and(|have| edits.iter().any(|e| have.iter().any(|k| overlaps(e, k)))) + }); + if collides { + continue; + } + for (u, edits) in fresh { + kept.entry(u.clone()).or_default().extend(edits); + } + applied += 1; + } + for edits in kept.values_mut() { + edits.sort_by_key(|e| (e.range.start, e.range.end)); + } + (kept, applied) +} + +#[cfg(test)] +mod stack_tests { + use super::*; + + /// A loop whose thread could not be given the stack the parser's + /// bound assumes used to run on the host's own stack with nothing + /// said — and a document nested past that stack ends the server + /// outright, too late for any channel. The log carries what the + /// system said and what the session risks by it. + #[test] + fn a_loop_whose_stack_is_refused_says_so() { + let (out, messages) = crossbeam_channel::unbounded(); + let refused = std::io::Error::new(std::io::ErrorKind::OutOfMemory, "no room for a thread"); + say_the_stack_was_refused(&out, &refused); + + let sent: Vec<(String, String)> = messages + .try_iter() + .map(|m| { + let Message::Notification(n) = m else { + panic!("{m:?}") + }; + let message = n.params["message"].as_str().expect("a message").to_string(); + (n.method, message) + }) + .collect(); + assert_eq!(sent.len(), 1, "{sent:?}"); + assert_eq!(sent[0].0, "window/logMessage", "{sent:?}"); + assert!(sent[0].1.contains("no room for a thread"), "{sent:?}"); + assert!(sent[0].1.contains("nesting bound"), "{sent:?}"); + } +} diff --git a/crates/sysmlv2-lsp/src/nav.rs b/crates/sysmlv2-lsp/src/nav.rs index fe34761..d44dd02 100644 --- a/crates/sysmlv2-lsp/src/nav.rs +++ b/crates/sysmlv2-lsp/src/nav.rs @@ -18,16 +18,72 @@ //! *reject atomically* and surface as request errors instead of //! corrupting the model. -use crate::position::Mapper; -use crate::{Document, Encoding}; +use crate::position::{Mapper, UnitMappers, offset32}; +use crate::{Document, Encoding, Report}; use lsp_types::{Location, Position, Range, TextEdit, Uri, WorkspaceEdit}; -use std::collections::HashMap; +use std::collections::{BTreeMap, HashMap}; use std::path::PathBuf; use std::str::FromStr; +use std::sync::Arc; use sysmlv2_parser::json::{ElementRef, RefSite}; use sysmlv2_parser::span::Span; use sysmlv2_parser::visit::Visit as _; -use sysmlv2_transform::{Library, Session}; +use sysmlv2_transform::{Library, Session, SessionError}; + +/// The session fingerprint, the package, and the actions planned for it. +type SplitCache = (Vec<(String, i32)>, ElementRef, Vec<(String, WorkspaceEdit)>); + +/// The package a split request names. +pub enum SplitTarget { + /// The declaration whose name spans `offset` of the unit `uri`. + Offset { uri: Uri, offset: u32 }, + /// A qualified name (quoted segments allowed) resolved from the + /// root namespace. + Package(String), +} + +/// One planned unit of a split — see [`Nav::split_request`]. +#[derive(serde::Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct SplitResponseEntry { + /// Qualified name before the split. + pub qualified_name: String, + pub name: String, + /// The root-level name the package takes when its own would collide. + pub new_name: Option, + /// The package's name after the split as a request `package` + /// spells it: its root-level name, quoted when needed. + pub root_name: String, + /// The new unit's uri. + pub uri: String, + /// Size of the package's text. + pub bytes: usize, + /// Directly nested packages — what a deeper level would split; a + /// leaf has none. + pub nested: usize, +} + +/// The package a split starts from. +#[derive(serde::Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct SplitResponseRoot { + pub name: String, + pub qualified_name: String, + /// The unit the package is declared in. + pub uri: String, +} + +/// A planned split, with its annotated edit when one was asked for. +#[derive(serde::Serialize, Debug, Clone)] +#[serde(rename_all = "camelCase")] +pub struct SplitResponse { + pub root: SplitResponseRoot, + /// The uri prefix the new units are named under. + pub directory: String, + pub entries: Vec, + #[serde(skip_serializing_if = "Option::is_none")] + pub edit: Option, +} pub struct Nav { pub library: Option, @@ -47,7 +103,7 @@ pub struct Nav { /// push-driven WASM frontend): `(uri string, text)`, keyed by the /// same uri strings the client opens documents under. Takes the /// role of the root walk when set. - workspace: Option>, + workspace: Option>>, /// Qualified symbols of the seeded workspace units, parsed once per /// seed (the [`Self::library_symbols`] pattern) — import fixes and /// completions must see the whole workspace, not just what happens @@ -55,6 +111,9 @@ pub struct Nav { /// shadowed by an open document are filtered at query time. workspace_seed_symbols: Option>, session: Option, + /// Failures behind an empty answer, waiting for the server to pass + /// them to the client ([`Nav::take_reports`]). + reports: Vec, /// (uri string, version) per open doc at the last rebuild. fingerprint: Vec<(String, i32)>, /// The solverless verify pass shared by inlay hints and code @@ -62,6 +121,18 @@ pub struct Nav { /// recomputing per request would run propagation dozens of times /// over an unchanged model). verify: Option, + /// The split actions last computed for a package, keyed by the + /// session fingerprint: the cursor rests on a package name across + /// many code-action requests, and each plan is a whole-workspace + /// dry run. + split_cache: Option, + /// The lint pass over the current session, keyed by the + /// configuration it ran with: code-action requests arrive per + /// cursor move and must not re-lint the workspace each time. + lint: Option<(u64, Vec)>, + /// The workspace's lint configuration, re-read only when the file + /// changes. + config: LintConfig, /// Suppress evaluated-value inlay hints that would restate the /// declared value expression verbatim (`x = 3.63 [kg]` needs no /// ` = 3.63 [kg]` hint). Default on; hosts flip it via @@ -91,6 +162,7 @@ pub struct Nav { impl Nav { pub fn new(library: Option, root: Option) -> Nav { let mut nav = Self::new_with(library.map(Library::dir)); + nav.config = LintConfig::under(root.as_deref()); nav.root = root; nav } @@ -109,13 +181,23 @@ impl Nav { session: None, fingerprint: Vec::new(), verify: None, + lint: None, + split_cache: None, hide_redundant_value_hints: true, snippet_completions: false, infer_unit_types: true, completion_session: None, + reports: Vec::new(), + config: LintConfig::under(None), } } + /// The workspace's lint configuration. Shared with the formatter, + /// whose project style comes out of the same file. + pub fn lint_config(&mut self) -> &sysmlv2_lint::Config { + self.config.get().1 + } + /// Set whether completion edits may use snippet syntax (`$0` /// cursor stops on statement-repair suffixes) — from the client's /// `completionItem.snippetSupport` capability at `initialize`. @@ -142,7 +224,7 @@ impl Nav { /// Unit names must be the same uri strings the client opens /// documents under, or an open document duplicates its on-model /// unit instead of overlaying it. - pub fn set_workspace_sources(&mut self, units: Vec<(String, String)>) { + pub fn set_workspace_sources(&mut self, units: Arc>) { self.workspace = Some(units); self.workspace_seed_symbols = None; self.invalidate(); @@ -154,6 +236,8 @@ impl Nav { self.session = None; self.fingerprint.clear(); self.verify = None; + self.lint = None; + self.split_cache = None; self.completion_session = None; } @@ -172,7 +256,7 @@ impl Nav { /// [`ResolvedModel::member_of`]: sysmlv2_parser::json::ResolvedModel::member_of fn chain_member_completions( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, cx: &CompletionCx, enc: Encoding, @@ -184,8 +268,8 @@ impl Nav { let text = &docs.get(uri)?.text; let line_end = text[(cx.offset as usize).min(text.len())..] .find('\n') - .map(|i| cx.offset + i as u32) - .unwrap_or(text.len() as u32); + .map(|i| cx.offset + offset32(i)) + .unwrap_or(offset32(text.len())); let session = self.completion_session(docs, uri, Span::new(cx.stmt_start, line_end))?; let unit = Self::unit_of_static(uri, session)?; let resolved = session.resolved(); @@ -262,10 +346,16 @@ impl Nav { details .into_iter() .map(|(name, kind, detail)| { - let (text_edit, repair, insert_text_format) = - item_edits(&d.text, &mapper, cx, &name, snippets); + let (text_edit, repair, insert_text_format) = item_edits( + &d.text, + &mapper, + cx, + crate::dialect_of(uri), + &name, + snippets, + ); lsp_types::CompletionItem { - label: name, + label: crate::outline::spell_name(&name), kind: Some(kind), detail, text_edit, @@ -282,7 +372,7 @@ impl Nav { /// version moved. `None` when a document fails to build a session /// (never expected — sessions tolerate parse errors — but a broken /// library directory reports here). - fn session(&mut self, docs: &HashMap) -> Option<&mut Session> { + fn session(&mut self, docs: &BTreeMap) -> Option<&mut Session> { let mut fp: Vec<(String, i32)> = docs .iter() .map(|(u, d)| (u.to_string(), d.version)) @@ -294,6 +384,8 @@ impl Nav { self.session = Some(session); self.fingerprint = fp; self.verify = None; + self.lint = None; + self.split_cache = None; } self.session.as_mut() } @@ -304,11 +396,11 @@ impl Nav { /// resolve. fn assemble_sources( &self, - docs: &HashMap, + docs: &BTreeMap, fp: &[(String, i32)], ) -> Vec<(String, String)> { let mut sources: Vec<(String, String)> = match (&self.workspace, &self.root) { - (Some(units), _) => units.clone(), + (Some(units), _) => units.as_ref().clone(), (None, Some(root)) => crate::worker::root_sources(root), (None, None) => Vec::new(), }; @@ -320,17 +412,39 @@ impl Nav { } /// A session over `sources`, the configured library loaded. `None` - /// when any unit fails to parse (sessions refuse parse errors). - fn build_session(&self, sources: Vec<(String, String)>) -> Option { - let session = Session::from_sources(sources).ok()?; - Some(match &self.library { - Some(lib) => { - let mut session = session; - session.load_library_from(lib.clone()).ok()?; - session + /// when any unit fails to parse (sessions refuse parse errors) — + /// the ordinary state of a document mid-edit, and the syntax tier + /// already shows those errors. A library that cannot be read is not + /// ordinary and is recorded for the client: without it every + /// model-backed answer here is silently empty. + fn build_session(&mut self, sources: Vec<(String, String)>) -> Option { + let mut session = match Session::from_sources(sources) { + Ok(session) => session, + Err(e) => { + self.note_failure(&e, false); + return None; } - None => session, - }) + }; + if let Some(lib) = &self.library { + if let Err(e) = session.load_library_from(lib.clone()) { + self.note_failure(&e, true); + return None; + } + } + Some(session) + } + + /// Record a session failure for the client, unless it is a unit + /// that does not parse — see [`Self::build_session`]. `library` + /// asks for a visible message rather than a log line. + fn note_failure(&mut self, e: &SessionError, library: bool) { + self.reports.extend(Report::for_session_failure(e, library)); + } + + /// Failures behind an empty answer, for the server to pass on — + /// navigation has no channel to the client of its own. + pub(crate) fn take_reports(&mut self) -> Vec { + std::mem::take(&mut self.reports) } /// The completion tier's session: [`Self::assemble_sources`] with @@ -345,7 +459,7 @@ impl Nav { /// `None` when the rest of the workspace does not parse either. fn completion_session( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, cut: Span, ) -> Option<&mut Session> { @@ -404,7 +518,7 @@ impl Nav { /// cursor. pub fn definition( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, enc: Encoding, @@ -420,7 +534,7 @@ impl Nav { /// under the cursor, optionally plus its declaration. pub fn references( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, include_declaration: bool, @@ -533,7 +647,7 @@ impl Nav { /// hover: qualified name + metaclass (and declared detail later). pub fn hover( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, enc: Encoding, @@ -565,7 +679,7 @@ impl Nav { let doc_text = docs.get(uri).map(|d| d.text.clone()); let site_value = match (&site, &doc_text) { (Some(s), Some(t)) => { - Self::chain_site_value(session, uri.path().as_str().ends_with(".kerml"), t, s) + Self::chain_site_value(session, crate::is_kerml(uri.path().as_str()), t, s) } _ => None, }; @@ -594,10 +708,12 @@ impl Nav { } } Ok( - sysmlv2_parser::eval::Value::Element(_) | sysmlv2_parser::eval::Value::Unbound(_), + sysmlv2_parser::eval::Value::Element(_) + | sysmlv2_parser::eval::Value::Unbound(_) + | sysmlv2_parser::eval::Value::UnboundMember(_), ) | Err(_) => text, - Ok(v) => format!("{text} \n= `{}`", resolved.render_value(&v)), + Ok(v) => format!("{text} \n= `{}`", resolved.render_value_approx(&v)), }; // Documentation bodies annotating the element join the card // under a rule, block-comment `*` gutters stripped. A named doc @@ -646,8 +762,11 @@ impl Nav { resolved.element_name(target).map(str::to_string), resolved.owner(target), ) { + // The counterpart lives among the typing's *effective* + // features (owned + inherited): the vocabulary attribute + // may itself be inherited within the library hierarchy. 'outer: for ty in resolved.typings(owner) { - for member in resolved.owned_members(ty) { + for member in resolved.effective_features(ty, true) { if resolved.element_name(member) == Some(name.as_str()) { inherited = docs_of(resolved, member); if !inherited.is_empty() { @@ -692,7 +811,7 @@ impl Nav { /// documents — the caller must `invalidate()`. pub fn rename( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, new_name: &str, @@ -743,7 +862,7 @@ impl Nav { /// advanced past the client's documents. pub fn minimize( &mut self, - docs: &HashMap, + docs: &BTreeMap, enc: Encoding, ) -> Result { let session = self @@ -775,13 +894,421 @@ impl Nav { }) } + /// "Split into files": offered when the cursor sits on the name of a + /// package that owns nested packages. One action per file-naming + /// scheme whose names differ. The edit creates the new units and + /// rewrites the root, every change under one annotation naming the + /// split (a client's refactor preview lists the files by it). + pub fn split_actions( + &mut self, + docs: &BTreeMap, + uri: &Uri, + offset: u32, + enc: Encoding, + ) -> Vec<(String, WorkspaceEdit)> { + let Some(session) = self.session(docs) else { + return Vec::new(); + }; + let Some(unit) = Self::unit_of_static(uri, session) else { + return Vec::new(); + }; + let Some(package) = session.resolved().declaration_at(unit, offset) else { + return Vec::new(); + }; + if session.resolved().element_type(package) != "Package" { + return Vec::new(); + } + let Some(name) = session.resolved().element_name(package).map(str::to_string) else { + return Vec::new(); + }; + if let Some((fp, cached_package, actions)) = &self.split_cache { + if *fp == self.fingerprint && *cached_package == package { + return actions.clone(); + } + } + let session = self.session.as_mut().expect("session built above"); + let mut out = Vec::new(); + let mut seen_trees: Vec> = Vec::new(); + for naming in [ + sysmlv2_transform::SplitNaming::Keep, + sysmlv2_transform::SplitNaming::Slug, + ] { + let options = sysmlv2_transform::SplitOptions { + naming, + directory: None, + uri_units: true, + }; + let Ok(plan) = session.split_plan(package, &options) else { + continue; + }; + let tree: Vec = plan.entries.iter().map(|e| e.unit.clone()).collect(); + if seen_trees.contains(&tree) { + continue; + } + seen_trees.push(tree.clone()); + let mut edit = session.edit(); + edit.split(&plan); + let Ok(report) = edit.check() else { + continue; + }; + let Some(workspace_edit) = Self::annotated_edit(session, &plan, &report.splices, enc) + else { + continue; + }; + let scheme = match naming { + sysmlv2_transform::SplitNaming::Keep => "", + sysmlv2_transform::SplitNaming::Slug => " (slugged file names)", + }; + let n = plan.entries.len(); + out.push(( + format!( + "Split '{name}' into {n} file{} under {}/{scheme}", + if n == 1 { "" } else { "s" }, + plan.directory.rsplit('/').next().unwrap_or(&plan.directory) + ), + workspace_edit, + )); + } + self.split_cache = Some((self.fingerprint.clone(), package, out.clone())); + out + } + + /// The split behind an editor's wizard (`sysmlv2/splitPlan`, + /// `sysmlv2/split`): the plan for one package under one naming + /// scheme and directory, with the annotated workspace edit when + /// `with_edit` (a whole-workspace dry run — the plan alone is + /// cheap, so a wizard previews both naming schemes and asks for the + /// edit once). The package is the declaration under a cursor + /// offset or a qualified name resolved from the root namespace, so + /// a deeper level can be requested by the name a hoisted package + /// takes in its new unit. Unit names are uris here, so the + /// options' `uri_units` is forced on. Refusals name their reason. + pub fn split_request( + &mut self, + docs: &BTreeMap, + target: &SplitTarget, + options: sysmlv2_transform::SplitOptions, + with_edit: bool, + enc: Encoding, + ) -> Result { + let session = self + .session(docs) + .ok_or_else(|| "the model could not be built".to_string())?; + let package = match target { + SplitTarget::Offset { uri, offset } => { + let unit = Self::unit_of_static(uri, session) + .ok_or_else(|| format!("{} is not a model unit", uri.as_str()))?; + session + .resolved() + .declaration_at(unit, *offset) + .ok_or_else(|| "the position is not on a declaration's name".to_string())? + } + SplitTarget::Package(name) => session + .resolved() + .resolve_qualified(name) + .ok_or_else(|| format!("cannot resolve `{name}`"))?, + }; + let options = sysmlv2_transform::SplitOptions { + uri_units: true, + ..options + }; + // The plan judges eligibility (a package, something nested). + let plan = session + .split_plan(package, &options) + .map_err(|e| e.to_string())?; + let edit = if with_edit { + let mut edit = session.edit(); + edit.split(&plan); + let report = edit.check().map_err(|e| e.to_string())?; + Some( + Self::annotated_edit(session, &plan, &report.splices, enc) + .ok_or_else(|| "the new units' names do not spell URIs".to_string())?, + ) + } else { + None + }; + let resolved = session.resolved(); + let nested_packages = |e: ElementRef| { + resolved + .owned_members(e) + .into_iter() + .filter(|&m| { + resolved.element_type(m) == "Package" && resolved.element_name(m).is_some() + }) + .count() + }; + let entries = plan + .entries + .iter() + .map(|e| SplitResponseEntry { + qualified_name: e.qualified.clone(), + name: e.name.clone(), + new_name: e.new_name.clone(), + root_name: sysmlv2_transform::spell_name(e.new_name.as_deref().unwrap_or(&e.name)), + uri: e.unit.clone(), + bytes: e.bytes, + nested: nested_packages(e.package), + }) + .collect(); + let name = resolved + .element_name(plan.root) + .unwrap_or_default() + .to_string(); + let qualified_name = resolved + .element_qualified_name(plan.root) + .unwrap_or_else(|| name.clone()); + Ok(SplitResponse { + root: SplitResponseRoot { + name, + qualified_name, + uri: plan.root_unit.clone(), + }, + directory: plan.directory, + entries, + edit, + }) + } + + /// A split's splices as one annotated workspace edit: a create + /// operation plus the full text for every new unit, ranged edits for + /// the existing ones, all under one change annotation that names + /// the split and its files in a client's refactor preview. The + /// annotation does not ask for confirmation: editors take that flag + /// as "opt in to each change" and open their preview with every + /// change unticked, while a split is one whole. + fn annotated_edit( + session: &Session, + plan: &sysmlv2_transform::SplitPlan, + splices: &[sysmlv2_transform::AppliedSplice], + enc: Encoding, + ) -> Option { + const ANNOTATION: &str = "split"; + let mut ops: Vec = Vec::new(); + for entry in &plan.entries { + let uri = Uri::from_str(&entry.unit).ok()?; + ops.push(lsp_types::DocumentChangeOperation::Op( + lsp_types::ResourceOp::Create(lsp_types::CreateFile { + uri: uri.clone(), + options: None, + annotation_id: Some(ANNOTATION.to_string()), + }), + )); + let text: String = splices + .iter() + .filter(|s| s.unit == entry.unit) + .map(|s| s.text.as_str()) + .collect(); + ops.push(lsp_types::DocumentChangeOperation::Edit( + lsp_types::TextDocumentEdit { + text_document: lsp_types::OptionalVersionedTextDocumentIdentifier { + uri, + version: None, + }, + edits: vec![lsp_types::OneOf::Right(lsp_types::AnnotatedTextEdit { + text_edit: TextEdit { + range: lsp_types::Range::default(), + new_text: text, + }, + annotation_id: ANNOTATION.to_string(), + })], + }, + )); + } + for (_, unit_name, text) in session.units() { + let mut edits: Vec> = + Vec::new(); + let mapper = Mapper::new(text, enc); + let mut unit_splices: Vec<&sysmlv2_transform::AppliedSplice> = + splices.iter().filter(|s| s.unit == unit_name).collect(); + unit_splices.sort_by_key(|s| (s.start, s.end)); + for s in unit_splices { + edits.push(lsp_types::OneOf::Right(lsp_types::AnnotatedTextEdit { + text_edit: TextEdit { + range: mapper.range(Span::new(s.start, s.end)), + new_text: s.text.clone(), + }, + annotation_id: ANNOTATION.to_string(), + })); + } + if edits.is_empty() { + continue; + } + ops.push(lsp_types::DocumentChangeOperation::Edit( + lsp_types::TextDocumentEdit { + text_document: lsp_types::OptionalVersionedTextDocumentIdentifier { + uri: Uri::from_str(unit_name).ok()?, + version: None, + }, + edits, + }, + )); + } + let files: Vec<&str> = plan.entries.iter().map(|e| e.unit.as_str()).collect(); + let mut annotations = HashMap::new(); + annotations.insert( + ANNOTATION.to_string(), + lsp_types::ChangeAnnotation { + label: format!("Split into {} new file(s)", plan.entries.len()), + needs_confirmation: None, + description: Some(files.join("\n")), + }, + ); + Some(WorkspaceEdit { + changes: None, + document_changes: Some(lsp_types::DocumentChanges::Operations(ops)), + change_annotations: Some(annotations), + }) + } + + /// The lint findings of `uri`'s unit that carry a fix, with every fix + /// rendered as a workspace edit over the session's texts. The pass + /// runs once per session build and `sysmlint.json` text (read from + /// the workspace root, as the push tier does). + pub fn lint_fixes( + &mut self, + docs: &BTreeMap, + uri: &Uri, + enc: Encoding, + ) -> Vec { + let Some(unit) = self.lint_unit(docs, uri) else { + return Vec::new(); + }; + self.lint_fix_sets(enc, |f| f.unit == Some(unit)) + } + + /// Every finding of `rule` across the workspace that carries a fix, + /// as fix sets — the requesting document's among them. Behind the + /// "fix every finding of this rule" actions. + pub fn lint_rule_fixes( + &mut self, + docs: &BTreeMap, + uri: &Uri, + enc: Encoding, + rule: &str, + ) -> Vec { + if self.lint_unit(docs, uri).is_none() { + return Vec::new(); + } + self.lint_fix_sets(enc, |f| f.rule == rule) + } + + /// Builds the session and caches the lint pass (per session build and + /// config text); the unit `uri` names, when the session holds it. + fn lint_unit(&mut self, docs: &BTreeMap, uri: &Uri) -> Option { + let generation = self.config.get().0; + self.session(docs)?; + let cached = self + .lint + .as_ref() + .filter(|(g, _)| *g == generation) + .is_some(); + if !cached { + let config = self.config.get().1; + let session = self.session.as_mut().expect("session built above"); + let texts: Vec<(usize, String)> = session + .units() + .map(|(i, _, t)| (i, t.to_string())) + .collect(); + let sources: Vec<(usize, &str)> = texts.iter().map(|(i, t)| (*i, t.as_str())).collect(); + let findings = sysmlv2_lint::lint_with_sources(session.resolved(), config, &sources); + self.lint = Some((generation, findings)); + } + let session: &Session = self.session.as_ref().expect("session built above"); + Self::unit_of_static(uri, session) + } + + /// The cached findings `keep` admits, as fix sets (findings without a + /// fix, or whose fix names a unit the session does not hold, drop). + fn lint_fix_sets( + &self, + enc: Encoding, + keep: impl Fn(&sysmlv2_lint::Finding) -> bool, + ) -> Vec { + let session: &Session = self.session.as_ref().expect("session built above"); + let findings = &self.lint.as_ref().expect("lint pass cached above").1; + // One line index per unit for every edit of every fix (see + // `UnitMappers`). + let mut mappers = UnitMappers::new(enc); + findings + .iter() + .filter(|f| keep(f)) + .filter_map(|f| { + let fix = f.fix.as_ref()?; + let (unit, span) = (f.unit?, f.span?); + let edit = Self::fix_edit(session, fix, &mut mappers)?; + let alternatives = f + .alternatives + .iter() + .filter_map(|a| { + Self::fix_edit(session, a, &mut mappers) + .map(|e| (a.label.clone(), a.semantic, e)) + }) + .collect(); + let range = mappers.get(unit, || unit_of(session, unit))?.1.range(span); + Some(LintFixSet { + rule: f.rule.id(), + range, + label: fix.label.clone(), + semantic: fix.semantic, + deletes: fix.deletes, + edit, + alternatives, + }) + }) + .collect() + } + + /// A lint fix's byte-offset edits over session units as a workspace + /// edit; `None` when an edit names a unit the session does not hold. + /// `mappers` memoizes each unit's name and line index across calls. + fn fix_edit<'s>( + session: &'s Session, + fix: &sysmlv2_lint::Fix, + mappers: &mut UnitMappers<'s, usize>, + ) -> Option { + let mut changes: HashMap> = HashMap::new(); + for e in &fix.edits { + let (name, mapper) = mappers.get(e.unit, || unit_of(session, e.unit))?; + changes + .entry(Uri::from_str(name).ok()?) + .or_default() + .push(TextEdit { + range: mapper.range(e.span), + new_text: e.replacement.clone(), + }); + } + Some(WorkspaceEdit { + changes: Some(changes), + ..Default::default() + }) + } + + /// Visibility advice for the import declared at `offset` in `uri`, + /// from the workspace model (see + /// `ResolvedModel::import_visibility_advice`). + pub fn import_visibility_advice( + &mut self, + docs: &BTreeMap, + uri: &Uri, + offset: u32, + ) -> Option { + let session = self.session(docs)?; + let unit = Self::unit_of_static(uri, session)?; + let resolved = session.resolved(); + let (import, _, _) = resolved + .imports_without_visibility() + .into_iter() + .find(|(_, u, span)| *u == unit && span.start <= offset && offset <= span.end)?; + resolved.import_visibility_advice(import) + } + /// "Extract definition": offered when the cursor sits on the /// declaration of a usage the eligibility gate admits. The edit is a /// dry-run's splices as ranged edits (cross-file capable); the /// session is left untouched, so no invalidation is needed. pub fn refactor_extract_action( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, enc: Encoding, @@ -808,7 +1335,7 @@ impl Nav { /// the inline. Same dry-run contract as extract. pub fn refactor_inline_action( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, enc: Encoding, @@ -862,9 +1389,13 @@ impl Nav { /// every name declared in the open documents, kinds mapped from the /// outline. Deliberately position-blind in this first cut — the /// body-context inversion of the validation matrix is the noted follow-up. - /// The library's `(unit name, text)` sources, both variants. + /// The library's `(unit name, text)` sources. fn library_sources(lib: &Library) -> Vec<(String, String)> { match lib { + Library::Prepared(library) => library + .sources() + .map(|(name, text)| (name.to_owned(), text.to_owned())) + .collect(), Library::Sources { units, .. } => units.as_ref().clone(), Library::Dir(dir) => { fn walk(dir: &std::path::Path, out: &mut Vec<(String, String)>) { @@ -901,7 +1432,7 @@ impl Nav { let mut symbols: Vec = Vec::new(); if let Some(lib) = &self.library { for (name, text) in Self::library_sources(lib) { - let parse = if name.ends_with(".kerml") { + let parse = if crate::is_kerml(name.as_str()) { sysmlv2_parser::parser::parse_kerml_source(&text) } else { sysmlv2_parser::parser::parse_source(&text) @@ -925,15 +1456,15 @@ impl Nav { /// this — the open-documents map alone hides most of the workspace. fn all_workspace_symbols( &mut self, - docs: &HashMap, + docs: &BTreeMap, enc: Encoding, ) -> Vec { let mut out = workspace_symbols(docs, enc); if self.workspace_seed_symbols.is_none() { if let Some(units) = &self.workspace { let mut symbols: Vec = Vec::new(); - for (name, text) in units { - let parse = if name.ends_with(".kerml") { + for (name, text) in units.iter() { + let parse = if crate::is_kerml(name) { sysmlv2_parser::parser::parse_kerml_source(text) } else { sysmlv2_parser::parser::parse_source(text) @@ -975,7 +1506,7 @@ impl Nav { /// no invalidate needed. pub fn optimize_imports( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, enc: Encoding, ) -> Option> { @@ -1020,7 +1551,7 @@ impl Nav { /// Returns `(title, document, edit, preferred)`. pub fn unresolved_reference_fixes( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: u32, enc: Encoding, @@ -1038,7 +1569,7 @@ impl Nav { }; let mut out: Vec<(String, Uri, TextEdit, bool)> = Vec::new(); let bare = match (&token, "ed) { - (Some((t, segs)), _) if segs.len() == 1 => Some((segs[0].clone(), t.len() as u32)), + (Some((t, segs)), _) if segs.len() == 1 => Some((segs[0].clone(), offset32(t.len()))), (None, Some((name, len))) => Some((name.clone(), *len)), _ => None, }; @@ -1060,8 +1591,8 @@ impl Nav { }; let mapper = Mapper::new(&text, enc); // The last segment's own range (what a respelling replaces). - let last_start = offset + (token.len() - last.len()) as u32; - let last_range = mapper.range(Span::new(last_start, offset + token.len() as u32)); + let last_start = offset + offset32(token.len() - last.len()); + let last_range = mapper.range(Span::new(last_start, offset + offset32(token.len()))); if prefix.is_empty() { // Bare name: suggest near-miss workspace names. @@ -1098,7 +1629,7 @@ impl Nav { // not); fallback: a unique workspace element carrying the // qualifier's final segment as its name. let prefix_last = prefix.last().expect("non-empty prefix").clone(); - let prefix_end = offset + (token.len() - last.len() - 2) as u32; + let prefix_end = offset + offset32(token.len() - last.len() - 2); let target = { let resolved = session.resolved(); let by_site = resolved @@ -1190,7 +1721,7 @@ impl Nav { #[allow(clippy::too_many_arguments)] fn import_fixes( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, text: &str, offset: u32, @@ -1199,7 +1730,7 @@ impl Nav { enc: Encoding, out: &mut Vec<(String, Uri, TextEdit, bool)>, ) { - let parse = if uri.path().as_str().ends_with(".kerml") { + let parse = if crate::is_kerml(uri.path().as_str()) { sysmlv2_parser::parser::parse_kerml_source(text) } else { sysmlv2_parser::parser::parse_source(text) @@ -1234,7 +1765,7 @@ impl Nav { out.push(( format!( "Add import {}", - crate::autoimport::escape_qualified(&s.qualified) + crate::autoimport::escape_qualified(crate::dialect_of(uri), &s.qualified) ), uri.clone(), TextEdit { @@ -1257,7 +1788,7 @@ impl Nav { /// qualified) it was built from. fn append_unit_type_edits( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, enc: Encoding, (cx, tcx): (&CompletionCx, &UnitTypeCx), @@ -1281,7 +1812,7 @@ impl Nav { let mapper = Mapper::new(text, enc); let insert_at = mapper.range(Span::new(tcx.name_end, tcx.name_end)); let Some(session) = - self.completion_session(docs, uri, Span::new(cx.stmt_start, line_end as u32)) + self.completion_session(docs, uri, Span::new(cx.stmt_start, offset32(line_end))) else { return; }; @@ -1325,7 +1856,8 @@ impl Nav { } } let [target] = types[..] else { continue }; - let Some(spelling) = resolved.type_spelling_at(scope, target) else { + let dialect = Some(crate::dialect_of(uri)); + let Some(spelling) = resolved.type_spelling_at(dialect, scope, target) else { continue; }; out[*idx] @@ -1350,7 +1882,7 @@ impl Nav { /// direct members. pub fn completions( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, offset: Option, enc: Encoding, @@ -1406,12 +1938,14 @@ impl Nav { } if s.is_member_of(&path) && seen.insert(s.name.clone()) { let (text_edit, repair, insert_text_format) = match "ing { - Some((mapper, text)) => item_edits(text, mapper, cx, &s.name, snippets), + Some((mapper, text)) => { + item_edits(text, mapper, cx, crate::dialect_of(uri), &s.name, snippets) + } None => (None, None, None), }; meta.push((out.len(), s.name.clone(), s.qualified.clone())); out.push(CompletionItem { - label: s.name.clone(), + label: crate::outline::spell_name(&s.name), kind: Some(s.kind), detail: Some(s.qualified.clone()), documentation: s.documentation(), @@ -1467,9 +2001,10 @@ impl Nav { if is_phantom(s) || s.depth > 2 || !seen.insert(s.qualified.clone()) { continue; } - let qualified = crate::autoimport::escape_qualified(&s.qualified); + let qualified = + crate::autoimport::escape_qualified(crate::dialect_of(uri), &s.qualified); out.push(CompletionItem { - label: s.name.clone(), + label: crate::outline::spell_name(&s.name), kind: Some(s.kind), detail: Some(if s.depth == 0 { "standard library".to_string() @@ -1502,7 +2037,7 @@ impl Nav { // declaration, an admitting import). let doc = docs.get(uri); let parsed = match (cx.as_ref(), doc) { - (Some(_), Some(d)) => Some(if uri.path().as_str().ends_with(".kerml") { + (Some(_), Some(d)) => Some(if crate::is_kerml(uri.path().as_str()) { sysmlv2_parser::parser::parse_kerml_source(&d.text) } else { sysmlv2_parser::parser::parse_source(&d.text) @@ -1546,7 +2081,14 @@ impl Nav { // The main edit (quoting + repair suffix) and the repair // insertion, per item; merged with the import edit below. let edits_for = |s: &QualifiedSymbol| match cx.as_ref().zip(mapper.as_ref().zip(doc)) { - Some((cx, (mapper, d))) => item_edits(&d.text, mapper, cx, &s.name, snippets), + Some((cx, (mapper, d))) => item_edits( + &d.text, + mapper, + cx, + crate::dialect_of(uri), + &s.name, + snippets, + ), None => (None, None, None), }; let assemble = |s: &QualifiedSymbol| { @@ -1580,7 +2122,7 @@ impl Nav { assemble(s); meta.push((out.len(), s.name.clone(), s.qualified.clone())); out.push(CompletionItem { - label: s.name.clone(), + label: crate::outline::spell_name(&s.name), kind: Some(s.kind), detail: (!s.qualified.eq(&s.name)).then(|| s.qualified.clone()), documentation: s.documentation(), @@ -1602,7 +2144,7 @@ impl Nav { let (text_edit, additional_text_edits, label_details, insert_text_format) = assemble(s); meta.push((out.len(), s.name.clone(), s.qualified.clone())); out.push(CompletionItem { - label: s.name.clone(), + label: crate::outline::spell_name(&s.name), kind: Some(s.kind), detail: Some(if s.depth == 0 { "standard library".to_string() @@ -1629,7 +2171,7 @@ impl Nav { /// feature whose domain the asserted constraints narrow). pub fn inlay_hints( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, enc: Encoding, ) -> Vec { @@ -1649,7 +2191,7 @@ impl Nav { // Evaluated values: every declared feature whose value expression // is not already a literal and whose value the evaluator settles. - let parse = if uri.path().as_str().ends_with(".kerml") { + let parse = if crate::is_kerml(uri.path().as_str()) { sysmlv2_parser::parser::parse_kerml_source(&doc_text) } else { sysmlv2_parser::parser::parse_source(&doc_text) @@ -1692,7 +2234,8 @@ impl Nav { // name — except after a bare reference, which already spells // the same element, and for the unbound self-result. let rendered = match value { - sysmlv2_parser::eval::Value::Unbound(_) => continue, + sysmlv2_parser::eval::Value::Unbound(_) + | sysmlv2_parser::eval::Value::UnboundMember(_) => continue, sysmlv2_parser::eval::Value::Element(t) => { if bare_ref || t == e { continue; @@ -1702,7 +2245,9 @@ impl Nav { None => continue, } } - v => session.resolved().render_value(&v), + // Editor hints favour a glanceable decimal over an exact + // fraction (`≈0.3333333333333333`, not `1/3`). + v => session.resolved().render_value_approx(&v), }; // A hint that restates the declared expression token for // token (`x = 3.63 [kg]` ⇒ ` = 3.63 [kg]`) adds nothing. @@ -1776,9 +2321,12 @@ impl Nav { if dunit != unit { continue; } + // Editor hints take the glanceable spelling: a bound + // without a terminating decimal expansion shows as an + // approximate decimal rather than a fraction. let label = match &r.unit { - Some(u) => format!(" ∈ {} [{u}]", r.range), - None => format!(" ∈ {}", r.range), + Some(u) => format!(" ∈ {} [{u}]", r.range_approx), + None => format!(" ∈ {}", r.range_approx), }; out.push(lsp_types::InlayHint { position: mapper.position(dspan.end), @@ -1800,7 +2348,7 @@ impl Nav { /// then interval propagation (solverless; Z3 stays a CLI concern). pub fn code_lenses( &mut self, - docs: &HashMap, + docs: &BTreeMap, uri: &Uri, enc: Encoding, ) -> Vec { @@ -1911,14 +2459,7 @@ impl Nav { enc: Encoding, ) -> Option { if let Some((name, text)) = session.library_unit(unit) { - let mut uri = String::from("sysmlv2-lib:/"); - for c in name.chars() { - match c { - ' ' => uri.push_str("%20"), - '%' => uri.push_str("%25"), - c => uri.push(c), - } - } + let uri = format!("sysmlv2-lib:/{}", crate::worker::encode_uri_path(name)); let mapper = Mapper::new(text, enc); return Some(Location { uri: Uri::from_str(&uri).ok()?, @@ -1935,6 +2476,85 @@ impl Nav { } } +/// The workspace's `sysmlint.json`, read from disk only when it +/// changes. Formatting and every code-action request consult it, both +/// of which fire per keystroke or per cursor move, and each consult +/// used to be a directory read, a file read and a JSON parse. +struct LintConfig { + path: Option, + /// The file's `(modified, len)` at the last read, `None` for no + /// readable file — a file written twice inside one clock tick, at + /// the same length, is the one change this misses. + stamp: Option<(std::time::SystemTime, u64)>, + /// Bumped whenever the configuration changes, so a cache built on + /// it can tell one from another without keeping its text. + generation: u64, + config: sysmlv2_lint::Config, + read: bool, +} + +impl LintConfig { + fn under(root: Option<&std::path::Path>) -> LintConfig { + LintConfig { + path: root.map(|r| r.join("sysmlint.json")), + stamp: None, + generation: 0, + config: sysmlv2_lint::Config::default(), + read: false, + } + } + + /// The configuration and the generation it belongs to, re-reading + /// the file when its timestamp or size moved. An absent or + /// unparseable file is every rule at its default severity — the + /// worker publishes the parse error on the file itself. + fn get(&mut self) -> (u64, &sysmlv2_lint::Config) { + let stamp = self + .path + .as_ref() + .and_then(|p| std::fs::metadata(p).ok()) + .and_then(|m| Some((m.modified().ok()?, m.len()))); + if self.read && stamp == self.stamp { + return (self.generation, &self.config); + } + self.stamp = stamp; + self.read = true; + self.generation += 1; + self.config = self + .path + .as_ref() + .and_then(|p| std::fs::read_to_string(p).ok()) + .and_then(|text| sysmlv2_lint::Config::from_json(&text).ok()) + .unwrap_or_default(); + (self.generation, &self.config) + } +} + +/// The name and text of a session's user unit by model unit index. +fn unit_of(session: &Session, unit: usize) -> Option<(&str, &str)> { + session + .units() + .find(|(i, _, _)| *i == unit) + .map(|(_, name, text)| (name, text)) +} + +/// One lint finding's fixes, ready for a code-action response: the +/// finding's rule and range identify the diagnostic it rides, `edit` is +/// the preferred fix and `alternatives` the equally valid ones (label, +/// semantic, edit). +pub struct LintFixSet { + pub rule: &'static str, + pub range: lsp_types::Range, + pub label: String, + /// The fix changes what a declaration means: its own quick fix, + /// never part of fix-all. + pub semantic: bool, + /// The fix deletes model text: never part of fix-all. + pub deletes: bool, + pub edit: WorkspaceEdit, + pub alternatives: Vec<(String, bool, WorkspaceEdit)>, +} + /// Flatten one document's outline into (name, kind, range) triples for /// `workspace/symbol`. pub fn flatten_symbols( @@ -1947,7 +2567,7 @@ pub fn flatten_symbols( if query.is_empty() || s.name.to_lowercase().contains(&query.to_lowercase()) { #[allow(deprecated)] out.push(lsp_types::SymbolInformation { - name: s.name.clone(), + name: crate::outline::spell_name(&s.name), kind: s.kind, tags: None, deprecated: None, @@ -2022,7 +2642,7 @@ fn quoted_name_at(text: &str, offset: u32) -> Option<(String, u32)> { let inner = rest.strip_prefix('\'')?; let end = inner.find('\'')?; let name = &inner[..end]; - (!name.is_empty() && !name.contains('\\')).then(|| (name.to_string(), end as u32 + 2)) + (!name.is_empty() && !name.contains('\\')).then(|| (name.to_string(), offset32(end) + 2)) } fn is_identifier(s: &str) -> bool { @@ -2109,7 +2729,7 @@ fn enum_member_insertion(text: &str, decl: Span, name: &str) -> Option<(Span, St .take_while(|c| *c == ' ' || *c == '\t') .collect(); Some(( - Span::new(line_start as u32, line_start as u32), + Span::new(offset32(line_start), offset32(line_start)), format!("{indent} {name};\n"), )) } else { @@ -2118,7 +2738,7 @@ fn enum_member_insertion(text: &str, decl: Span, name: &str) -> Option<(Span, St } else { format!(" {name}; ") }; - Some((Span::new(close as u32, close as u32), insert)) + Some((Span::new(offset32(close), offset32(close)), insert)) } } @@ -2137,12 +2757,12 @@ fn whole_line_removal(text: &str, span: Span) -> Span { le += 1; } if indent_only && le < bytes.len() && bytes[le] == b'\n' { - return Span::new(ls as u32, (le + 1) as u32); + return Span::new(offset32(ls), offset32(le + 1)); } if indent_only && le == bytes.len() { - return Span::new(ls as u32, le as u32); + return Span::new(offset32(ls), offset32(le)); } - Span::new(start as u32, end as u32) + Span::new(offset32(start), offset32(end)) } /// "Sort imports": alphabetize each contiguous run of import @@ -2400,10 +3020,10 @@ fn collect_qualified( } /// Every open document's outline, flattened to qualified symbols. -fn workspace_symbols(docs: &HashMap, enc: Encoding) -> Vec { +fn workspace_symbols(docs: &BTreeMap, enc: Encoding) -> Vec { let mut out = Vec::new(); for (uri, doc) in docs { - let parse = if uri.path().as_str().ends_with(".kerml") { + let parse = if crate::is_kerml(uri.path().as_str()) { sysmlv2_parser::parser::parse_kerml_source(&doc.text) } else { sysmlv2_parser::parser::parse_source(&doc.text) @@ -2528,8 +3148,8 @@ pub(crate) fn untyped_attribute_unit_context(text: &str, cx: &CompletionCx) -> O } let bracket_open = open?; Some(UnitTypeCx { - name_end: cx.stmt_start + name_end as u32, - bracket_open: cx.stmt_start + bracket_open as u32, + name_end: cx.stmt_start + offset32(name_end), + bracket_open: cx.stmt_start + offset32(bracket_open), }) } @@ -2705,6 +3325,7 @@ fn item_edits( text: &str, mapper: &Mapper<'_>, cx: &CompletionCx, + dialect: sysmlv2_parser::ast::Dialect, name: &str, snippets: bool, ) -> ( @@ -2712,7 +3333,10 @@ fn item_edits( Option, Option, ) { - let escaped = sysmlv2_parser::ast::escape_name(name); + // Insert text is source for this document: a name the dialect + // reserves (`'view'`) and a non-basic name are quoted, a word the + // dialect does not reserve stays bare — the label keeps the raw name. + let escaped = sysmlv2_parser::name::spell_name_in(Some(dialect), name); let range = crate::autoimport::replace_range_for(text, cx.partial_start, cx.offset, name); let repairs = crate::autofix::statement_repairs(text, cx.stmt_start, range.start, cx.offset); let (suffix, insert) = match repairs { @@ -2822,10 +3446,10 @@ pub(crate) fn completion_context(text: &str, offset: u32) -> CompletionCx { CompletionCx { qualifier, dot_chain, - partial_start: partial_start as u32, - offset: offset as u32, + partial_start: offset32(partial_start), + offset: offset32(offset), import, - stmt_start: stmt_start as u32, + stmt_start: offset32(stmt_start), } } diff --git a/crates/sysmlv2-lsp/src/outline.rs b/crates/sysmlv2-lsp/src/outline.rs index 3b7c118..225c242 100644 --- a/crates/sysmlv2-lsp/src/outline.rs +++ b/crates/sysmlv2-lsp/src/outline.rs @@ -28,11 +28,44 @@ use sysmlv2_parser::ast::{ use sysmlv2_parser::span::Span; /// Build the outline for one parsed unit over its source text. +/// +/// Names are the declared names verbatim (anonymous members get a +/// `«keyword»` label): the completion tier derives referenceable +/// spellings from this tree, so the empty unrestricted name `''` stays +/// `""` here. Responses that leave the server go through +/// [`spell_symbols`] / [`spell_name`], which give that name a visible +/// spelling — clients reject a symbol whose name is empty and drop the +/// whole outline of the file on one. +#[must_use] pub fn document_symbols(unit: &SourceUnit, src: &str, mapper: &Mapper<'_>) -> Vec { let ctx = Ctx { src, mapper }; walk(&unit.members, &ctx, false) } +/// A symbol or completion label that is never empty: the empty +/// unrestricted name is spelled as in source, `''`. Only for labels — +/// insert text must keep escaping the raw name. +#[must_use] +pub fn spell_name(raw: &str) -> String { + if raw.is_empty() { + "''".to_string() + } else { + raw.to_string() + } +} + +/// Apply [`spell_name`] to every symbol of an outline before it is sent. +pub fn spell_symbols(symbols: &mut [DocumentSymbol]) { + for s in symbols { + if s.name.is_empty() { + s.name = spell_name(""); + } + if let Some(children) = &mut s.children { + spell_symbols(children); + } + } +} + /// First `doc` body per declaration, keyed by the declared name's /// start position (the outline's `selection_range.start`). Syntax-tier /// like the outline itself, so completion can attach documentation @@ -415,6 +448,8 @@ fn usage_detail(u: &Usage, ctx: &Ctx<'_>) -> Option { /// Declared name: regular name preferred, short name as fallback, /// `«keyword»` for anonymous members (positional structure stays visible). +/// The empty unrestricted name `''` is legal and distinct from anonymity +/// and stays `""` here (see [`document_symbols`]). fn name_of(id: &Identification, keyword: &str) -> String { id.name .as_ref() @@ -430,7 +465,7 @@ fn sel(id: &Identification, member: Span) -> Span { .as_ref() .or(id.short_name.as_ref()) .map(|n| n.span) - .unwrap_or(Span::new(member.start, member.start)) + .unwrap_or_else(|| Span::new(member.start, member.start)) } #[allow(deprecated)] // DocumentSymbol's `deprecated` field must be filled diff --git a/crates/sysmlv2-lsp/src/position.rs b/crates/sysmlv2-lsp/src/position.rs index 07c4b27..6b5e618 100644 --- a/crates/sysmlv2-lsp/src/position.rs +++ b/crates/sysmlv2-lsp/src/position.rs @@ -6,8 +6,23 @@ //! `positionEncoding`) makes characters plain byte columns. use lsp_types::{Position, Range}; +use std::collections::HashMap; +use std::collections::hash_map::Entry; +use std::hash::Hash; use sysmlv2_parser::span::Span; +/// A count measured inside one document — a byte offset or length, a +/// line number, the width of one character — as the `u32` every span +/// in the toolkit is measured in. A unit too wide to address in 32 +/// bits has no spans to answer with in the first place, so the +/// conversion is total in practice. A document that somehow got here +/// anyway panics rather than answering a silently wrapped position — +/// the request loop turns that into one failed request and a message, +/// which is the containment this relies on. +pub(crate) fn offset32(n: usize) -> u32 { + u32::try_from(n).expect("a model unit is addressed in 32 bits") +} + #[derive(Clone, Copy, PartialEq, Eq, Debug)] pub enum Encoding { Utf8, @@ -23,11 +38,12 @@ pub struct Mapper<'a> { } impl<'a> Mapper<'a> { + #[must_use] pub fn new(text: &'a str, encoding: Encoding) -> Self { let mut line_starts = vec![0u32]; for (i, b) in text.bytes().enumerate() { if b == b'\n' { - line_starts.push(i as u32 + 1); + line_starts.push(offset32(i) + 1); } } Mapper { @@ -43,28 +59,30 @@ impl<'a> Mapper<'a> { } /// Convert a byte offset (clamped to the text) to an LSP position. + #[must_use] pub fn position(&self, offset: u32) -> Position { - let offset = offset.min(self.text.len() as u32); + let offset = offset.min(offset32(self.text.len())); let line = self.line_of(offset); let start = self.line_starts[line] as usize; let character = match self.encoding { - Encoding::Utf8 => offset - start as u32, + Encoding::Utf8 => offset - offset32(start), Encoding::Utf16 => self.text[start..offset as usize] .chars() - .map(|c| c.len_utf16() as u32) + .map(|c| offset32(c.len_utf16())) .sum(), }; Position { - line: line as u32, + line: offset32(line), character, } } /// Convert an LSP position to a byte offset, clamping past-the-end /// lines and columns (clients may send positions beyond the text). + #[must_use] pub fn offset(&self, pos: Position) -> u32 { let Some(&start) = self.line_starts.get(pos.line as usize) else { - return self.text.len() as u32; + return offset32(self.text.len()); }; let line_end = self .line_starts @@ -75,16 +93,17 @@ impl<'a> Mapper<'a> { let mut units = 0u32; for (i, c) in line.char_indices() { if units >= pos.character { - return start + i as u32; + return start + offset32(i); } units += match self.encoding { - Encoding::Utf8 => c.len_utf8() as u32, - Encoding::Utf16 => c.len_utf16() as u32, + Encoding::Utf8 => offset32(c.len_utf8()), + Encoding::Utf16 => offset32(c.len_utf16()), }; } - line_end as u32 + offset32(line_end) } + #[must_use] pub fn range(&self, span: Span) -> Range { Range { start: self.position(span.start), @@ -93,15 +112,53 @@ impl<'a> Mapper<'a> { } /// The range covering the whole document (for full-text edits). + #[must_use] pub fn full_range(&self) -> Range { Range { start: Position { line: 0, character: 0, }, - end: self.position(self.text.len() as u32), + end: self.position(offset32(self.text.len())), + } + } +} + +/// Line indexes over a set of units, each built on first use and shared +/// by every span mapped afterwards. A workspace cycle or a code-action +/// request maps many spans per unit; building the index anew per span +/// walks the whole text each time, which on a large model with +/// thousands of findings costs findings × text bytes. +pub(crate) struct UnitMappers<'a, K> { + encoding: Encoding, + built: HashMap)>, +} + +impl<'a, K: Hash + Eq> UnitMappers<'a, K> { + pub(crate) fn new(encoding: Encoding) -> Self { + UnitMappers { + encoding, + built: HashMap::new(), } } + + /// The name and line index of the unit under `key`, built from + /// `unit()` — its `(name, text)` — on first use; `None` when + /// `unit()` finds nothing. + pub(crate) fn get( + &mut self, + key: K, + unit: impl FnOnce() -> Option<(&'a str, &'a str)>, + ) -> Option<(&'a str, &Mapper<'a>)> { + let slot = match self.built.entry(key) { + Entry::Occupied(o) => o.into_mut(), + Entry::Vacant(v) => { + let (name, text) = unit()?; + v.insert((name, Mapper::new(text, self.encoding))) + } + }; + Some((slot.0, &slot.1)) + } } #[cfg(test)] @@ -200,7 +257,7 @@ mod tests { line: 99, character: 0 }), - TEXT.len() as u32 + offset32(TEXT.len()) ); } @@ -209,9 +266,45 @@ mod tests { for enc in [Encoding::Utf8, Encoding::Utf16] { let m = Mapper::new(TEXT, enc); for (i, _) in TEXT.char_indices() { - let off = i as u32; + let off = offset32(i); assert_eq!(m.offset(m.position(off)), off, "offset {off} {enc:?}"); } } } + + /// Every span of a unit maps through one line index: the second and + /// later lookups of a unit reuse the index the first built, and each + /// unit still maps against its own text. + #[test] + fn unit_mappers_build_one_index_per_unit() { + let built = std::cell::Cell::new(0u32); + let mut mappers: UnitMappers<'static, usize> = UnitMappers::new(Encoding::Utf8); + let lookup = |unit: usize| { + built.set(built.get() + 1); + match unit { + 0 => Some(("a", "one\ntwo\n")), + 1 => Some(("b", "\n\nthree\n")), + _ => None, + } + }; + let at = |mappers: &mut UnitMappers<'static, usize>, + unit: usize, + offset: u32| + -> Option<(&'static str, u32)> { + mappers + .get(unit, || lookup(unit)) + .map(|(name, m)| (name, m.position(offset).line)) + }; + assert_eq!(at(&mut mappers, 0, 0), Some(("a", 0))); + assert_eq!(at(&mut mappers, 0, 4), Some(("a", 1))); + assert_eq!(at(&mut mappers, 1, 4), Some(("b", 2))); + assert_eq!(at(&mut mappers, 1, 0), Some(("b", 0))); + assert_eq!(at(&mut mappers, 0, 4), Some(("a", 1))); + assert_eq!(built.get(), 2, "one index per unit, however many spans"); + // A unit the session does not hold yields nothing, and is not + // remembered as an index. + assert_eq!(at(&mut mappers, 2, 0), None); + assert_eq!(at(&mut mappers, 2, 0), None); + assert_eq!(built.get(), 4); + } } diff --git a/crates/sysmlv2-lsp/src/push.rs b/crates/sysmlv2-lsp/src/push.rs index f435166..f297ef7 100644 --- a/crates/sysmlv2-lsp/src/push.rs +++ b/crates/sysmlv2-lsp/src/push.rs @@ -20,10 +20,15 @@ use lsp_server::{Connection, ErrorCode, Message, Request, Response}; use lsp_types::request::{Initialize, Request as _, Shutdown}; use lsp_types::{InitializeParams, InitializeResult, ServerInfo}; -use std::collections::HashMap; +use std::collections::BTreeMap; use crate::{Error, Server, capabilities, negotiate_encoding, worker}; +/// The server endpoint is held from construction until `initialize` +/// builds the server around it, and `server` is `Some` from then on, so +/// exactly one of the two is always available to answer on. +const HELD_UNTIL_BUILT: &str = "the server endpoint is held until the server is built"; + /// A server driven by [`PushServer::handle`] calls instead of a /// blocking main loop. pub struct PushServer { @@ -33,7 +38,7 @@ pub struct PushServer { library: Option, /// In-memory workspace units, held when seeded before `initialize` /// (applied to the server's navigation at build time). - workspace: Option>, + workspace: Option>>, /// Held until `initialize` arrives (the server is built from its /// params); `None` afterwards. server_conn: Option, @@ -70,6 +75,7 @@ impl Default for PushServer { } impl PushServer { + #[must_use] pub fn new() -> PushServer { Self::new_with(None) } @@ -77,6 +83,7 @@ impl PushServer { /// A push server whose navigation and completions see an in-memory /// standard library (`(unit name, text)` units, optionally with a /// sealed resolution snapshot recorded against the same units). + #[must_use] pub fn with_library_sources( units: Vec<(String, String)>, snapshot: Option>, @@ -141,6 +148,7 @@ impl PushServer { /// like any [`Self::handle`] output; without the drain they ride /// along with the next dispatch). pub fn set_workspace_sources(&mut self, units: Vec<(String, String)>) { + let units = std::sync::Arc::new(units); if let Some(server) = &mut self.server { server.nav.set_workspace_sources(units.clone()); self.send_refreshes(); @@ -213,15 +221,11 @@ impl PushServer { )))?; } Some(server) => server.handle_request(req)?, - None => { - self.client_conn - .sender - .send(Message::Response(Response::new_err( - req.id, - ErrorCode::ServerNotInitialized as i32, - "initialize first".to_string(), - )))?; - } + None => self.reply(Response::new_err( + req.id, + ErrorCode::ServerNotInitialized as i32, + "initialize first".to_string(), + ))?, }, Message::Notification(n) => { // `initialized` and `exit` need nothing here; the rest @@ -239,19 +243,41 @@ impl PushServer { Ok(out) } + /// A response produced outside a built server's own dispatch, on + /// the server→client channel [`Self::handle`] drains — the channel + /// the built server answers on, or, before `initialize`, the one it + /// will be built around. (The client endpoint's sender feeds the + /// server's inbox, which nothing here reads.) + fn reply(&self, response: Response) -> Result<(), Error> { + let sender = match &self.server { + Some(server) => &server.connection.sender, + None => &self.server_conn.as_ref().expect(HELD_UNTIL_BUILT).sender, + }; + sender.send(Message::Response(response))?; + Ok(()) + } + fn initialize(&mut self, req: Request) -> Result<(), Error> { - let Some(connection) = self.server_conn.take() else { + if self.server.is_some() { // Double initialize: protocol error. - self.client_conn - .sender - .send(Message::Response(Response::new_err( + return self.reply(Response::new_err( + req.id, + ErrorCode::InvalidRequest as i32, + "already initialized".to_string(), + )); + } + let init: InitializeParams = match serde_json::from_value(req.params) { + Ok(init) => init, + Err(e) => { + // Malformed: answered, and still initializable. + return self.reply(Response::new_err( req.id, - ErrorCode::InvalidRequest as i32, - "already initialized".to_string(), - )))?; - return Ok(()); + ErrorCode::InvalidParams as i32, + format!("initialize: invalid params: {e}"), + )); + } }; - let init: InitializeParams = serde_json::from_value(req.params)?; + let connection = self.server_conn.take().expect(HELD_UNTIL_BUILT); let encoding = negotiate_encoding(&init); let ws = init.capabilities.workspace.as_ref(); self.inlay_refresh = ws @@ -288,10 +314,11 @@ impl PushServer { self.server = Some(Server { connection, encoding, - docs: HashMap::new(), + docs: BTreeMap::new(), nav, worker: worker::Worker::disabled(), root: None, + reported: std::collections::HashSet::new(), }); Ok(()) } @@ -301,7 +328,7 @@ impl PushServer { mod tests { use super::PushServer; - fn responses(server: &mut PushServer, msg: serde_json::Value) -> Vec { + fn responses(server: &mut PushServer, msg: &serde_json::Value) -> Vec { server .handle(&msg.to_string()) .expect("handled") @@ -318,7 +345,7 @@ mod tests { let mut s = PushServer::new(); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {"general": {"positionEncodings": ["utf-8"]}}}}), ); assert_eq!(out.len(), 1); @@ -330,13 +357,13 @@ mod tests { responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "initialized", "params": {}}), + &serde_json::json!({"jsonrpc": "2.0", "method": "initialized", "params": {}}), ); // A document with a syntax-tier problem publishes diagnostics. let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///workspace/m.sysml", "languageId": "sysml", "version": 1, "text": "package P { part def X; part x : X; "}}}), ); @@ -348,7 +375,7 @@ mod tests { let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/documentSymbol", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/documentSymbol", "params": {"textDocument": {"uri": "file:///workspace/m.sysml"}}}), ); let symbols = out[0]["result"].as_array().expect("symbol tree"); @@ -357,11 +384,147 @@ mod tests { let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "shutdown", "params": null}), + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "shutdown", "params": null}), ); assert_eq!(out[0]["result"], serde_json::Value::Null); } + /// Malformed messages are answered (requests) or logged + /// (notifications) and never end the session — a bad `initialize` + /// included, which leaves the server initializable. + #[test] + fn malformed_messages_do_not_end_the_session() { + let mut s = PushServer::new(); + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 0, "method": "textDocument/hover", + "params": {}}), + ); + assert_eq!(out[0]["error"]["code"], -32002, "{out:?}"); + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": {"capabilities": 7}}), + ); + assert_eq!(out[0]["error"]["code"], -32602, "{out:?}"); + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "initialize", + "params": {"capabilities": {}}}), + ); + assert_eq!(out[0]["result"]["serverInfo"]["name"], "sysmlv2-lsp"); + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "initialize", + "params": {"capabilities": {}}}), + ); + assert_eq!(out[0]["error"]["code"], -32600, "{out:?}"); + + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + "textDocument": {"uri": "file:///w/m.sysml", "version": "one"}}}), + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert_eq!(out[0]["method"], "window/logMessage"); + assert!( + out[0]["params"]["message"] + .as_str() + .unwrap() + .starts_with("textDocument/didOpen: invalid params"), + "{out:?}" + ); + + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/documentSymbol", + "params": {"textDocument": {"uri": null}}}), + ); + assert_eq!(out[0]["id"], 3); + assert_eq!(out[0]["error"]["code"], -32602, "{out:?}"); + + responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", + "version": 1, "text": "package P { part def X; }"}}}), + ); + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/documentSymbol", + "params": {"textDocument": {"uri": "file:///w/m.sysml"}}}), + ); + assert_eq!(out[0]["result"][0]["name"], "P", "{out:?}"); + } + + /// A handler that panics answers the request with an internal + /// error, says so once, and leaves the session serving — the same + /// for a notification, which has no reply to carry the error. (The + /// panics these two messages provoke print to stderr as usual; the + /// point is that the session outlives them.) + #[test] + fn a_panicking_handler_does_not_end_the_session() { + let mut s = PushServer::new(); + responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + "params": {"capabilities": {}}}), + ); + responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", + "version": 1, "text": "package P { part def X; }"}}}), + ); + + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": crate::PANIC_METHOD, + "params": null}), + ); + let shown: Vec<&serde_json::Value> = out + .iter() + .filter(|m| m["method"] == "window/showMessage") + .collect(); + assert_eq!(shown.len(), 1, "{out:?}"); + assert!( + shown[0]["params"]["message"] + .as_str() + .unwrap() + .contains(crate::PANIC_REASON), + "{out:?}" + ); + let answer = out.iter().find(|m| m["id"] == 2).expect("answered"); + assert_eq!(answer["error"]["code"], -32603, "{out:?}"); + + // The same failure a second time is not announced again. + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": crate::PANIC_METHOD, + "params": null}), + ); + assert!( + !out.iter().any(|m| m["method"] == "window/showMessage"), + "{out:?}" + ); + assert_eq!(out[0]["error"]["code"], -32603, "{out:?}"); + + // A notification whose handling panics is dropped, not fatal. + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "method": crate::PANIC_METHOD, "params": null}), + ); + assert!(out.is_empty(), "{out:?}"); + + // Still serving. + let out = responses( + &mut s, + &serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/documentSymbol", + "params": {"textDocument": {"uri": "file:///w/m.sysml"}}}), + ); + assert_eq!(out[0]["result"][0]["name"], "P", "{out:?}"); + } + /// With in-memory library sources, completions offer the library's /// packages and direct members alongside workspace names. #[test] @@ -375,18 +538,18 @@ mod tests { ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {}}}), ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P { part def X; }"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 0, "character": 12}}}), ); @@ -408,14 +571,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n private import OtherLib::*;\n part w : \n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 2, "character": 13}}}), ); @@ -457,14 +620,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n attribute g = 9.8 [m/s];\n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 26}}}), ); @@ -501,14 +664,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n attribute gravity = 9.8 [m\n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 30}}}), ); @@ -533,14 +696,14 @@ mod tests { // becomes its own insertion behind it. responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 2}, "contentChanges": [ {"text": "package P {\n attribute gravity = 9.8 [m]\n}\n"}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 30}}}), ); @@ -565,14 +728,14 @@ mod tests { // Already terminated: nothing to repair. responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 3}, "contentChanges": [ {"text": "package P {\n attribute gravity = 9.8 [m];\n}\n"}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 30}}}), ); @@ -591,19 +754,19 @@ mod tests { /// before the auto-inserted `];`, where typing continues. #[test] fn snippet_client_gets_cursor_stop_before_repairs() { - let mut s = two_package_server_with_caps(serde_json::json!({ + let mut s = two_package_server_with_caps(&serde_json::json!({ "general": {"positionEncodings": ["utf-8"]}, "textDocument": {"completion": {"completionItem": {"snippetSupport": true}}}})); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n attribute gravity = 9.8 [m\n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 30}}}), ); @@ -618,14 +781,14 @@ mod tests { // An import-context accept carries its `;` the same way. responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 2}, "contentChanges": [ {"text": "package P {\n private import Widge\n}\n"}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 24}}}), ); @@ -640,14 +803,14 @@ mod tests { // No repairs → no snippet: the plain quoting edit stays plain. responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 3}, "contentChanges": [ {"text": "package P {\n attribute gravity = 9.8 [m];\n}\n"}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 30}}}), ); @@ -666,14 +829,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n attribute g = Widge.value\n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 1, "character": 23}}}), ); @@ -719,13 +882,13 @@ mod tests { }\n"; responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": text}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 12, "character": 38}}}), ); @@ -753,13 +916,13 @@ mod tests { ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 2}, "contentChanges": [{"text": two}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 12, "character": 46}}}), ); @@ -774,13 +937,13 @@ mod tests { let broken = text.replace("= oxidizerTank.", "= noSuchTank."); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 3}, "contentChanges": [{"text": broken}]}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 4, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 12, "character": 36}}}), ); @@ -798,7 +961,7 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n part w : Widget;\n}\n"}}}), @@ -807,7 +970,7 @@ mod tests { "end": {"line": 1, "character": 19}}); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "range": range, "context": {"diagnostics": [ @@ -829,7 +992,7 @@ mod tests { // Quoted reference: the diagnostic starts at the quote. responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didChange", "params": { "textDocument": {"uri": "file:///w/m.sysml", "version": 2}, "contentChanges": [ {"text": "package P {\n attribute g = 9.8 ['m/s²'];\n}\n"}]}}), @@ -838,7 +1001,7 @@ mod tests { "end": {"line": 1, "character": 29}}); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/codeAction", + &serde_json::json!({"jsonrpc": "2.0", "id": 3, "method": "textDocument/codeAction", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "range": range, "context": {"diagnostics": [ @@ -870,7 +1033,7 @@ mod tests { ]); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n part e : Engine;\n}\n"}}}), @@ -879,7 +1042,7 @@ mod tests { "end": {"line": 1, "character": 19}}); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "range": range, "context": {"diagnostics": [ @@ -902,7 +1065,7 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n private import Widget;\n}\n"}}}), @@ -911,7 +1074,7 @@ mod tests { "end": {"line": 1, "character": 25}}); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/codeAction", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "range": range, "context": {"diagnostics": [ @@ -927,11 +1090,11 @@ mod tests { } fn two_package_server() -> PushServer { - two_package_server_with_caps(serde_json::json!( + two_package_server_with_caps(&serde_json::json!( {"general": {"positionEncodings": ["utf-8"]}})) } - fn two_package_server_with_caps(capabilities: serde_json::Value) -> PushServer { + fn two_package_server_with_caps(capabilities: &serde_json::Value) -> PushServer { let mut s = PushServer::with_library_sources( vec![( "MiniLib.kerml".to_string(), @@ -944,7 +1107,7 @@ mod tests { ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": capabilities}}), ); s @@ -968,13 +1131,13 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": text}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 0, "character": character}}}), ); @@ -1002,14 +1165,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P { private import Widg }"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 0, "character": 31}}}), ); @@ -1037,12 +1200,12 @@ mod tests { )]); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {"general": {"positionEncodings": ["utf-8"]}}}}), ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/uses.sysml", "languageId": "sysml", "version": 1, "text": "package Uses {\n private import Defs::*;\n part w : Wheel;\n}\n"}}}), @@ -1050,7 +1213,7 @@ mod tests { let definition = |s: &mut PushServer, id: i32| -> serde_json::Value { let out = responses( s, - serde_json::json!({"jsonrpc": "2.0", "id": id, "method": "textDocument/definition", + &serde_json::json!({"jsonrpc": "2.0", "id": id, "method": "textDocument/definition", "params": {"textDocument": {"uri": "file:///w/uses.sysml"}, "position": {"line": 2, "character": 14}}}), ); @@ -1082,19 +1245,19 @@ mod tests { ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {"general": {"positionEncodings": ["utf-8"]}}}}), ); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P {\n private import MiniLib::*;\n part w : Widget;\n}\n"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/definition", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/definition", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 2, "character": 14}}}), ); @@ -1115,14 +1278,14 @@ mod tests { let mut s = two_package_server(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { + &serde_json::json!({"jsonrpc": "2.0", "method": "textDocument/didOpen", "params": { "textDocument": {"uri": "file:///w/m.sysml", "languageId": "sysml", "version": 1, "text": "package P { private import Widg }"}}}), ); let out = responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", + &serde_json::json!({"jsonrpc": "2.0", "id": 2, "method": "textDocument/completion", "params": {"textDocument": {"uri": "file:///w/m.sysml"}, "position": {"line": 0, "character": 31}}}), ); @@ -1158,7 +1321,7 @@ mod tests { let mut s = PushServer::new(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {"workspace": { "inlayHint": {"refreshSupport": true}, "codeLens": {"refreshSupport": true}}}}}), @@ -1175,7 +1338,7 @@ mod tests { let mut s = PushServer::new(); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {}}}), ); s.set_workspace_sources(seed()); @@ -1209,7 +1372,7 @@ mod tests { assert_eq!(outbound(&mut s), Vec::::new()); responses( &mut s, - serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", + &serde_json::json!({"jsonrpc": "2.0", "id": 1, "method": "initialize", "params": {"capabilities": {"workspace": { "inlayHint": {"refreshSupport": true}}}}}), ); diff --git a/crates/sysmlv2-lsp/src/tokens.rs b/crates/sysmlv2-lsp/src/tokens.rs index 56bedfa..409b316 100644 --- a/crates/sysmlv2-lsp/src/tokens.rs +++ b/crates/sysmlv2-lsp/src/tokens.rs @@ -14,7 +14,7 @@ //! the grammars, and the corpus sweep asserts every `Ident` in every //! clean-parsing file classifies (a vocabulary gap cannot hide). -use crate::position::Mapper; +use crate::position::{Mapper, offset32}; use lsp_types::{SemanticToken, SemanticTokenModifier, SemanticTokenType}; use std::collections::HashMap; use sysmlv2_parser::ast::{ @@ -205,6 +205,7 @@ pub const VOCABULARY: &[&str] = &[ ]; /// Legend indices — the order is the wire protocol; append only. +#[must_use] pub fn legend_types() -> Vec { vec![ SemanticTokenType::NAMESPACE, // 0 @@ -219,6 +220,7 @@ pub fn legend_types() -> Vec { ] } +#[must_use] pub fn legend_modifiers() -> Vec { vec![SemanticTokenModifier::DECLARATION] // bit 0 } @@ -244,6 +246,7 @@ pub struct Classified { /// Classify one parsed unit's tokens. `tokens` must be the unfiltered /// lexer output for `src` (trivia included — notes classify as comments). +#[must_use] pub fn classify(unit: &SourceUnit, src: &str, tokens: &[Token]) -> Vec { let names = collect_name_roles(unit); let mut out = Vec::new(); @@ -449,6 +452,7 @@ fn record_qn(map: &mut HashMap<(u32, u32), (u32, u32)>, qn: &QualifiedName, ty: /// Encode classified tokens as the LSP wire format: sorted, multi-line /// comments split per line (multiline tokens need a client capability we /// don't assume), lengths in the negotiated encoding's units. +#[must_use] pub fn encode(mut toks: Vec, src: &str, mapper: &Mapper<'_>) -> Vec { toks.sort_by_key(|t| t.span.start); let mut out = Vec::with_capacity(toks.len()); @@ -477,7 +481,7 @@ pub fn encode(mut toks: Vec, src: &str, mapper: &Mapper<'_>) -> Vec< if text.contains('\n') { let mut line_start = t.span.start; for line in text.split('\n') { - let line_end = line_start + line.len() as u32; + let line_end = line_start + offset32(line.len()); if line_start < line_end { push(Span::new(line_start, line_end), t.token_type, t.modifiers); } @@ -492,6 +496,7 @@ pub fn encode(mut toks: Vec, src: &str, mapper: &Mapper<'_>) -> Vec< /// Convenience: how many `Ident` tokens failed to classify (the corpus /// completeness gate — 0 on clean-parsing files). +#[must_use] pub fn unclassified_idents(unit: &SourceUnit, src: &str, tokens: &[Token]) -> Vec { let names = collect_name_roles(unit); tokens @@ -506,6 +511,7 @@ pub fn unclassified_idents(unit: &SourceUnit, src: &str, tokens: &[Token]) -> Ve } /// The unfiltered token stream for one text (lexer output, trivia kept). +#[must_use] pub fn lex(src: &str) -> Vec { sysmlv2_parser::lexer::tokenize(src).0 } diff --git a/crates/sysmlv2-lsp/src/worker.rs b/crates/sysmlv2-lsp/src/worker.rs index 95c07bb..f6f152e 100644 --- a/crates/sysmlv2-lsp/src/worker.rs +++ b/crates/sysmlv2-lsp/src/worker.rs @@ -13,21 +13,41 @@ //! The syntax tier still publishes per keystroke for fast feedback; this //! worker's fuller set replaces it a debounce later. -use crate::position::{Encoding, Mapper}; +use crate::Report; +use crate::position::{Encoding, UnitMappers}; use lsp_server::Message; +use lsp_types::notification::Notification as _; use lsp_types::{DiagnosticSeverity, DiagnosticTag, PublishDiagnosticsParams, Uri}; use std::collections::{HashMap, HashSet}; +use std::panic::{AssertUnwindSafe, catch_unwind}; use std::path::PathBuf; use std::str::FromStr; use std::sync::mpsc; use std::time::Duration; -use sysmlv2_transform::{Session, Severity, check_sources}; +use sysmlv2_transform::{Library, Session, Severity, check_sources}; pub(crate) const UNUSED_IMPORT_MESSAGE: &str = "unused private import"; +/// Stack reserved for the worker thread. +/// +/// The worker parses, and the parser bounds its own descent at a depth +/// it can only reach on a stack sized for it — the size named here. A +/// thread that does not ask for one gets two megabytes, a fraction of +/// that bound: ordinary nested input the parser accepts and reports +/// nothing about would end the whole language server, editor session and +/// all, with no diagnostic and no unwind to catch. +/// +/// Reserved address space, not resident pages: the cost of asking for it +/// is nothing until the recursion touches it. +/// +/// It is the parser's own constant, not a number sized to match one, so +/// there is nothing here that can drift from what the bound asks for. +const WORKER_STACK_BYTES: usize = sysmlv2_parser::parser::MAX_NESTING_STACK_BYTES; + pub(crate) struct Job { - /// (uri, version, text) of every open document. - pub docs: Vec<(String, i32, String)>, + /// (uri, version, text) of every open document; the texts are + /// shared with the document store, not copied per job. + pub docs: Vec<(String, i32, std::sync::Arc)>, pub root: Option, } @@ -43,8 +63,52 @@ impl Worker { debounce: Duration, ) -> Worker { let (tx, rx) = mpsc::channel::(); - std::thread::spawn(move || run(rx, sender, library, encoding, debounce)); - Worker { tx } + let client = sender.clone(); + let spawned = std::thread::Builder::new() + .name("sysmlv2-lsp-worker".into()) + .stack_size(WORKER_STACK_BYTES) + .spawn(move || { + run(&rx, &sender, library.as_deref(), encoding, debounce, cycle); + }); + match spawned { + Ok(_) => Worker { tx }, + Err(err) => Worker::unstarted(&client, &err), + } + } + + /// The worker whose thread never started. No thread, no model tier: + /// the syntax tier keeps publishing per keystroke and every job is + /// dropped, exactly as for a host without threads — but a host that + /// *has* threads and could not give this one a stack the size the + /// parser's bound asks for has lost half its findings, so it is told + /// rather than left to notice. + /// + /// Once, both ways: the thread is started once, so the failure is + /// reported once — the log carries what the system said, and the + /// message says what the editor session loses by it. + fn unstarted(sender: &crossbeam_channel::Sender, err: &std::io::Error) -> Worker { + let lost = "the workspace model tier is off: its thread could not be started. \ + Findings are the open file's own syntax only — the library-aware and \ + cross-file ones are not computed."; + for notification in [ + lsp_server::Notification::new( + lsp_types::notification::LogMessage::METHOD.to_string(), + lsp_types::LogMessageParams { + typ: lsp_types::MessageType::ERROR, + message: format!("{lost} The thread was refused: {err}"), + }, + ), + lsp_server::Notification::new( + lsp_types::notification::ShowMessage::METHOD.to_string(), + lsp_types::ShowMessageParams { + typ: lsp_types::MessageType::ERROR, + message: lost.to_string(), + }, + ), + ] { + let _ = sender.send(Message::Notification(notification)); + } + Worker::disabled() } pub fn schedule(&self, job: Job) { @@ -60,17 +124,24 @@ impl Worker { } } +/// One cycle's work — [`cycle`], swapped out in tests. +type CycleFn = fn(&Job, Option<&std::path::Path>, Encoding) -> (Diagnostics, Vec); + fn run( - rx: mpsc::Receiver, - sender: crossbeam_channel::Sender, - library: Option, + rx: &mpsc::Receiver, + sender: &crossbeam_channel::Sender, + library: Option<&std::path::Path>, encoding: Encoding, debounce: Duration, + cycle: CycleFn, ) { // Uris published last cycle — files whose findings vanish (or which // drop out of the workspace) publish an empty set once to clear. let mut published: HashSet = HashSet::new(); let mut pending: Option = None; + // Panics already announced: a model that panics on the text in the + // editor would otherwise announce it again per keystroke. + let mut announced: HashSet = HashSet::new(); loop { let mut job = match pending.take() { Some(j) => j, @@ -89,26 +160,140 @@ fn run( } } - let sources = collect_sources(&job); + // A panic in the model, the lint or the line mapping used to + // end this thread, after which every later job vanished into a + // dead channel and the editor kept the findings it had, for + // good, with nothing said. The cycle is skipped instead and the + // worker stays up for the next edit. + let (by_uri, reports) = + match catch_unwind(AssertUnwindSafe(|| cycle(&job, library, encoding))) { + Ok(done) => done, + Err(payload) => { + let reason = crate::panic_reason(payload.as_ref()); + let message = format!( + "model diagnostics failed: {reason}. \ + Findings already shown may be out of date." + ); + announce( + sender, + &mut announced, + &Report { + show: true, + message, + }, + ); + continue; + } + }; + // A model the worker could not build at all publishes nothing, + // which on its own reads as "no problems here". + for report in &reports { + announce(sender, &mut announced, report); + } + + // Latest-only: a job that arrived during computation wins. + if let Ok(newer) = rx.try_recv() { + pending = Some(newer); + continue; + } + let versions: HashMap<&str, i32> = job.docs.iter().map(|(u, v, _)| (u.as_str(), *v)).collect(); + let mut next_published = HashSet::new(); + for (uri_str, diagnostics) in by_uri { + if diagnostics.is_empty() && !published.contains(&uri_str) { + continue; // nothing to say, nothing to clear + } + let Ok(uri) = Uri::from_str(&uri_str) else { + continue; + }; + if !diagnostics.is_empty() { + next_published.insert(uri_str.clone()); + } + let params = PublishDiagnosticsParams { + uri, + diagnostics, + version: versions.get(uri_str.as_str()).copied(), + }; + let _ = sender.send(Message::Notification(lsp_server::Notification::new( + "textDocument/publishDiagnostics".to_string(), + params, + ))); + } + published = next_published; + } +} - // Findings per uri (every workspace file gets an entry so stale - // sets clear). - let mut by_uri: HashMap> = sources - .iter() - .map(|(u, _)| (u.clone(), Vec::new())) - .collect(); +/// Findings keyed by the uri they belong to. +type Diagnostics = HashMap>; - let named: Vec<(String, String)> = sources.clone(); - if let Ok(findings) = check_sources(&named, library.as_deref()) { +/// Tell the client about a failure the first time it comes up. The +/// same failure recurs on every keystroke until it is fixed, and one +/// popup per keystroke is worse than the silence it replaces. +fn announce( + sender: &crossbeam_channel::Sender, + announced: &mut HashSet, + report: &Report, +) { + if !announced.insert(report.message.clone()) { + return; + } + // What the user has to act on is an error; the rest is background + // for whoever reads the log. + let message = report.message.clone(); + let notification = if report.show { + let typ = lsp_types::MessageType::ERROR; + lsp_server::Notification::new( + lsp_types::notification::ShowMessage::METHOD.to_string(), + lsp_types::ShowMessageParams { typ, message }, + ) + } else { + let typ = lsp_types::MessageType::WARNING; + lsp_server::Notification::new( + lsp_types::notification::LogMessage::METHOD.to_string(), + lsp_types::LogMessageParams { typ, message }, + ) + }; + let _ = sender.send(Message::Notification(notification)); +} + +/// One workspace cycle: the findings of every workspace unit, keyed by +/// uri (every unit gets an entry, so stale sets clear). +fn cycle( + job: &Job, + library: Option<&std::path::Path>, + encoding: Encoding, +) -> (Diagnostics, Vec) { + // A failure here can only come from the library: the units + // themselves are already in memory. + let mut reports: Vec = Vec::new(); + let from_library = library.is_some(); + let sources = collect_sources(job); + let mut by_uri: Diagnostics = sources + .iter() + .map(|(u, _)| (u.clone(), Vec::new())) + .collect(); + + // The check set, keyed by unit name; one line index per unit with + // findings, built over the texts that are about to move into the + // session. + match check_sources(&sources, library) { + Err(e) => reports.extend(Report::for_session_failure(&e, from_library)), + Ok(findings) => { + let texts: HashMap<&str, &str> = sources + .iter() + .map(|(u, t)| (u.as_str(), t.as_str())) + .collect(); + let mut mappers = UnitMappers::new(encoding); for f in findings { - let Some((_, text)) = sources.iter().find(|(u, _)| *u == f.unit) else { + let Some((&name, &text)) = texts.get_key_value(f.unit.as_str()) else { + continue; + }; + let Some((_, mapper)) = mappers.get(name, || Some((name, text))) else { continue; }; - let mapper = Mapper::new(text, encoding); by_uri - .entry(f.unit.clone()) + .entry(f.unit) .or_default() .push(lsp_types::Diagnostic { range: mapper.range(f.span), @@ -122,149 +307,131 @@ fn run( }); } } + } - // Unused private imports: a second model build; bounded - // and debounced, so the duplication is acceptable until a shared - // check pipeline exists. - let session = Session::from_sources(named); - let session = match (&library, session) { - (Some(dir), Ok(s)) => s.with_library(dir).ok(), - (None, Ok(s)) => Some(s), - (_, Err(_)) => None, + // Unused private imports and the lint: a second model build over + // the same sources (one build, library included); bounded and + // debounced, so the duplication is acceptable until a shared check + // pipeline exists. + let library = library.map(Library::dir); + let mut session = match Session::from_sources_with_library(sources, library) { + Ok(session) => session, + Err(e) => { + reports.extend(Report::for_session_failure(&e, from_library)); + return (by_uri, reports); + } + }; + let unused = session.unused_private_imports(); + + // Configurable lint: project policy from the workspace root's + // sysmlint.json, over the same resolved model. Absent file = every + // rule at its default severity; unreadable JSON degrades to + // defaults with the error published on the config file itself — + // where `lint-config` findings (unknown ids/options) anchor too, so + // a typo is never silent. + let config_path = job.root.as_ref().map(|r| r.join("sysmlint.json")); + let config_uri = config_path.as_ref().map(|p| uri_for_path(p)); + let mut config_errors: Vec = Vec::new(); + let config = match config_path.as_ref().map(std::fs::read_to_string) { + Some(Ok(text)) => match sysmlv2_lint::Config::from_json(&text) { + Ok(c) => c, + Err(e) => { + config_errors.push(e.to_string()); + sysmlv2_lint::Config::default() + } + }, + _ => sysmlv2_lint::Config::default(), + }; + let push_config = |message: String, by: &mut Diagnostics| { + let Some(uri) = &config_uri else { return }; + by.entry(uri.clone()) + .or_default() + .push(lsp_types::Diagnostic { + range: lsp_types::Range::default(), + severity: Some(DiagnosticSeverity::WARNING), + source: Some("sysmlv2 lint".to_string()), + code: Some(lsp_types::NumberOrString::String("lint-config".to_string())), + message, + ..Default::default() + }); + }; + for e in config_errors.drain(..) { + push_config(e, &mut by_uri); + } + // The units' names and texts, copied out once: the textual lint + // tier (`indentation`) reads the texts while the resolved model is + // borrowed mutably, and both tiers' findings map through the same + // line indexes afterwards. User unit indexes run consecutively from + // the first one, so a finding's unit indexes straight into this. + let units: Vec<(String, String)> = session + .units() + .map(|(_, n, t)| (n.to_string(), t.to_string())) + .collect(); + let first_unit = session.units().next().map_or(0, |(i, _, _)| i); + let unit_at = |unit: usize| { + unit.checked_sub(first_unit) + .and_then(|i| units.get(i)) + .map(|(n, t)| (n.as_str(), t.as_str())) + }; + let lint_sources: Vec<(usize, &str)> = units + .iter() + .enumerate() + .map(|(i, (_, t))| (i + first_unit, t.as_str())) + .collect(); + let findings = sysmlv2_lint::lint_with_sources(session.resolved(), &config, &lint_sources); + + // One line index per unit, shared by every finding of both tiers. + let mut mappers = UnitMappers::new(encoding); + for (unit, span) in unused { + let Some((name, mapper)) = mappers.get(unit, || unit_at(unit)) else { + continue; }; - if let Some(mut session) = session { - for (unit, span) in session.unused_private_imports() { - let Some((_, name, text)) = session.units().find(|(i, _, _)| *i == unit) else { + by_uri + .entry(name.to_string()) + .or_default() + .push(lsp_types::Diagnostic { + range: mapper.range(span), + severity: Some(DiagnosticSeverity::WARNING), + source: Some("sysmlv2".to_string()), + message: UNUSED_IMPORT_MESSAGE.to_string(), + tags: Some(vec![DiagnosticTag::UNNECESSARY]), + ..Default::default() + }); + } + for f in findings { + let severity = match f.severity { + sysmlv2_lint::Severity::Error => DiagnosticSeverity::ERROR, + sysmlv2_lint::Severity::Info => DiagnosticSeverity::INFORMATION, + sysmlv2_lint::Severity::Hint => DiagnosticSeverity::HINT, + _ => DiagnosticSeverity::WARNING, + }; + match f.unit.zip(f.span) { + Some((unit, span)) => { + let Some((name, mapper)) = mappers.get(unit, || unit_at(unit)) else { continue; }; - let mapper = Mapper::new(text, encoding); by_uri .entry(name.to_string()) .or_default() .push(lsp_types::Diagnostic { range: mapper.range(span), - severity: Some(DiagnosticSeverity::WARNING), - source: Some("sysmlv2".to_string()), - message: UNUSED_IMPORT_MESSAGE.to_string(), - tags: Some(vec![DiagnosticTag::UNNECESSARY]), + severity: Some(severity), + source: Some("sysmlv2 lint".to_string()), + code: Some(lsp_types::NumberOrString::String(f.rule.to_string())), + // Dead-model rules render faded, like unused + // imports. + tags: f + .rule + .is_dead_model() + .then(|| vec![DiagnosticTag::UNNECESSARY]), + message: f.message, ..Default::default() }); } - - // Configurable lint: project policy from the - // workspace root's sysmlint.json, over the same resolved - // model. Absent file = every rule at its default severity; - // unreadable JSON degrades to defaults with the error - // published on the config file itself — where `lint-config` - // findings (unknown ids/options) anchor too, so a typo is - // never silent. - let config_path = job.root.as_ref().map(|r| r.join("sysmlint.json")); - let config_uri = config_path.as_ref().map(|p| uri_for_path(p)); - let mut config_errors: Vec = Vec::new(); - let config = match config_path.as_ref().map(std::fs::read_to_string) { - Some(Ok(text)) => match sysmlv2_lint::Config::from_json(&text) { - Ok(c) => c, - Err(e) => { - config_errors.push(e); - sysmlv2_lint::Config::default() - } - }, - _ => sysmlv2_lint::Config::default(), - }; - let unit_texts: Vec<(usize, String, String)> = session - .units() - .map(|(i, n, t)| (i, n.to_string(), t.to_string())) - .collect(); - let push_config = - |message: String, by: &mut HashMap>| { - let Some(uri) = &config_uri else { return }; - by.entry(uri.clone()) - .or_default() - .push(lsp_types::Diagnostic { - range: lsp_types::Range::default(), - severity: Some(DiagnosticSeverity::WARNING), - source: Some("sysmlv2 lint".to_string()), - code: Some(lsp_types::NumberOrString::String( - "lint-config".to_string(), - )), - message, - ..Default::default() - }); - }; - for e in config_errors.drain(..) { - push_config(e, &mut by_uri); - } - // The textual tier (`indentation`) reads the units' source text. - let sources: Vec<(usize, &str)> = unit_texts - .iter() - .map(|(i, _, t)| (*i, t.as_str())) - .collect(); - for f in sysmlv2_lint::lint_with_sources(session.resolved(), &config, &sources) { - let severity = match f.severity { - sysmlv2_lint::Severity::Error => DiagnosticSeverity::ERROR, - sysmlv2_lint::Severity::Info => DiagnosticSeverity::INFORMATION, - sysmlv2_lint::Severity::Hint => DiagnosticSeverity::HINT, - _ => DiagnosticSeverity::WARNING, - }; - match f.unit.zip(f.span) { - Some((unit, span)) => { - let Some((_, name, text)) = unit_texts.iter().find(|(i, _, _)| *i == unit) - else { - continue; - }; - let mapper = Mapper::new(text, encoding); - by_uri - .entry(name.clone()) - .or_default() - .push(lsp_types::Diagnostic { - range: mapper.range(span), - severity: Some(severity), - source: Some("sysmlv2 lint".to_string()), - code: Some(lsp_types::NumberOrString::String(f.rule.to_string())), - // Dead-model rules render faded, like - // unused imports. - tags: f - .rule - .starts_with("unused-") - .then(|| vec![DiagnosticTag::UNNECESSARY]), - message: f.message, - ..Default::default() - }); - } - None => push_config(f.message, &mut by_uri), - } - } - } - - // Latest-only: a job that arrived during computation wins. - if let Ok(newer) = rx.try_recv() { - pending = Some(newer); - continue; - } - - let mut next_published = HashSet::new(); - for (uri_str, diagnostics) in by_uri { - if diagnostics.is_empty() && !published.contains(&uri_str) { - continue; // nothing to say, nothing to clear - } - let Ok(uri) = Uri::from_str(&uri_str) else { - continue; - }; - if !diagnostics.is_empty() { - next_published.insert(uri_str.clone()); - } - let params = PublishDiagnosticsParams { - uri, - diagnostics, - version: versions.get(uri_str.as_str()).copied(), - }; - let _ = sender.send(Message::Notification(lsp_server::Notification::new( - "textDocument/publishDiagnostics".to_string(), - params, - ))); + None => push_config(f.message, &mut by_uri), } - published = next_published; } + (by_uri, reports) } /// The workspace's sources: every model file under the root (skipping @@ -300,7 +467,7 @@ pub(crate) fn root_sources(root: &std::path::Path) -> Vec<(String, String)> { if !name.starts_with('.') && name != "target" && name != "node_modules" { stack.push(path); } - } else if name.ends_with(".sysml") || name.ends_with(".kerml") { + } else if crate::is_model_file(&name) { if let Ok(text) = std::fs::read_to_string(&path) { out.push((uri_for_path(&path), text)); } @@ -312,31 +479,464 @@ pub(crate) fn root_sources(root: &std::path::Path) -> Vec<(String, String)> { } /// Overlay one open document's text on the collected sources: replace -/// the on-disk unit under the same uri, or append a unit the walk did -/// not find. +/// the on-disk unit the client is editing — under the client's own +/// spelling of its uri, which is what diagnostics must be published +/// under — or append a unit the walk did not find. pub(crate) fn overlay_source(out: &mut Vec<(String, String)>, uri: &str, text: &str) { - match out.iter_mut().find(|(u, _)| u == uri) { - Some(slot) => slot.1 = text.to_string(), + match out.iter_mut().find(|(u, _)| same_unit(u, uri)) { + Some(slot) => { + slot.0 = uri.to_string(); + slot.1 = text.to_string(); + } None => out.push((uri.to_string(), text.to_string())), } } -/// A `file://` uri for an absolute path (space and percent encoded — the -/// characters that actually occur in model corpora). +/// Whether two uris name the same unit. Clients disagree with the walk +/// — and with each other — on which characters of a path they escape, +/// and a unit that only *looks* new joins the model a second time, so +/// everything it declares is reported as declared twice. +fn same_unit(a: &str, b: &str) -> bool { + a == b || matches!((decode(a), decode(b)), (Some(a), Some(b)) if a == b) +} + +/// A `file://` uri for an absolute path. pub(crate) fn uri_for_path(path: &std::path::Path) -> String { - let mut out = String::from("file://"); - for c in path.display().to_string().chars() { - match c { - ' ' => out.push_str("%20"), - '%' => out.push_str("%25"), - c => out.push(c), + let mut path = path.display().to_string(); + if std::path::MAIN_SEPARATOR == '\\' { + path = path.replace('\\', "/"); + } + // A drive-letter path has no leading separator of its own; the uri + // needs one, after the empty authority. + if !path.starts_with('/') { + path.insert(0, '/'); + } + format!("file://{}", encode_uri_path(&path)) +} + +/// Percent-encode a uri path. Everything RFC 3986 allows in a path +/// segment stays literal (the unreserved set, the sub-delimiters, `:` +/// and `@`) along with the separator; every other byte of the UTF-8 +/// spelling becomes `%XX`. Leaving the rest raw is not cosmetic: a `#` +/// would start a fragment and a `?` a query, and a non-ASCII byte is +/// not a uri character at all, so the result parses as no uri and that +/// file's diagnostics never reach the client. +pub(crate) fn encode_uri_path(path: &str) -> String { + use std::fmt::Write as _; + let mut out = String::with_capacity(path.len()); + for b in path.bytes() { + match b { + b'A'..=b'Z' + | b'a'..=b'z' + | b'0'..=b'9' + | b'-' + | b'.' + | b'_' + | b'~' + | b'!' + | b'$' + | b'&' + | b'\'' + | b'(' + | b')' + | b'*' + | b'+' + | b',' + | b';' + | b'=' + | b':' + | b'@' + | b'/' => out.push(b as char), + b => { + let _ = write!(out, "%{b:02X}"); + } } } out } -/// The path for a `file://` uri produced by [`uri_for_path`] or a client. +/// A percent-encoded uri with every `%XX` resolved, as UTF-8. `None` +/// when an escape is truncated or not hexadecimal, or when the bytes it +/// spells are not UTF-8 — nothing names a file there. +fn decode(uri: &str) -> Option { + if !uri.contains('%') { + return Some(uri.to_string()); + } + let bytes = uri.as_bytes(); + let mut out: Vec = Vec::with_capacity(bytes.len()); + let mut i = 0; + while i < bytes.len() { + if bytes[i] == b'%' { + out.push(u8::from_str_radix(uri.get(i + 1..i + 3)?, 16).ok()?); + i += 3; + } else { + out.push(bytes[i]); + i += 1; + } + } + String::from_utf8(out).ok() +} + +/// The path for a `file://` uri, from [`uri_for_path`] or from any +/// client: the parsed path component — never a query or a fragment, +/// whatever an unescaped `?` or `#` in a file name would otherwise make +/// of them — with every escape resolved, whatever the client escaped. pub(crate) fn path_for_uri(uri: &Uri) -> Option { - let s = uri.as_str().strip_prefix("file://")?; - Some(PathBuf::from(s.replace("%20", " ").replace("%25", "%"))) + if !uri + .scheme() + .is_some_and(|s| s.as_str().eq_ignore_ascii_case("file")) + { + return None; + } + let path = decode(uri.path().as_str())?; + // `/C:/dir/file`: the leading separator belongs to the empty + // authority, not to a drive-letter path. Only where drive letters + // are what paths start with, though — elsewhere `/a:/b` is an + // ordinary absolute path whose first segment happens to hold a + // colon, and dropping its root would make it relative. + let drive_letter = |rest: &str| { + let b = rest.as_bytes(); + cfg!(windows) && b.first().is_some_and(u8::is_ascii_alphabetic) && b.get(1) == Some(&b':') + }; + let path = match path.strip_prefix('/') { + Some(rest) if drive_letter(rest) => rest, + _ => &path, + }; + Some(PathBuf::from(path)) +} + +#[cfg(test)] +mod tests { + use super::*; + use sysmlv2_parser::parser::MAX_NESTING; + + const PANIC_TEXT: &str = "the model gave up"; + const FAILURE_TEXT: &str = "the library could not be read"; + + /// A worker whose thread never started used to disable the model + /// tier in silence: half the findings an editor shows stopped + /// arriving with nothing said, and asking for a stack the size the + /// parser's bound needs is exactly what makes a host refuse. What + /// the system said goes to the log, and what the session loses goes + /// to the client. + #[test] + fn a_worker_whose_thread_is_refused_says_so() { + let (out, messages) = crossbeam_channel::unbounded(); + let refused = std::io::Error::new(std::io::ErrorKind::OutOfMemory, "no room for a thread"); + let worker = Worker::unstarted(&out, &refused); + // Still a worker, and still one that swallows jobs. + worker.schedule(Job { + docs: Vec::new(), + root: None, + }); + + let sent: Vec<(String, String)> = messages + .try_iter() + .map(|m| { + let Message::Notification(n) = m else { + panic!("{m:?}") + }; + (n.method, n.params["message"].as_str().unwrap().to_string()) + }) + .collect(); + let methods: Vec<&str> = sent.iter().map(|(m, _)| m.as_str()).collect(); + assert_eq!( + methods, + ["window/logMessage", "window/showMessage"], + "{sent:?}" + ); + assert!(sent[0].1.contains("no room for a thread"), "{sent:?}"); + for (_, message) in &sent { + assert!(message.contains("model tier is off"), "{sent:?}"); + } + } + + /// Input nested to the parser's bound is ordinary input — a + /// kilobyte and a half of it here, with nothing to report — and the + /// bound only reports what it bounds on a stack sized for it. On the + /// two megabytes a thread gets when it asks for nothing, the descent + /// ends the process: no diagnostic, no unwind, no server. + /// + /// The worker is started here exactly as the server starts it, so + /// what this runs on is the stack it really runs on. A worker whose + /// reservation went missing does not fail this test — it ends the + /// test process. + #[test] + fn the_worker_parses_at_the_nesting_bound() { + // One level is the package, so the braces within it stop one + // short of the bound. + let levels = MAX_NESTING as usize - 1; + let deep = format!( + "package P {{ {}part x;{} }}", + "part x { ".repeat(levels), + "}".repeat(levels) + ); + // Nesting that also carries a full operator chain at every + // level: the same descent with the widest expression the parser + // admits hanging off it. + let chain = (0..960) + .map(|i| format!("a{i} > 0")) + .collect::>() + .join(" and "); + let wide = format!( + "package P {{ {}part y;{} }}", + format!("part x {{ attribute v = {chain}; ").repeat(60), + "}".repeat(60) + ); + + // A clean document publishes nothing at all — an empty set is + // only sent to clear findings already shown — so each job + // carries a second document that does have something to say. + // Its publish is the signal that the cycle ran to the end, and + // the deep document's silence is the finding count being zero. + const MARKER: &str = "file:///w/marker.sysml"; + let (out, messages) = crossbeam_channel::unbounded(); + let worker = Worker::spawn(out, None, Encoding::Utf8, Duration::from_millis(1)); + for (name, text) in [("deep", deep), ("wide", wide)] { + let uri = format!("file:///w/{name}.sysml"); + worker.schedule(Job { + docs: vec![ + (uri.clone(), 1, text.into()), + (MARKER.to_string(), 1, "package".into()), + ], + root: None, + }); + let deadline = std::time::Instant::now() + Duration::from_secs(60); + loop { + let m = messages + .recv_deadline(deadline) + .expect("the worker answers every job"); + let Message::Notification(n) = m else { + continue; + }; + assert_eq!(n.method, "textDocument/publishDiagnostics", "{n:?}"); + assert_eq!( + n.params["uri"], MARKER, + "{name}: nesting the parser accepts has nothing to report" + ); + assert!( + n.params["diagnostics"] + .as_array() + .is_some_and(|d| !d.is_empty()), + "{}: the marker's own finding: {}", + name, + n.params + ); + break; + } + } + } + + /// A cycle that gives up on a document whose text is its own panic + /// message, reports a failure for one whose text asks for it, and + /// otherwise yields one finding per document. + fn flaky_cycle( + job: &Job, + _library: Option<&std::path::Path>, + _encoding: Encoding, + ) -> (Diagnostics, Vec) { + let mut reports = Vec::new(); + let by_uri = job + .docs + .iter() + .map(|(uri, _, text)| { + assert_ne!(&**text, PANIC_TEXT, "{PANIC_TEXT}"); + if &**text == FAILURE_TEXT { + reports.push(Report { + show: true, + message: FAILURE_TEXT.to_string(), + }); + } + ( + uri.clone(), + vec![lsp_types::Diagnostic { + message: text.to_string(), + ..Default::default() + }], + ) + }) + .collect(); + (by_uri, reports) + } + + /// A cycle that panics used to end the worker thread, after which + /// every later job vanished into a dead channel and the editor kept + /// its findings for good with nothing said. It is announced once + /// instead, and the next job publishes as usual — as is a cycle + /// that ran but could not build the model. + #[test] + fn a_failed_cycle_is_announced_once_and_the_worker_keeps_serving() { + let (tx, rx) = mpsc::channel::(); + let (out, messages) = crossbeam_channel::unbounded(); + let worker = std::thread::spawn(move || { + run( + &rx, + &out, + None, + Encoding::Utf8, + Duration::from_millis(1), + flaky_cycle, + ); + }); + let job = |text: &str| Job { + docs: vec![("file:///w/m.sysml".to_string(), 1, text.into())], + root: None, + }; + let next = |kind: &str| -> serde_json::Value { + let deadline = std::time::Instant::now() + Duration::from_secs(10); + loop { + let m = messages + .recv_deadline(deadline) + .expect("the worker answers every job"); + let Message::Notification(n) = m else { + continue; + }; + assert_eq!(n.method, kind, "{n:?}"); + return n.params; + } + }; + + tx.send(job(PANIC_TEXT)).expect("worker alive"); + let params = next("window/showMessage"); + assert!( + params["message"].as_str().unwrap().contains(PANIC_TEXT), + "{params}" + ); + + tx.send(job("first")).expect("worker alive"); + let params = next("textDocument/publishDiagnostics"); + assert_eq!(params["diagnostics"][0]["message"], "first", "{params}"); + + // The same failure again says nothing more; the job after it + // still publishes, and its publish is the next message out. + tx.send(job(PANIC_TEXT)).expect("worker alive"); + tx.send(job("second")).expect("worker alive"); + let params = next("textDocument/publishDiagnostics"); + assert_eq!(params["diagnostics"][0]["message"], "second", "{params}"); + + // A cycle that ran but could not build the model says so once + // too: an empty finding set on its own reads as "no problems". + tx.send(job(FAILURE_TEXT)).expect("worker alive"); + let params = next("window/showMessage"); + assert_eq!(params["message"], FAILURE_TEXT, "{params}"); + let params = next("textDocument/publishDiagnostics"); + assert_eq!( + params["diagnostics"][0]["message"], FAILURE_TEXT, + "{params}" + ); + tx.send(job(FAILURE_TEXT)).expect("worker alive"); + let params = next("textDocument/publishDiagnostics"); + assert_eq!( + params["diagnostics"][0]["message"], FAILURE_TEXT, + "the same failure is not announced twice: {params}" + ); + + drop(tx); + worker.join().expect("the worker ends with its channel"); + } + + /// Paths a corpus really contains — a space, an accent, a `#`, a + /// `%` — survive the round trip, and the uri they produce is one a + /// client can parse. A raw `#` or `?` would otherwise start a + /// fragment or a query and a raw non-ASCII byte is no uri character + /// at all, leaving a uri nothing can be published against. + #[test] + fn uris_round_trip_the_paths_a_corpus_contains() { + for path in [ + "/w/models/plain.sysml", + "/w/my models/Heizöl.sysml", + "/w/a#b/c?d.sysml", + "/w/100%/x.kerml", + "/w/日本語/モデル.sysml", + "/w/punct/a+b,c;d=e:f@g!h$i&j'k(l)m*n.sysml", + ] { + let uri = uri_for_path(std::path::Path::new(path)); + let parsed = Uri::from_str(&uri).unwrap_or_else(|e| panic!("{uri}: {e}")); + assert_eq!( + path_for_uri(&parsed), + Some(PathBuf::from(path)), + "{uri} from {path}" + ); + } + // The sub-delimiters a path may carry literally are not + // escaped, so the spelling stays the one clients use. + assert_eq!( + uri_for_path(std::path::Path::new("/w/a+b/c.sysml")), + "file:///w/a+b/c.sysml" + ); + assert_eq!( + uri_for_path(std::path::Path::new("/w/a#b.sysml")), + "file:///w/a%23b.sysml" + ); + // Why those two have to be escaped: a raw non-ASCII byte is no + // uri character, and a raw `#` ends the path and starts a + // fragment. + assert!(Uri::from_str("file:///w/Heizöl.sysml").is_err()); + assert_eq!( + path_for_uri(&Uri::from_str("file:///w/a#b.sysml").unwrap()), + Some(PathBuf::from("/w/a")) + ); + } + + /// A client that escapes more than the walk does — the drive-letter + /// form a Windows client sends, or an escaped separator — still + /// names a path, and a malformed escape names none. + #[test] + fn a_clients_own_escaping_still_names_a_path() { + let path = |s: &str| path_for_uri(&Uri::from_str(s).unwrap()); + // Where paths begin with a drive letter the root separator is + // the empty authority's and comes off; everywhere else the same + // spelling is an ordinary absolute path and keeps its root. + let drive = |p: &str| { + Some(PathBuf::from(if cfg!(windows) { + p.to_string() + } else { + format!("/{p}") + })) + }; + assert_eq!(path("file:///c%3A/w/m.sysml"), drive("c:/w/m.sysml")); + assert_eq!(path("file:///c:/w/m.sysml"), drive("c:/w/m.sysml")); + // A first segment that merely contains a colon is not a drive. + assert_eq!( + path("file:///a:b/m.sysml"), + Some(PathBuf::from("/a:b/m.sysml")) + ); + assert_eq!( + path("file:///w/%E6%97%A5/m.sysml"), + Some(PathBuf::from("/w/日/m.sysml")) + ); + assert_eq!(path("sysmlv2-lib:/Lib.sysml"), None, "another scheme"); + // A well-formed escape that spells no text names no file; a + // malformed one is not a uri to begin with. + assert_eq!(path("file:///w/%FF.sysml"), None, "not UTF-8"); + assert!(Uri::from_str("file:///w/a%2").is_err()); + assert!(Uri::from_str("file:///w/a%zz").is_err()); + } + + /// An open document overlays the on-disk unit it edits even when + /// the client spells the uri with different escapes, and the unit + /// takes the client's spelling — the one its diagnostics must be + /// published under. Appending it instead would put the same + /// declarations into the model twice. + #[test] + fn an_open_document_overlays_its_on_disk_unit() { + let mut sources = vec![ + ("file:///w/a.sysml".to_string(), "package A;".to_string()), + ( + "file:///w/my+dir/b.sysml".to_string(), + "package B;".to_string(), + ), + ]; + overlay_source(&mut sources, "file:///w/my%2Bdir/b.sysml", "package B2;"); + assert_eq!(sources.len(), 2, "{sources:?}"); + assert_eq!( + sources[1], + ( + "file:///w/my%2Bdir/b.sysml".to_string(), + "package B2;".to_string() + ) + ); + overlay_source(&mut sources, "file:///w/c.sysml", "package C;"); + assert_eq!(sources.len(), 3, "a unit the walk did not find is added"); + } } diff --git a/crates/sysmlv2-lsp/tests/extras.rs b/crates/sysmlv2-lsp/tests/extras.rs index ae9522b..49ff5f5 100644 --- a/crates/sysmlv2-lsp/tests/extras.rs +++ b/crates/sysmlv2-lsp/tests/extras.rs @@ -58,9 +58,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{error:?}"); return serde_json::from_value(result.unwrap_or_default()).unwrap(); } @@ -119,7 +122,7 @@ fn completion_offers_keywords_and_workspace_names() { let resp = client.request_ok::(CompletionParams { text_document_position: TextDocumentPositionParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, position: Position { line: 1, character: 13, @@ -315,7 +318,7 @@ fn completion_items_carry_doc_bodies() { let resp = client.request_ok::(CompletionParams { text_document_position: TextDocumentPositionParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, position: Position { line: 1, character: 13, @@ -360,7 +363,7 @@ fn inlay_hints_show_evaluated_values_and_ranges() { ); let hints: Option> = client.request_ok::(InlayHintParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, range: Range { start: Position { line: 0, @@ -398,6 +401,53 @@ fn inlay_hints_show_evaluated_values_and_ranges() { client.shutdown(); } +#[test] +fn inlay_hints_show_non_terminating_rationals_as_approximate_decimals() { + let mut client = Client::start(); + let u = uri("r.sysml"); + // Exact decimals hint exactly; a rational with no terminating + // decimal expansion hints as a marked approximation rather than the + // fraction the CLI prints. + client.open( + &u, + "part def P {\n attribute tenth = 0.1 + 0.2;\n attribute third = 2 / 6;\n attribute mm;\n attribute pitch = (1 / 3) [mm];\n}\n", + ); + let hints: Option> = + client.request_ok::(InlayHintParams { + text_document: TextDocumentIdentifier { uri: u }, + range: Range { + start: Position { + line: 0, + character: 0, + }, + end: Position { + line: 6, + character: 0, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + }); + let labels: Vec = hints + .unwrap() + .iter() + .map(|h| match &h.label { + InlayHintLabel::String(s) => s.clone(), + other => panic!("unexpected label shape: {other:?}"), + }) + .collect(); + assert!(labels.iter().any(|l| l == " = 0.3"), "{labels:?}"); + assert!( + labels.iter().any(|l| l == " = ≈0.3333333333333333"), + "{labels:?}" + ); + assert!( + labels.iter().any(|l| l == " = ≈0.3333333333333333 [mm]"), + "{labels:?}" + ); + assert!(!labels.iter().any(|l| l.contains("1/3")), "{labels:?}"); + client.shutdown(); +} + #[test] fn inlay_hints_land_after_closing_parenthesis() { let mut client = Client::start(); @@ -411,7 +461,7 @@ fn inlay_hints_land_after_closing_parenthesis() { ); let hints: Option> = client.request_ok::(InlayHintParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, range: Range { start: Position { line: 0, @@ -517,7 +567,7 @@ fn inlay_hints_name_element_values_but_skip_bare_references() { ); let hints: Option> = client.request_ok::(InlayHintParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, range: Range { start: Position { line: 0, @@ -565,7 +615,7 @@ fn code_lenses_carry_verify_verdicts() { ); let lenses: Option> = client.request_ok::(CodeLensParams { - text_document: TextDocumentIdentifier { uri: u.clone() }, + text_document: TextDocumentIdentifier { uri: u }, work_done_progress_params: WorkDoneProgressParams::default(), partial_result_params: PartialResultParams::default(), }); @@ -600,3 +650,86 @@ fn code_lenses_carry_verify_verdicts() { ); client.shutdown(); } + +/// A definition named by a reserved word completes as source: the +/// label is the raw name, the insert text and the auto-import path +/// quote it. +#[test] +fn completion_quotes_reserved_word_names_in_edits() { + let mut client = Client::start(); + let defs = uri("defs.sysml"); + let u = uri("u.sysml"); + client.open(&defs, "package Defs { part def 'view'; }\n"); + client.open(&u, "package U {\n part w : \n}\n"); + let resp = client.request_ok::(CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: u }, + position: Position { + line: 1, + character: 13, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: None, + }); + let Some(CompletionResponse::Array(items)) = resp else { + panic!("expected items: {resp:?}"); + }; + let view = items + .iter() + .find(|i| i.label == "view" && i.kind == Some(CompletionItemKind::CLASS)) + .expect("cross-document name `view`"); + let Some(lsp_types::CompletionTextEdit::Edit(edit)) = &view.text_edit else { + panic!("quoted insert text needs an edit: {view:?}"); + }; + assert!(edit.new_text.starts_with("'view'"), "{edit:?}"); + let edits = view + .additional_text_edits + .as_ref() + .expect("out-of-scope name carries the import edit"); + assert_eq!(edits[0].new_text, "private import Defs::'view';\n "); + client.shutdown(); +} + +/// The document's dialect governs the spelling: in a KerML document a +/// word only SysML reserves is a plain name, so the insert text and the +/// auto-import path stay bare — quoting would be legal but the +/// formatter would immediately undo it. +#[test] +fn completion_spells_for_the_document_dialect() { + let mut client = Client::start(); + let defs = uri("defs.kerml"); + let u = uri("u.kerml"); + client.open(&defs, "package Defs { classifier part; }\n"); + client.open(&u, "package U {\n feature w : \n}\n"); + let resp = client.request_ok::(CompletionParams { + text_document_position: TextDocumentPositionParams { + text_document: TextDocumentIdentifier { uri: u }, + position: Position { + line: 1, + character: 16, + }, + }, + work_done_progress_params: WorkDoneProgressParams::default(), + partial_result_params: PartialResultParams::default(), + context: None, + }); + let Some(CompletionResponse::Array(items)) = resp else { + panic!("expected items: {resp:?}"); + }; + let part = items + .iter() + .find(|i| i.label == "part" && i.kind == Some(CompletionItemKind::CLASS)) + .expect("cross-document name `part`"); + if let Some(lsp_types::CompletionTextEdit::Edit(edit)) = &part.text_edit { + assert!(edit.new_text.starts_with("part"), "{edit:?}"); + assert!(!edit.new_text.starts_with("'"), "{edit:?}"); + } + let edits = part + .additional_text_edits + .as_ref() + .expect("out-of-scope name carries the import edit"); + assert_eq!(edits[0].new_text, "private import Defs::part;\n "); + client.shutdown(); +} diff --git a/crates/sysmlv2-lsp/tests/lsp.rs b/crates/sysmlv2-lsp/tests/lsp.rs index c771f62..7ae256f 100644 --- a/crates/sysmlv2-lsp/tests/lsp.rs +++ b/crates/sysmlv2-lsp/tests/lsp.rs @@ -66,9 +66,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{}: {error:?}", R::METHOD); return serde_json::from_value(result.unwrap_or_default()).unwrap(); } @@ -275,7 +278,7 @@ fn formatting_a_broken_document_warns_and_leaves_it_alone() { id.clone(), "textDocument/formatting".to_string(), DocumentFormattingParams { - text_document: TextDocumentIdentifier { uri: uri.clone() }, + text_document: TextDocumentIdentifier { uri }, options: FormattingOptions::default(), work_done_progress_params: Default::default(), }, @@ -289,9 +292,12 @@ fn formatting_a_broken_document_warns_and_leaves_it_alone() { } Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{error:?}"); break serde_json::from_value(result.unwrap_or_default()).unwrap(); } @@ -354,7 +360,7 @@ fn document_symbols_form_the_expected_tree() { ); let resp: Option = client.request::(DocumentSymbolParams { - text_document: TextDocumentIdentifier { uri: uri.clone() }, + text_document: TextDocumentIdentifier { uri }, work_done_progress_params: Default::default(), partial_result_params: Default::default(), }); @@ -484,9 +490,379 @@ fn unknown_request_gets_method_not_found() { loop { if let Message::Response(r) = client.conn.receiver.recv().unwrap() { assert_eq!(r.id, RequestId::from(99)); - assert!(r.error.is_some(), "signatureHelp is not implemented"); + assert!( + r.response_result.is_err(), + "signatureHelp is not implemented" + ); break; } } client.shutdown(); } + +/// A request whose parameters do not deserialize is answered with +/// `InvalidParams`, a malformed notification is logged and dropped, and +/// the session goes on serving either way. +#[test] +fn malformed_messages_are_answered_and_the_session_continues() { + let (mut client, _) = Client::start(false); + let uri = uri("m.sysml"); + client.open(&uri, 1, "package P { part def X; }\n"); + + // A uri that is a number, not a string. + client + .conn + .sender + .send(Message::Request(Request::new( + RequestId::from(42), + "textDocument/hover".to_string(), + serde_json::json!({"textDocument": {"uri": 5}, "position": {"line": 0, "character": 0}}), + ))) + .unwrap(); + let error = loop { + if let Message::Response(r) = client.conn.receiver.recv().unwrap() { + assert_eq!(r.id, RequestId::from(42)); + break r.response_result.expect_err("malformed params are refused"); + } + }; + assert_eq!(error.code, lsp_server::ErrorCode::InvalidParams as i32); + assert!( + error.message.starts_with("textDocument/hover: "), + "{error:?}" + ); + + // A didOpen without its text: logged, not fatal. + client + .conn + .sender + .send(Message::Notification(Notification::new( + "textDocument/didOpen".to_string(), + serde_json::json!({"textDocument": {"uri": "file:///harness/n.sysml"}}), + ))) + .unwrap(); + let logged = loop { + if let Message::Notification(n) = client.conn.receiver.recv().unwrap() { + if n.method == "window/logMessage" { + let p: lsp_types::LogMessageParams = serde_json::from_value(n.params).unwrap(); + break p; + } + } + }; + assert!( + logged.message.starts_with("textDocument/didOpen: "), + "{logged:?}" + ); + + // The session still answers. + use lsp_types::request::DocumentSymbolRequest; + let resp: Option = + client.request::(lsp_types::DocumentSymbolParams { + text_document: TextDocumentIdentifier { uri }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + assert!( + matches!(resp, Some(lsp_types::DocumentSymbolResponse::Nested(ref s)) if s.len() == 1), + "{resp:?}" + ); + client.shutdown(); +} + +#[test] +fn document_symbols_never_carry_an_empty_name() { + // `''` is a legal (empty) unrestricted name, distinct from an + // anonymous member. VS Code rejects a `DocumentSymbol` whose name is + // falsy and drops the whole response, so the outline must spell it. + use lsp_types::request::DocumentSymbolRequest; + use lsp_types::{DocumentSymbolParams, DocumentSymbolResponse}; + let (mut client, _) = Client::start(false); + let uri = uri("e.sysml"); + client.open( + &uri, + 1, + "package P {\n\ + \x20 enum def K {\n\ + \x20 '';\n\ + \x20 Key;\n\ + \x20 }\n\ + \x20 part def '' {\n\ + \x20 attribute <''> x;\n\ + \x20 attribute <''>;\n\ + \x20 }\n\ + }\n", + ); + let resp: Option = + client.request::(DocumentSymbolParams { + text_document: TextDocumentIdentifier { uri }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let Some(DocumentSymbolResponse::Nested(top)) = resp else { + panic!("expected a nested response: {resp:?}"); + }; + fn walk(symbols: &[lsp_types::DocumentSymbol], names: &mut Vec) { + for s in symbols { + assert!(!s.name.is_empty(), "empty symbol name at {:?}", s.range); + names.push(s.name.clone()); + if let Some(children) = &s.children { + walk(children, names); + } + } + } + let mut names = Vec::new(); + walk(&top, &mut names); + assert_eq!(names, ["P", "K", "''", "Key", "''", "x", "''"]); + + // The same spelling reaches workspace/symbol. + use lsp_types::request::WorkspaceSymbolRequest; + use lsp_types::{WorkspaceSymbolParams, WorkspaceSymbolResponse}; + let resp: Option = + client.request::(WorkspaceSymbolParams { + query: String::new(), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let Some(WorkspaceSymbolResponse::Flat(flat)) = resp else { + panic!("expected a flat response: {resp:?}"); + }; + assert!(flat.iter().all(|s| !s.name.is_empty())); + assert_eq!(flat.iter().filter(|s| s.name == "''").count(), 3); + client.shutdown(); +} + +#[test] +fn import_visibility_quick_fix_leads_with_the_computed_keyword() { + use lsp_types::request::CodeActionRequest; + use lsp_types::{CodeActionContext, CodeActionOrCommand, CodeActionParams, CodeActionResponse}; + let (mut client, _) = Client::start(false); + let lib = uri("lib.sysml"); + client.open(&lib, 1, "package Lib { part def Thing; }\n"); + let p = uri("p.sysml"); + let diags = client.open(&p, 1, "package P { import Lib::*; }\n"); + let q = uri("q.sysml"); + client.open(&q, 1, "package Q { part b : P::Thing; }\n"); + let visibility = diags + .diagnostics + .iter() + .find(|d| { + d.message + .starts_with("an import must declare an explicit visibility") + }) + .cloned() + .expect("the bare import is diagnosed"); + let resp: Option = client.request::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: p }, + range: visibility.range, + context: CodeActionContext { + diagnostics: vec![visibility], + only: None, + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let titles: Vec<(String, bool)> = resp + .unwrap_or_default() + .into_iter() + .filter_map(|a| match a { + CodeActionOrCommand::CodeAction(a) if a.title.starts_with("Make the import") => { + Some((a.title, a.is_preferred.unwrap_or(false))) + } + _ => None, + }) + .collect(); + // Q reaches Lib::Thing through P's import, so `public` is required + // and leads; the other keywords follow unpreferred. + assert_eq!(titles.len(), 3, "{titles:?}"); + assert_eq!( + titles[0], + ( + "Make the import `public` (1 reference(s) beyond the importing namespace resolve through it)".to_string(), + true + ) + ); + assert!( + titles[1..].iter().all(|(_, preferred)| !preferred), + "{titles:?}" + ); + + // Two bare imports in one file: the advice is for the one under the + // diagnostic. + let r = uri("r.sysml"); + let diags = client.open( + &r, + 1, + "package R {\n import Lib::*;\n import P::*;\n part a : Thing;\n}\n", + ); + let second = diags + .diagnostics + .iter() + .filter(|d| { + d.message + .starts_with("an import must declare an explicit visibility") + }) + .nth(1) + .cloned() + .expect("both bare imports are diagnosed"); + let resp: Option = client.request::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: r }, + range: second.range, + context: CodeActionContext { + diagnostics: vec![second], + only: None, + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let first_title = resp + .unwrap_or_default() + .into_iter() + .find_map(|a| match a { + CodeActionOrCommand::CodeAction(a) if a.title.starts_with("Make the import") => { + Some(a.title) + } + _ => None, + }) + .unwrap(); + // `import P::*` is only ever walked with full access. + assert_eq!( + first_title, + "Make the import `private` (nothing outside uses it)" + ); + client.shutdown(); +} + +/// Successive edits each replace the document's text outright. The +/// store shares a document's text with every snapshot taken of it — +/// jobs, requests — so an edit has to hand out a new one rather than +/// leave a reader on the old: diagnostics, the outline and formatting +/// all answer from the latest version. +#[test] +fn successive_edits_all_answer_from_the_latest_text() { + use lsp_types::request::DocumentSymbolRequest; + let (mut client, _) = Client::start(false); + let target = uri("m.sysml"); + let symbols = |client: &mut Client| -> Vec { + let resp: Option = client + .request::(lsp_types::DocumentSymbolParams { + text_document: TextDocumentIdentifier { + uri: uri("m.sysml"), + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + match resp { + Some(lsp_types::DocumentSymbolResponse::Nested(s)) => { + s.into_iter().map(|s| s.name).collect() + } + other => panic!("{other:?}"), + } + }; + client.open(&target, 1, "package First;\n"); + assert_eq!(symbols(&mut client), ["First"]); + + client.change(&target, 2, "package Second;\n"); + assert_eq!(symbols(&mut client), ["Second"]); + + // A version that does not parse, then one that does again. + let p = client.change(&target, 3, "package Third {\n"); + assert!(!p.diagnostics.is_empty(), "{:?}", p.diagnostics); + let p = client.change(&target, 4, "package Fourth;\n"); + assert_eq!(p.diagnostics, Vec::new(), "{:?}", p.diagnostics); + assert_eq!(symbols(&mut client), ["Fourth"]); + + // Formatting reads the same text: an already-formatted document + // has nothing to change. + let edits: Option> = + client.request::(lsp_types::DocumentFormattingParams { + text_document: TextDocumentIdentifier { uri: target }, + options: Default::default(), + work_done_progress_params: Default::default(), + }); + assert_eq!(edits, Some(Vec::new())); + client.shutdown(); +} + +/// The unit order every tier derives from the open documents is the +/// document order, and that is by uri — not the order the client +/// happened to open them in, and not a hash order that varies run to +/// run. Unit indexes, the resolver's tie-break on an ambiguous name and +/// the order of workspace symbols all ride on it. +#[test] +fn the_document_order_is_by_uri_whatever_order_they_arrive_in() { + use lsp_types::request::WorkspaceSymbolRequest; + use lsp_types::{WorkspaceSymbolParams, WorkspaceSymbolResponse}; + let names = |client: &mut Client| -> Vec { + let resp: Option = + client.request::(WorkspaceSymbolParams { + query: String::new(), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + match resp { + Some(WorkspaceSymbolResponse::Flat(flat)) => flat.into_iter().map(|s| s.name).collect(), + other => panic!("{other:?}"), + } + }; + let expected = ["Pa", "Pb", "Pc", "Pd", "Pe"]; + + let (mut client, _) = Client::start(false); + for (name, package) in [ + ("d.sysml", "Pd"), + ("a.sysml", "Pa"), + ("e.sysml", "Pe"), + ("c.sysml", "Pc"), + ("b.sysml", "Pb"), + ] { + client.open(&uri(name), 1, &format!("package {package};\n")); + } + assert_eq!(names(&mut client), expected); + client.shutdown(); + + // A second server, opened in the opposite order, answers the same. + let (mut client, _) = Client::start(false); + for (name, package) in [ + ("b.sysml", "Pb"), + ("c.sysml", "Pc"), + ("e.sysml", "Pe"), + ("a.sysml", "Pa"), + ("d.sysml", "Pd"), + ] { + client.open(&uri(name), 1, &format!("package {package};\n")); + } + assert_eq!(names(&mut client), expected); + client.shutdown(); +} + +/// The syntax tier parses on the server's own loop thread, and the +/// parser's bound only turns unbounded input into a diagnostic on a +/// stack that reaches the bound. A document nested to it is ordinary +/// input with nothing to report — a kilobyte and a half here — and on +/// the stack a thread gets when it asks for nothing, the descent ends +/// the whole process: no diagnostic, no unwind, no server, and an +/// editor session goes with it. +/// +/// The harness starts the server on exactly such a thread, so the loop's +/// own reservation is what carries this. A server whose reservation went +/// missing does not fail this test — it ends the test process. +#[test] +fn the_server_parses_at_the_nesting_bound() { + let (client, _) = Client::start(false); + let uri = uri("deep.sysml"); + // One level is the package, so the braces within it stop one short. + let levels = sysmlv2_parser::parser::MAX_NESTING as usize - 1; + let text = format!( + "package P {{ {}part x;{} }}\n", + "part x { ".repeat(levels), + "}".repeat(levels) + ); + let diags = client.open(&uri, 1, &text); + assert_eq!(diags.uri, uri); + assert!( + diags.diagnostics.is_empty(), + "nesting the parser accepts has nothing to report: {:?}", + diags.diagnostics + ); + client.shutdown(); +} diff --git a/crates/sysmlv2-lsp/tests/nav.rs b/crates/sysmlv2-lsp/tests/nav.rs index 391bc5f..fb4b20f 100644 --- a/crates/sysmlv2-lsp/tests/nav.rs +++ b/crates/sysmlv2-lsp/tests/nav.rs @@ -88,9 +88,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; if let Some(e) = error { return Err(e.message); } @@ -186,6 +189,44 @@ fn definition_crosses_files() { client.shutdown(); } +/// An `about` target naming a documentation or comment element jumps +/// to that element's declared name — by local name and by qualified +/// name, like any other member. +#[test] +fn definition_reaches_named_documentation() { + let mut client = Client::start(); + let doc = uri("doc.sysml"); + client.open( + &doc, + "package P {\n part def Vehicle {\n doc vehicleDoc /* A vehicle. */\n comment about vehicleDoc /* about the doc */\n }\n comment about Vehicle::vehicleDoc /* qualified */\n}\n", + ); + let mut definition = |line: u32, character: u32| -> Location { + let resp = client.request_ok::(GotoDefinitionParams { + text_document_position_params: Client::pos_params(&doc, line, character), + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let Some(GotoDefinitionResponse::Scalar(loc)) = resp else { + panic!("expected a definition at {line}:{character}: {resp:?}"); + }; + loc + }; + let declared = Position { + line: 2, + character: 12, + }; + // `vehicleDoc` in `comment about vehicleDoc` — line 3, col 22. + let loc = definition(3, 25); + assert_eq!(loc.uri, doc); + assert_eq!(loc.range.start, declared); + assert_eq!(loc.range.end.character, 22, "the `vehicleDoc` name token"); + // `vehicleDoc` in `comment about Vehicle::vehicleDoc` — line 5, col 27. + let loc = definition(5, 30); + assert_eq!(loc.uri, doc); + assert_eq!(loc.range.start, declared); + client.shutdown(); +} + #[test] fn references_span_the_workspace() { let (mut client, defs, uses) = workspace(); @@ -553,7 +594,8 @@ fn rename_shadow_capture_rejects() { /// qualified reference. #[test] fn definition_reaches_unopened_workspace_units() { - let dir = std::env::temp_dir().join("sysmlv2-lsp-nav-root-test"); + let dir = + std::env::temp_dir().join(format!("sysmlv2-lsp-nav-root-test-{}", std::process::id())); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); let defs = "package Defs {\n part def Wheel {\n attribute radius : Real;\n }\n part def Axle;\n}\n"; @@ -725,7 +767,10 @@ fn hover_inherits_metadata_vocabulary_docs() { /// surfaced with generated provenance stores hovering bare. #[test] fn hover_inherits_library_vocabulary_docs() { - let dir = std::env::temp_dir().join("sysmlv2-lsp-nav-libdocs-test"); + let dir = std::env::temp_dir().join(format!( + "sysmlv2-lsp-nav-libdocs-test-{}", + std::process::id() + )); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); std::fs::write( @@ -770,3 +815,50 @@ fn hover_inherits_library_vocabulary_docs() { ); client.shutdown(); } + +/// A standard-library directory that cannot be read leaves hover, +/// definition, references and rename with nothing to answer from. The +/// empty answers used to be all the client ever heard; the reason now +/// reaches it too, once, before the answer. +#[test] +fn an_unreadable_library_reaches_the_client() { + use lsp_types::request::Request as _; + let missing = std::env::temp_dir().join(format!( + "sysmlv2-lsp-no-such-library-{}", + std::process::id() + )); + let _ = std::fs::remove_dir_all(&missing); + let client = Client::start_with_library(missing); + let u = uri("defs.sysml"); + client.open(&u, DEFS); + + let id = RequestId::from(99); + client + .conn + .sender + .send(Message::Request(Request::new( + id.clone(), + HoverRequest::METHOD.to_string(), + HoverParams { + text_document_position_params: Client::pos_params(&u, 1, 14), + work_done_progress_params: Default::default(), + }, + ))) + .unwrap(); + let mut shown: Option = None; + loop { + match client.conn.receiver.recv().unwrap() { + Message::Notification(n) if n.method == "window/showMessage" => { + shown = Some(serde_json::from_value(n.params).unwrap()); + } + Message::Response(r) if r.id == id => break, + _ => continue, + } + } + let shown = shown.expect("the library failure reaches the client"); + assert!( + shown.message.contains("standard library could not be read"), + "{shown:?}" + ); + client.shutdown(); +} diff --git a/crates/sysmlv2-lsp/tests/outline_corpus.rs b/crates/sysmlv2-lsp/tests/outline_corpus.rs index 686e433..976b30b 100644 --- a/crates/sysmlv2-lsp/tests/outline_corpus.rs +++ b/crates/sysmlv2-lsp/tests/outline_corpus.rs @@ -5,7 +5,7 @@ //! here would render as a mysteriously incomplete Outline view. use lsp_types::DocumentSymbol; -use sysmlv2_lsp::{Encoding, Mapper, document_symbols}; +use sysmlv2_lsp::{Encoding, Mapper, document_symbols, spell_symbols}; use sysmlv2_parser::parser::{parse_kerml_source, parse_source}; fn check( @@ -55,7 +55,8 @@ fn corpus_outlines_satisfy_containment() { parse_source(&src) }; let mapper = Mapper::new(&src, Encoding::Utf16); - let tree = document_symbols(&parse.unit, &src, &mapper); + let mut tree = document_symbols(&parse.unit, &src, &mapper); + spell_symbols(&mut tree); check(&tree, None, &path.display().to_string(), &mut symbols); files += 1; } diff --git a/crates/sysmlv2-lsp/tests/refactor.rs b/crates/sysmlv2-lsp/tests/refactor.rs index 13c7ecf..74b515c 100644 --- a/crates/sysmlv2-lsp/tests/refactor.rs +++ b/crates/sysmlv2-lsp/tests/refactor.rs @@ -57,9 +57,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{error:?}"); return serde_json::from_value(result.unwrap_or_default()).unwrap(); } diff --git a/crates/sysmlv2-lsp/tests/unit_typing.rs b/crates/sysmlv2-lsp/tests/unit_typing.rs index 5b1f355..452e4a8 100644 --- a/crates/sysmlv2-lsp/tests/unit_typing.rs +++ b/crates/sysmlv2-lsp/tests/unit_typing.rs @@ -57,9 +57,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{error:?}"); return serde_json::from_value(result.unwrap_or_default()).unwrap(); } @@ -68,7 +71,7 @@ impl Client { } } - fn notify(&mut self, params: N::Params) { + fn notify(&self, params: N::Params) { self.conn .sender .send(Message::Notification(Notification::new( @@ -78,7 +81,7 @@ impl Client { .unwrap(); } - fn open(&mut self, uri: &Uri, text: &str) { + fn open(&self, uri: &Uri, text: &str) { self.notify::(DidOpenTextDocumentParams { text_document: TextDocumentItem { uri: uri.clone(), @@ -170,18 +173,14 @@ fn compound_spelled_units_type_through_their_alias() { "package G {\n private import ISQ::*;\n private import SI::*;\n attribute gravity = 9.8 [m/s\n}\n", ); let items = complete(&mut client, &u, 3, 32); - let accel: Vec<_> = items - .iter() - .filter(|i| { - i.additional_text_edits - .iter() - .flatten() - .any(|e| e.new_text == " : AccelerationValue") - }) - .map(|i| i.label.clone()) - .collect(); + let mut accel = items.iter().filter(|i| { + i.additional_text_edits + .iter() + .flatten() + .any(|e| e.new_text == " : AccelerationValue") + }); assert!( - !accel.is_empty(), + accel.next().is_some(), "expected an acceleration-unit item carrying the typing edit" ); client.shutdown(); diff --git a/crates/sysmlv2-lsp/tests/workspace.rs b/crates/sysmlv2-lsp/tests/workspace.rs index f9b8fd8..ff62b6a 100644 --- a/crates/sysmlv2-lsp/tests/workspace.rs +++ b/crates/sysmlv2-lsp/tests/workspace.rs @@ -8,8 +8,8 @@ use lsp_server::{Connection, Message, Notification, Request, RequestId, Response use lsp_types::notification::{DidChangeTextDocument, DidOpenTextDocument, Exit, Initialized}; use lsp_types::request::{CodeActionRequest, Initialize, Shutdown}; use lsp_types::{ - CodeActionContext, CodeActionKind, CodeActionOrCommand, CodeActionParams, DiagnosticTag, - DidChangeTextDocumentParams, DidOpenTextDocumentParams, InitializeParams, + CodeActionContext, CodeActionKind, CodeActionOrCommand, CodeActionParams, DiagnosticSeverity, + DiagnosticTag, DidChangeTextDocumentParams, DidOpenTextDocumentParams, InitializeParams, PublishDiagnosticsParams, Range, TextDocumentContentChangeEvent, TextDocumentIdentifier, TextDocumentItem, Uri, VersionedTextDocumentIdentifier, }; @@ -27,11 +27,41 @@ fn uri(name: &str) -> Uri { Uri::from_str(&format!("file:///w/{name}")).unwrap() } +/// A `file://` uri for a real path, percent-encoding every byte a uri +/// path may not carry — the spelling the client and the server's +/// workspace walk have to agree on. +fn file_uri(path: &std::path::Path) -> Uri { + use std::fmt::Write as _; + let mut out = String::from("file://"); + for b in path.display().to_string().bytes() { + match b { + b'A'..=b'Z' | b'a'..=b'z' | b'0'..=b'9' => out.push(b as char), + b'-' | b'.' | b'_' | b'~' | b'/' | b':' | b'@' => out.push(b as char), + b'!' | b'$' | b'&' | b'\'' | b'(' | b')' | b'*' | b'+' | b',' | b';' | b'=' => { + out.push(b as char); + } + b => { + let _ = write!(out, "%{b:02X}"); + } + } + } + Uri::from_str(&out).unwrap() +} + impl Client { fn start(root: Option<&std::path::Path>) -> Client { + Self::start_with_library(root, None) + } + + /// [`Self::start`] with a standard-library directory for the + /// workspace tier's referential and semantic checks. + fn start_with_library( + root: Option<&std::path::Path>, + library: Option, + ) -> Client { let (server_side, client_side) = Connection::memory(); let server = std::thread::spawn(move || { - sysmlv2_lsp::run_with_options(server_side, None, Duration::from_millis(50)) + sysmlv2_lsp::run_with_options(server_side, library, Duration::from_millis(50)) }); let mut c = Client { conn: client_side, @@ -69,9 +99,12 @@ impl Client { match self.conn.receiver.recv().unwrap() { Message::Response(Response { id: rid, - result, - error, + response_result, }) if rid == id => { + let (result, error) = match response_result { + Ok(v) => (Some(v), None), + Err(e) => (None, Some(e)), + }; assert!(error.is_none(), "{error:?}"); return serde_json::from_value(result.unwrap_or_default()).unwrap(); } @@ -80,6 +113,36 @@ impl Client { } } + /// A request by method name (the server's custom methods), answered + /// as the raw result or the error the server sent. + fn request_raw( + &mut self, + method: &str, + params: serde_json::Value, + ) -> Result { + self.next_id += 1; + let id = RequestId::from(self.next_id); + self.conn + .sender + .send(Message::Request(Request::new( + id.clone(), + method.to_string(), + params, + ))) + .unwrap(); + loop { + match self.conn.receiver.recv().unwrap() { + Message::Response(Response { + id: rid, + response_result, + }) if rid == id => { + return response_result; + } + _ => continue, + } + } + } + fn notify(&self, params: N::Params) { self.conn .sender @@ -217,6 +280,103 @@ fn worker_reports_unused_import_and_quickfix_removes_it() { c.shutdown(); } +/// Several findings in one unit, and findings in several units, each +/// land on their own line: the line index a cycle builds once per unit +/// serves every finding of that unit. +#[test] +fn worker_maps_every_finding_of_a_unit_and_of_every_unit() { + let client = Client::start(None); + let defs = uri("defs.sysml"); + let a = uri("a.sysml"); + let b = uri("b.sysml"); + client.open( + &defs, + "package D1 { part def Wheel; }\npackage D2 { part def Axle; }\npackage D3 { part def Cog; }\n", + ); + client.open( + &a, + "package A {\n private import D1::Wheel;\n private import D2::Axle;\n part def P;\n}\n", + ); + client.open( + &b, + "package B {\n part def Q;\n private import D3::Cog;\n}\n", + ); + let unused = |p: &PublishDiagnosticsParams| -> Vec<(u32, u32, u32)> { + p.diagnostics + .iter() + .filter(|d| d.message == "unused private import") + .map(|d| { + ( + d.range.start.line, + d.range.start.character, + d.range.end.line, + ) + }) + .collect() + }; + // One cycle publishes both units in no particular order: take the + // first publish of each that carries its warnings. + let mut got: std::collections::HashMap = + std::collections::HashMap::new(); + let deadline = std::time::Instant::now() + Duration::from_secs(10); + while got.len() < 2 { + let msg = client + .conn + .receiver + .recv_timeout(deadline - std::time::Instant::now()) + .expect("timed out waiting for the publishes"); + if let Message::Notification(n) = msg { + if n.method == "textDocument/publishDiagnostics" { + let p: PublishDiagnosticsParams = serde_json::from_value(n.params).unwrap(); + if (p.uri == a || p.uri == b) && !unused(&p).is_empty() { + got.entry(p.uri.clone()).or_insert(p); + } + } + } + } + assert_eq!(unused(&got[&a]), [(1, 4, 1), (2, 4, 2)]); + assert_eq!(unused(&got[&b]), [(2, 4, 2)]); + client.shutdown(); +} + +/// A model file whose name is not plain ASCII, and carries a character +/// a uri gives its own meaning, is published like any other: its uri +/// has to be one the client can parse, or that file's findings never +/// leave the server. Opening it then replaces the unit the walk found +/// rather than joining the model a second time. +#[test] +fn a_non_ascii_workspace_path_publishes_and_overlays_when_opened() { + let dir = std::env::temp_dir().join(format!("sysmlv2-lsp-ws-uri-test-{}", std::process::id())); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + // Han characters: no canonical decomposition, so the name on disk + // reads back byte for byte on every filesystem. + let path = dir.join("日本語 #1.sysml"); + std::fs::write(&path, "package P { part def Wheel;\n").unwrap(); + + let client = Client::start(Some(&dir)); + // Any open document triggers a workspace cycle. + client.open(&uri("probe.sysml"), "package OK;\n"); + + let target = file_uri(&path); + let p = client.await_publish(&target, |p| !p.diagnostics.is_empty()); + assert!( + p.diagnostics.iter().any(|d| d.message.contains("expected")), + "{:?}", + p.diagnostics + ); + assert_eq!(p.version, None, "closed files publish without a version"); + + // Opening it with the error fixed clears the file's findings: the + // open text replaced the unit on disk. A second unit under the same + // path would keep publishing the broken text's findings, and would + // declare `P` twice besides. + client.open(&target, "package P { part def Wheel; }\n"); + let p = client.await_publish(&target, |p| p.version == Some(1)); + assert_eq!(p.diagnostics, Vec::new(), "{:?}", p.diagnostics); + client.shutdown(); +} + fn client_await_clear(c: &Client, target: &Uri) -> PublishDiagnosticsParams { c.await_publish(target, |p| { p.version == Some(2) @@ -232,7 +392,7 @@ fn worker_publishes_scoped_lint_findings_from_sysmlint_json() { // rule findings carry the rule id as the diagnostic code (dead- // model rules tagged UNNECESSARY), and configuration complaints // anchor on the config file itself. - let dir = std::env::temp_dir().join("sysmlv2-lsp-lint-test"); + let dir = std::env::temp_dir().join(format!("sysmlv2-lsp-lint-test-{}", std::process::id())); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); std::fs::write( @@ -309,7 +469,7 @@ fn worker_publishes_scoped_lint_findings_from_sysmlint_json() { fn workspace_root_files_get_diagnostics_without_being_open() { // A broken file on disk under the workspace root: the worker reads // it and publishes its parse error even though it was never opened. - let dir = std::env::temp_dir().join("sysmlv2-lsp-ws-test"); + let dir = std::env::temp_dir().join(format!("sysmlv2-lsp-ws-test-{}", std::process::id())); let _ = std::fs::remove_dir_all(&dir); std::fs::create_dir_all(&dir).unwrap(); std::fs::write(dir.join("broken.sysml"), "part def P {\n").unwrap(); @@ -337,6 +497,52 @@ fn workspace_root_files_get_diagnostics_without_being_open() { client.shutdown(); } +#[test] +fn worker_reports_user_roots_shadowing_library_roots() { + // A library directory with one standard root package; a user + // document declaring a root package of the same name gets the + // referential warning at the declaration's name, severity warning. + let lib = std::env::temp_dir().join(format!( + "sysmlv2-lsp-shadow-lib-test-{}", + std::process::id() + )); + let _ = std::fs::remove_dir_all(&lib); + std::fs::create_dir_all(&lib).unwrap(); + std::fs::write( + lib.join("Requirements.sysml"), + "standard library package Requirements { requirement def Base; }\n", + ) + .unwrap(); + + let client = Client::start_with_library(None, Some(lib)); + let u = uri("shadow.sysml"); + client.open( + &u, + "package Requirements {\n requirement def Speed;\n}\n", + ); + let p = client.await_publish(&u, |p| { + p.diagnostics + .iter() + .any(|d| d.message.starts_with("root package")) + }); + let diag = p + .diagnostics + .iter() + .find(|d| d.message.starts_with("root package")) + .unwrap(); + assert_eq!( + diag.message, + "root package `Requirements` shadows the standard library package `Requirements`; \ + references resolve to the library" + ); + assert_eq!(diag.severity, Some(DiagnosticSeverity::WARNING)); + assert_eq!(diag.source.as_deref(), Some("sysmlv2")); + assert_eq!(diag.range.start, lsp_types::Position::new(0, 8)); + assert_eq!(diag.range.end, lsp_types::Position::new(0, 20)); + assert_eq!(p.version, Some(1)); + client.shutdown(); +} + #[test] fn visibility_quickfix_rides_the_m11a_finding() { let mut client = Client::start(None); @@ -377,12 +583,14 @@ fn visibility_quickfix_rides_the_m11a_finding() { _ => None, }) .collect(); + // Nothing resolves through the import, so `private` is computed + // and leads; the other keywords follow as plain alternatives. assert_eq!( titles, [ - "Make the import private", - "Make the import public", - "Make the import protected" + "Make the import `private` (nothing outside uses it)", + "Make the import `public`", + "Make the import `protected`" ], "{titles:?}" ); @@ -486,6 +694,99 @@ fn apply_edits(text: &str, edits: &[lsp_types::TextEdit]) -> String { out } +/// Beside a finding's own quick fix: the rule's every finding at once, +/// in this document and — where other documents hold more — across the +/// workspace, each labeled for the rewrite it is and offered once per +/// rule however many of its findings the request carries. +#[test] +fn rule_wide_fix_all_rides_the_quick_fix() { + let mut client = Client::start(None); + let a = uri("kinds-a.sysml"); + let b = uri("kinds-b.sysml"); + client.open( + &a, + "package A {\n port def Pd;\n part def X { attribute p : Pd; attribute q : Pd; }\n}\n", + ); + client.open( + &b, + "package B {\n part def Y { attribute r : A::Pd; }\n}\n", + ); + let kind = |d: &lsp_types::Diagnostic| { + d.code + == Some(lsp_types::NumberOrString::String( + "usage-kind-mismatch".into(), + )) + }; + let p = client.await_publish(&a, |p| { + p.diagnostics.iter().filter(|d| kind(d)).count() >= 2 + }); + let lint: Vec<_> = p.diagnostics.iter().filter(|d| kind(d)).cloned().collect(); + let request = |client: &mut Client, + diags: Vec| + -> Vec { + client + .request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: a.clone() }, + range: diags[0].range, + context: CodeActionContext { + diagnostics: diags, + only: None, + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }) + .unwrap_or_default() + .into_iter() + .filter_map(|a| match a { + CodeActionOrCommand::CodeAction(c) if c.kind == Some(CodeActionKind::QUICKFIX) => { + Some(c) + } + _ => None, + }) + .collect() + }; + let actions = request(&mut client, vec![lint[0].clone()]); + let titles: Vec<&str> = actions.iter().map(|c| c.title.as_str()).collect(); + assert_eq!( + titles, + [ + "change `attribute` to `port` (rewrites the declaration)", + "Fix all 2 `usage-kind-mismatch` findings in this file (rewrites the declarations)", + "Fix all 3 `usage-kind-mismatch` findings across 2 files (rewrites the declarations)", + ] + ); + let changes = |c: &lsp_types::CodeAction| c.edit.clone().unwrap().changes.unwrap(); + let in_file = changes(&actions[1]); + assert_eq!(in_file.len(), 1); + assert_eq!( + apply_edits( + "package A {\n port def Pd;\n part def X { attribute p : Pd; attribute q : Pd; }\n}\n", + &in_file[&a] + ), + "package A {\n port def Pd;\n part def X { port p : Pd; port q : Pd; }\n}\n" + ); + let everywhere = changes(&actions[2]); + assert_eq!(everywhere.len(), 2); + assert_eq!(everywhere[&a], in_file[&a]); + assert_eq!( + apply_edits( + "package B {\n part def Y { attribute r : A::Pd; }\n}\n", + &everywhere[&b] + ), + "package B {\n part def Y { port r : A::Pd; }\n}\n" + ); + // Both of this document's findings in the request: two single fixes, + // the rule-wide pair once. + let actions = request(&mut client, lint); + let wide = actions + .iter() + .filter(|c| c.title.starts_with("Fix all")) + .count(); + assert_eq!((actions.len(), wide), (4, 2), "{actions:#?}"); + client.shutdown(); +} + /// "Optimize imports" removes exactly the unused imports, keeps the /// used ones in their original order, and leaves no blank lines. #[test] @@ -717,3 +1018,494 @@ fn sort_imports_alphabetizes_contiguous_runs() { ); client.shutdown(); } + +#[test] +fn lint_fixes_ride_quick_fixes_and_fix_all() { + // Two lint findings with fixes: a bare import (safe fix: declare + // `private`) and an attribute typed by a port definition (semantic + // fix: rewrite the keyword). Quick fixes offer both, labeled; fix-all + // applies only the safe one. + let mut client = Client::start(None); + let m = uri("fixes.sysml"); + client.open( + &m, + "package P {\n import Lib::*;\n port def Pd;\n part def A { attribute p : Pd; }\n}\npackage Lib { part def Thing; }\n", + ); + let p = client.await_publish(&m, |p| { + p.diagnostics + .iter() + .filter(|d| d.source.as_deref() == Some("sysmlv2 lint")) + .count() + >= 2 + }); + let lint: Vec<_> = p + .diagnostics + .iter() + .filter(|d| d.source.as_deref() == Some("sysmlv2 lint")) + .cloned() + .collect(); + let actions: Option> = + client.request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: m.clone() }, + range: lint[0].range, + context: CodeActionContext { + diagnostics: lint.clone(), + only: None, + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let titles: Vec = actions + .unwrap_or_default() + .into_iter() + .filter_map(|a| match a { + CodeActionOrCommand::CodeAction(c) if c.kind == Some(CodeActionKind::QUICKFIX) => { + Some(c.title) + } + _ => None, + }) + .collect(); + assert!( + titles.iter().any(|t| t == "Make the import `private`"), + "{titles:?}" + ); + assert!( + titles + .iter() + .any(|t| t == "change `attribute` to `port` (rewrites the declaration)"), + "{titles:?}" + ); + // With the syntax tier's own visibility diagnostic in the request, + // its quick fix stands and the lint twin steps aside. + let import_diag = lint + .iter() + .find(|d| { + d.code + == Some(lsp_types::NumberOrString::String( + "import-visibility".into(), + )) + }) + .expect("the bare import's lint finding"); + let syntax = lsp_types::Diagnostic { + range: import_diag.range, + severity: Some(DiagnosticSeverity::ERROR), + source: Some("sysmlv2".to_string()), + message: + "an import must declare an explicit visibility (`public`, `private`, or `protected`)" + .to_string(), + ..Default::default() + }; + let actions: Option> = + client.request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: m.clone() }, + range: import_diag.range, + context: CodeActionContext { + diagnostics: vec![syntax, import_diag.clone()], + only: None, + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let titles: Vec = actions + .unwrap_or_default() + .into_iter() + .filter_map(|a| match a { + CodeActionOrCommand::CodeAction(c) => Some(c.title), + _ => None, + }) + .collect(); + assert!( + titles + .iter() + .any(|t| t.starts_with("Make the import `private`")), + "{titles:?}" + ); + assert!( + !titles.iter().any(|t| t == "Make the import `private`"), + "{titles:?}" + ); + let actions: Option> = + client.request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: m.clone() }, + range: Range::default(), + context: CodeActionContext { + diagnostics: Vec::new(), + only: Some(vec![CodeActionKind::SOURCE_FIX_ALL]), + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let fix_all = actions + .unwrap_or_default() + .into_iter() + .find_map(|a| match a { + CodeActionOrCommand::CodeAction(c) + if c.kind == Some(CodeActionKind::SOURCE_FIX_ALL) => + { + Some(c) + } + _ => None, + }) + .expect("a fix-all action"); + assert_eq!(fix_all.title, "Fix all auto-fixable lint findings (1)"); + let edits = &fix_all.edit.unwrap().changes.unwrap()[&m]; + assert_eq!(edits.len(), 1); + assert_eq!(edits[0].new_text, "private "); + client.shutdown(); +} + +#[test] +fn split_action_creates_annotated_files_from_a_package_declaration() { + let mut client = Client::start(None); + let r = uri("r.sysml"); + client.open( + &r, + "package Lib { part def Thing; }\npackage R {\n private import Lib::*;\n package A { part def X; part t : Thing; }\n package B { part def Y :> A::X; }\n part r : A::X;\n}\n", + ); + // The cursor on `R` in `package R {` (line 1, character 8). + let at = lsp_types::Position { + line: 1, + character: 8, + }; + let actions: Option> = + client.request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: r.clone() }, + range: Range { start: at, end: at }, + context: CodeActionContext { + diagnostics: Vec::new(), + only: Some(vec![CodeActionKind::new("refactor.move")]), + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + let actions: Vec = actions + .unwrap_or_default() + .into_iter() + .filter_map(|a| match a { + CodeActionOrCommand::CodeAction(c) => Some(c), + _ => None, + }) + .collect(); + assert_eq!(actions.len(), 1, "{actions:?}"); + assert_eq!(actions[0].title, "Split 'R' into 2 files under r/"); + let edit = actions[0].edit.clone().expect("workspace edit"); + let Some(lsp_types::DocumentChanges::Operations(ops)) = edit.document_changes else { + panic!("expected document operations: {edit:?}"); + }; + let creates: Vec = ops + .iter() + .filter_map(|op| match op { + lsp_types::DocumentChangeOperation::Op(lsp_types::ResourceOp::Create(c)) => { + Some(c.uri.to_string()) + } + _ => None, + }) + .collect(); + assert_eq!(creates, ["file:///w/r/A.sysml", "file:///w/r/B.sysml"]); + let edits: Vec<(String, String)> = ops + .iter() + .filter_map(|op| match op { + lsp_types::DocumentChangeOperation::Edit(e) => Some(( + e.text_document.uri.to_string(), + e.edits + .iter() + .map(|x| match x { + lsp_types::OneOf::Left(t) => t.new_text.clone(), + lsp_types::OneOf::Right(a) => a.text_edit.new_text.clone(), + }) + .collect::>() + .join("|"), + )), + _ => None, + }) + .collect(); + assert_eq!(edits.len(), 3, "{edits:?}"); + assert!(edits[0].1.starts_with("package A {"), "{:?}", edits[0]); + assert!( + edits[0].1.contains("part t : Lib::Thing;"), + "{:?}", + edits[0] + ); + assert!(edits[1].1.starts_with("package B {"), "{:?}", edits[1]); + assert_eq!(edits[2].0, "file:///w/r.sysml"); + assert!(edits[2].1.contains("public import A;"), "{:?}", edits[2]); + // Annotated for a client's preview, not flagged for confirmation: + // editors read that flag as opt-in per change and would open the + // preview with every change unticked. + let annotations = edit.change_annotations.expect("annotated"); + assert_eq!(annotations["split"].needs_confirmation, None); + assert_eq!(annotations["split"].label, "Split into 2 new file(s)"); + // A package with nothing nested offers no action. + let at = lsp_types::Position { + line: 0, + character: 8, + }; + let none: Option> = + client.request_ok::(CodeActionParams { + text_document: TextDocumentIdentifier { uri: r }, + range: Range { start: at, end: at }, + context: CodeActionContext { + diagnostics: Vec::new(), + only: Some(vec![CodeActionKind::new("refactor.move")]), + trigger_kind: None, + }, + work_done_progress_params: Default::default(), + partial_result_params: Default::default(), + }); + assert!(none.unwrap_or_default().is_empty()); + client.shutdown(); +} + +#[test] +fn split_requests_plan_and_edit_a_package_by_position_or_name() { + let mut client = Client::start(None); + let r = uri("r.sysml"); + let text = "package Lib { part def Thing; }\npackage B { part def Elsewhere; }\npackage R {\n private import Lib::*;\n package A { part def X; part t : Thing; package Deep { part def D; } }\n package B { part def Y :> A::X; }\n package '02 JPL' { part def Z; }\n part r : A::X;\n}\n"; + client.open(&r, text); + // The plan alone, from the cursor on `R`: one unit per nested + // package, file segments spelled as the editor spells a created + // file's uri, a root-level collision renamed, no edit computed. + let plan = client + .request_raw( + sysmlv2_lsp::SPLIT_PLAN_METHOD, + serde_json::json!({ + "textDocument": { "uri": r.as_str() }, + "position": { "line": 2, "character": 8 }, + }), + ) + .expect("a plan"); + assert_eq!(plan["root"]["qualifiedName"], "R"); + assert_eq!(plan["root"]["uri"], r.as_str()); + assert_eq!(plan["directory"], "file:///w/r"); + assert!(plan.get("edit").is_none(), "{plan}"); + let entries = plan["entries"].as_array().expect("entries"); + let uris: Vec<&str> = entries.iter().map(|e| e["uri"].as_str().unwrap()).collect(); + assert_eq!( + uris, + [ + "file:///w/r/A.sysml", + "file:///w/r/R%20B.sysml", + "file:///w/r/02%20JPL.sysml" + ] + ); + let nested: Vec = entries + .iter() + .map(|e| e["nested"].as_u64().unwrap()) + .collect(); + assert_eq!(nested, [1, 0, 0]); + assert_eq!(entries[1]["name"], "B"); + assert_eq!(entries[1]["newName"], "R B"); + assert_eq!(entries[1]["rootName"], "'R B'"); + assert_eq!(entries[2]["qualifiedName"], "R::'02 JPL'"); + assert_eq!(entries[2]["rootName"], "'02 JPL'"); + assert!(entries[2]["newName"].is_null()); + assert!(entries[0]["bytes"].as_u64().unwrap() > entries[2]["bytes"].as_u64().unwrap()); + // The edit, by package name without a document, under a chosen + // directory and slugged names. + let split = client + .request_raw( + sysmlv2_lsp::SPLIT_METHOD, + serde_json::json!({ "package": "R", "naming": "slug", "directory": "file:///w/out" }), + ) + .expect("a split"); + assert_eq!(split["directory"], "file:///w/out"); + let (creates, _) = split_ops(&split["edit"]); + assert_eq!( + creates, + [ + "file:///w/out/A.sysml", + "file:///w/out/R-B.sysml", + "file:///w/out/02-JPL.sysml" + ] + ); + // The edit with the names kept: percent-encoded uris spell, the + // root re-exports each moved package (an alias for the renamed + // one), and the created texts stand alone. + let split = client + .request_raw( + sysmlv2_lsp::SPLIT_METHOD, + serde_json::json!({ "textDocument": { "uri": r.as_str() }, "position": { "line": 2, "character": 8 } }), + ) + .expect("a split"); + let edit: lsp_types::WorkspaceEdit = serde_json::from_value(split["edit"].clone()).unwrap(); + assert_eq!( + edit.change_annotations.as_ref().expect("annotated")["split"].needs_confirmation, + None + ); + let (creates, texts) = split_ops(&split["edit"]); + assert_eq!(creates, uris); + let root_text = apply_edits(text, &texts[r.as_str()]); + assert!(root_text.contains("public import A;"), "{root_text}"); + assert!( + root_text.contains("public alias B for 'R B';"), + "{root_text}" + ); + assert!(root_text.contains("public import '02 JPL';"), "{root_text}"); + assert!(!root_text.contains("package A"), "{root_text}"); + let a_text = apply_edits("", &texts["file:///w/r/A.sysml"]); + assert!(a_text.starts_with("package A {"), "{a_text}"); + assert!(a_text.contains("part t : Lib::Thing;"), "{a_text}"); + let b_text = apply_edits("", &texts["file:///w/r/R%20B.sysml"]); + assert!(b_text.starts_with("package 'R B' {"), "{b_text}"); + assert!(b_text.contains("part def Y :> R::A::X;"), "{b_text}"); + // A deeper level: with the level applied (the root changed, the + // new units open), the hoisted packages are reachable by the names + // they took — the renamed one by its quoted name (a leaf, refused + // as such), `A` with its nested package under its own directory. + client.notify::(DidChangeTextDocumentParams { + text_document: lsp_types::VersionedTextDocumentIdentifier { + uri: r.clone(), + version: 2, + }, + content_changes: vec![lsp_types::TextDocumentContentChangeEvent { + range: None, + range_length: None, + text: root_text, + }], + }); + client.open(&Uri::from_str("file:///w/r/A.sysml").unwrap(), &a_text); + client.open(&Uri::from_str("file:///w/r/R%20B.sysml").unwrap(), &b_text); + let err = client + .request_raw( + sysmlv2_lsp::SPLIT_PLAN_METHOD, + serde_json::json!({ "package": "'R B'" }), + ) + .expect_err("a leaf"); + assert_eq!(err.code, lsp_server::ErrorCode::RequestFailed as i32); + assert!( + err.message.contains("owns no nested package"), + "{}", + err.message + ); + // A name takes precedence over a document and position beside it + // (the wizard's deeper-level shape). + let deeper = client + .request_raw( + sysmlv2_lsp::SPLIT_PLAN_METHOD, + serde_json::json!({ "textDocument": { "uri": r.as_str() }, "position": { "line": 0, "character": 8 }, "package": "A" }), + ) + .expect("a deeper plan"); + assert_eq!(deeper["root"]["uri"], "file:///w/r/A.sysml"); + assert_eq!(deeper["directory"], "file:///w/r/A"); + assert_eq!(deeper["entries"][0]["uri"], "file:///w/r/A/Deep.sysml"); + // Refusals carry their reason: not a package; a position in a + // document that is not open; neither a package nor a position. + let err = client + .request_raw( + sysmlv2_lsp::SPLIT_METHOD, + serde_json::json!({ "package": "Lib::Thing" }), + ) + .expect_err("not a package"); + assert_eq!(err.code, lsp_server::ErrorCode::RequestFailed as i32); + assert!(err.message.contains("is not a package"), "{}", err.message); + let err = client + .request_raw( + sysmlv2_lsp::SPLIT_PLAN_METHOD, + serde_json::json!({ "textDocument": { "uri": "file:///w/closed.sysml" }, "position": { "line": 0, "character": 0 } }), + ) + .expect_err("not open"); + assert_eq!(err.code, lsp_server::ErrorCode::InvalidParams as i32); + let err = client + .request_raw(sysmlv2_lsp::SPLIT_METHOD, serde_json::json!({})) + .expect_err("no target"); + assert_eq!(err.code, lsp_server::ErrorCode::InvalidParams as i32); + client.shutdown(); +} + +/// A split edit's created uris and, per document, its text edits. +fn split_ops( + edit: &serde_json::Value, +) -> ( + Vec, + std::collections::HashMap>, +) { + let edit: lsp_types::WorkspaceEdit = serde_json::from_value(edit.clone()).unwrap(); + let Some(lsp_types::DocumentChanges::Operations(ops)) = edit.document_changes else { + panic!("expected document operations"); + }; + let mut creates = Vec::new(); + let mut texts = std::collections::HashMap::new(); + for op in ops { + match op { + lsp_types::DocumentChangeOperation::Op(lsp_types::ResourceOp::Create(c)) => { + creates.push(c.uri.to_string()); + } + lsp_types::DocumentChangeOperation::Edit(e) => { + let edits = e + .edits + .into_iter() + .map(|x| match x { + lsp_types::OneOf::Left(t) => t, + lsp_types::OneOf::Right(a) => a.text_edit, + }) + .collect(); + texts.insert(e.text_document.uri.to_string(), edits); + } + _ => {} + } + } + (creates, texts) +} + +/// The workspace's lint configuration drives formatting style as well +/// as the lint, and both are asked for it on every keystroke-driven +/// request. It is read from disk once and re-read when the file +/// changes — a stale answer here would leave the editor formatting to +/// a policy the project no longer has. +#[test] +fn formatting_follows_the_lint_configuration_as_it_changes() { + use lsp_types::request::Formatting; + let dir = std::env::temp_dir().join(format!( + "sysmlv2-lsp-config-cache-test-{}", + std::process::id() + )); + let _ = std::fs::remove_dir_all(&dir); + std::fs::create_dir_all(&dir).unwrap(); + let config = dir.join("sysmlint.json"); + // `min: 0` keeps a logical chain on one line. + std::fs::write( + &config, + r#"{ "rules": { "multiline-conditions": { "min": 0 } } }"#, + ) + .unwrap(); + + let mut client = Client::start(Some(&dir)); + let m = uri("m.sysml"); + client.open( + &m, + "package P {\n constraint def C {\n a and b and c and d\n }\n}\n", + ); + let format = |client: &mut Client| -> Vec { + client + .request_ok::(lsp_types::DocumentFormattingParams { + text_document: TextDocumentIdentifier { + uri: uri("m.sysml"), + }, + options: Default::default(), + work_done_progress_params: Default::default(), + }) + .unwrap_or_default() + }; + assert_eq!(format(&mut client), Vec::new(), "the chain stays inline"); + + // A project that wants chains of two or more broken out. The new + // text is a different length, so the change is visible however + // coarse the clock is. + std::fs::write( + &config, + r#"{ "rules": { "multiline-conditions": { "min": 2, "severity": "warn" } } }"#, + ) + .unwrap(); + let edits = format(&mut client); + assert_eq!(edits.len(), 1, "{edits:?}"); + assert!( + edits[0].new_text.contains("and b\n"), + "one operand per line: {:?}", + edits[0].new_text + ); + client.shutdown(); +} diff --git a/crates/sysmlv2-model/Cargo.toml b/crates/sysmlv2-model/Cargo.toml index 428d21d..39de2ee 100644 --- a/crates/sysmlv2-model/Cargo.toml +++ b/crates/sysmlv2-model/Cargo.toml @@ -12,7 +12,11 @@ repository.workspace = true include = ["src/**", "build.rs", "Cargo.toml"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -serde.workspace = true +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0", features = ["serde"] } +serde = { workspace = true, features = ["rc"] } serde_json.workspace = true -uuid.workspace = true +uuid = { workspace = true, features = ["serde"] } +num-bigint.workspace = true +num-integer.workspace = true +num-rational.workspace = true +num-traits.workspace = true diff --git a/crates/sysmlv2-model/build.rs b/crates/sysmlv2-model/build.rs index 8779f89..1aceb30 100644 --- a/crates/sysmlv2-model/build.rs +++ b/crates/sysmlv2-model/build.rs @@ -10,7 +10,7 @@ //! cannot tell two working-tree states apart, and a resolution or //! evaluation change that leaves the pending-reference queue unchanged //! slips past the sequence fingerprint — observed as a cached library -//! export silently serving pre-change evaluated values (2026-08-05). +//! export silently serving pre-change evaluated values. use std::path::{Path, PathBuf}; diff --git a/crates/sysmlv2-model/src/ambient.rs b/crates/sysmlv2-model/src/ambient.rs index a8ab331..b64f912 100644 --- a/crates/sysmlv2-model/src/ambient.rs +++ b/crates/sysmlv2-model/src/ambient.rs @@ -49,11 +49,13 @@ pub const LIBRARIES: &[(&str, &str)] = &[ /// out — to validate a regenerated file as a candidate without its /// built-in copy colliding, or to run against a bare standard library. /// Always on where there is no environment (the browser target). +#[must_use] pub fn enabled() -> bool { !std::env::var_os("SYSMLV2_AMBIENT").is_some_and(|v| v == "off") } /// The ambient units in load order, honoring [`enabled`]. +#[must_use] pub fn units() -> Vec<(String, String)> { if !enabled() { return Vec::new(); @@ -79,6 +81,7 @@ pub fn add_to(model: &mut Model) { /// A content hash over the ambient sources (and whether they are /// enabled), mixed into library cache keys so a regenerated library /// never replays a stale recording. +#[must_use] pub fn content_hash() -> u64 { if !enabled() { return 0x6f66_6600; // "off" @@ -101,6 +104,7 @@ pub fn content_hash() -> u64 { } /// Mix an ambient content hash into a library-directory cache key. +#[must_use] pub fn mix_key(dir_key: u64) -> u64 { dir_key.rotate_left(17).wrapping_mul(0x9e37_79b9_7f4a_7c15) ^ content_hash() } diff --git a/crates/sysmlv2-model/src/cache_codec.rs b/crates/sysmlv2-model/src/cache_codec.rs new file mode 100644 index 0000000..d0a5a89 --- /dev/null +++ b/crates/sysmlv2-model/src/cache_codec.rs @@ -0,0 +1,769 @@ +//! Private schema-directed binary encoding for build-versioned library caches. +//! Fixed record layouts omit redundant collection headers. Scalar tags retain +//! dynamic JSON number types. String/byte lengths and collection counts are bounded. +#[cfg(test)] +use serde::Deserialize; +use serde::{ + Serialize, + de::{ + self, DeserializeOwned, DeserializeSeed, EnumAccess, IntoDeserializer, MapAccess, + SeqAccess, VariantAccess, Visitor, + }, + ser, +}; +use std::fmt; + +#[derive(Debug)] +pub(crate) struct Error(String); +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.0.fmt(f) + } +} +impl std::error::Error for Error {} +impl ser::Error for Error { + fn custom(s: T) -> Self { + Self(s.to_string()) + } +} +impl de::Error for Error { + fn custom(s: T) -> Self { + Self(s.to_string()) + } +} +type Result = std::result::Result; +#[cold] +fn bad() -> Error { + Error("invalid prepared-library encoding".into()) +} +const UNIT: u8 = 0; +const FALSE: u8 = 1; +const TRUE: u8 = 2; +const UINT: u8 = 3; +const INT: u8 = 4; +const FLOAT: u8 = 5; +const STR: u8 = 6; +const SEQ: u8 = 7; +const MAP: u8 = 8; +const ENUM: u8 = 9; +const SOME: u8 = 10; +const BYTES: u8 = 11; +pub(crate) fn encode(value: &impl Serialize) -> Result> { + let mut w = Writer::default(); + value.serialize(&mut w)?; + let mut out = Writer::default(); + out.count(w.2.len() as u64); + for value in &w.2 { + out.count(value.len() as u64); + out.0.extend_from_slice(value.as_bytes()); + } + out.0.extend(w.0); + Ok(out.0) +} +pub(crate) fn decode(bytes: &[u8]) -> Result { + let _strings = SharedStrings::enter(); + let mut r = Reader { + bytes, + depth: 0, + strings: Vec::new(), + }; + let count = r.length()?; + if count > 1_048_576 { + return Err(bad()); + } + for _ in 0..count { + let len = r.length()?; + let text = std::str::from_utf8(r.take(len)?).map_err(|_| bad())?; + r.strings.push(text); + } + let value = T::deserialize(&mut r)?; + if !r.bytes.is_empty() { + return Err(bad()); + } + Ok(value) +} +#[derive(Default)] +struct Writer( + Vec, + std::collections::HashMap, u64>, + Vec>, +); +impl Writer { + #[inline] + fn count(&mut self, mut n: u64) { + while n >= 128 { + self.0.push(n as u8 | 128); + n >>= 7; + } + self.0.push(n as u8); + } + fn collection(&mut self, tag: u8, n: usize) { + self.0.push(tag); + self.count(n as u64); + } + fn variant(&mut self, n: u32) { + self.0.push(ENUM); + self.count(n as u64); + } +} +struct Compound<'a>(&'a mut Writer); +macro_rules! integer_ser { ($($name:ident:$ty:ty => $dest:ident),*) => { $(fn $name(self,v:$ty)->Result<()> { self.$dest(v as _) })* }; } +impl<'a> ser::Serializer for &'a mut Writer { + type Ok = (); + type Error = Error; + type SerializeSeq = Compound<'a>; + type SerializeTuple = Compound<'a>; + type SerializeTupleStruct = Compound<'a>; + type SerializeTupleVariant = Compound<'a>; + type SerializeMap = Compound<'a>; + type SerializeStruct = Compound<'a>; + type SerializeStructVariant = Compound<'a>; + fn is_human_readable(&self) -> bool { + false + } + fn serialize_bool(self, v: bool) -> Result<()> { + self.0.push(if v { TRUE } else { FALSE }); + Ok(()) + } + integer_ser!(serialize_i8:i8=>serialize_i64,serialize_i16:i16=>serialize_i64,serialize_i32:i32=>serialize_i64,serialize_u8:u8=>serialize_u64,serialize_u16:u16=>serialize_u64,serialize_u32:u32=>serialize_u64); + fn serialize_i64(self, v: i64) -> Result<()> { + self.0.push(INT); + self.count(((v << 1) ^ (v >> 63)) as u64); + Ok(()) + } + fn serialize_u64(self, v: u64) -> Result<()> { + self.0.push(UINT); + self.count(v); + Ok(()) + } + fn serialize_f32(self, v: f32) -> Result<()> { + self.serialize_f64(v as f64) + } + fn serialize_f64(self, v: f64) -> Result<()> { + self.0.push(FLOAT); + self.0.extend_from_slice(&v.to_le_bytes()); + Ok(()) + } + fn serialize_char(self, v: char) -> Result<()> { + self.serialize_str(v.encode_utf8(&mut [0; 4])) + } + fn serialize_str(self, v: &str) -> Result<()> { + let index = if let Some(&index) = self.1.get(v) { + index + } else { + let text: std::sync::Arc = v.into(); + let index = self.2.len() as u64; + self.2.push(text.clone()); + self.1.insert(text, index); + index + }; + self.0.push(STR); + self.count(index); + Ok(()) + } + fn serialize_bytes(self, v: &[u8]) -> Result<()> { + self.collection(BYTES, v.len()); + self.0.extend_from_slice(v); + Ok(()) + } + fn serialize_none(self) -> Result<()> { + self.serialize_unit() + } + fn serialize_some(self, v: &T) -> Result<()> { + self.0.push(SOME); + v.serialize(self) + } + fn serialize_unit(self) -> Result<()> { + self.0.push(UNIT); + Ok(()) + } + fn serialize_unit_struct(self, _: &'static str) -> Result<()> { + self.serialize_unit() + } + fn serialize_unit_variant(self, _: &'static str, i: u32, _: &'static str) -> Result<()> { + self.variant(i); + Ok(()) + } + fn serialize_newtype_struct(self, _: &'static str, v: &T) -> Result<()> { + v.serialize(self) + } + fn serialize_newtype_variant( + self, + _: &'static str, + i: u32, + _: &'static str, + v: &T, + ) -> Result<()> { + self.variant(i); + v.serialize(self) + } + fn serialize_seq(self, n: Option) -> Result> { + self.collection(SEQ, n.ok_or_else(bad)?); + Ok(Compound(self)) + } + fn serialize_tuple(self, _: usize) -> Result> { + Ok(Compound(self)) + } + fn serialize_tuple_struct(self, _: &'static str, n: usize) -> Result> { + self.serialize_tuple(n) + } + fn serialize_tuple_variant( + self, + _: &'static str, + i: u32, + _: &'static str, + n: usize, + ) -> Result> { + self.variant(i); + self.serialize_tuple(n) + } + fn serialize_map(self, n: Option) -> Result> { + self.collection(MAP, n.ok_or_else(bad)?); + Ok(Compound(self)) + } + fn serialize_struct(self, _: &'static str, n: usize) -> Result> { + self.serialize_tuple(n) + } + fn serialize_struct_variant( + self, + _: &'static str, + i: u32, + _: &'static str, + n: usize, + ) -> Result> { + self.variant(i); + self.serialize_tuple(n) + } +} +macro_rules! compound { + ($trait:ident,$method:ident) => { + impl ser::$trait for Compound<'_> { + type Ok = (); + type Error = Error; + fn $method(&mut self, v: &T) -> Result<()> { + v.serialize(&mut *self.0) + } + fn end(self) -> Result<()> { + Ok(()) + } + } + }; +} +compound!(SerializeSeq, serialize_element); +compound!(SerializeTuple, serialize_element); +compound!(SerializeTupleStruct, serialize_field); +compound!(SerializeTupleVariant, serialize_field); +impl ser::SerializeMap for Compound<'_> { + type Ok = (); + type Error = Error; + fn serialize_key(&mut self, v: &T) -> Result<()> { + v.serialize(&mut *self.0) + } + fn serialize_value(&mut self, v: &T) -> Result<()> { + v.serialize(&mut *self.0) + } + fn end(self) -> Result<()> { + Ok(()) + } +} +macro_rules! compound_struct { + ($trait:ident) => { + impl ser::$trait for Compound<'_> { + type Ok = (); + type Error = Error; + fn serialize_field( + &mut self, + _: &'static str, + v: &T, + ) -> Result<()> { + v.serialize(&mut *self.0) + } + fn end(self) -> Result<()> { + Ok(()) + } + } + }; +} +compound_struct!(SerializeStruct); +compound_struct!(SerializeStructVariant); +struct Reader<'de> { + bytes: &'de [u8], + depth: usize, + strings: Vec<&'de str>, +} +impl<'de> Reader<'de> { + #[inline] + fn take(&mut self, n: usize) -> Result<&'de [u8]> { + if n > self.bytes.len() { + return Err(bad()); + } + let (v, rest) = self.bytes.split_at(n); + self.bytes = rest; + Ok(v) + } + #[inline] + fn tag(&mut self) -> Result { + Ok(self.take(1)?[0]) + } + #[inline] + fn count(&mut self) -> Result { + let mut n = 0; + for shift in (0..70).step_by(7) { + let b = self.tag()?; + if shift == 63 && b > 1 { + return Err(bad()); + } + n |= ((b & 127) as u64) << shift; + if b < 128 { + return Ok(n); + } + } + Err(bad()) + } + #[inline] + fn length(&mut self) -> Result { + let n = usize::try_from(self.count()?).map_err(|_| bad())?; + if n > self.bytes.len() { + return Err(bad()); + } + Ok(n) + } +} +struct Access<'a, 'de> { + r: &'a mut Reader<'de>, + remaining: usize, +} +impl<'de> SeqAccess<'de> for Access<'_, 'de> { + type Error = Error; + fn next_element_seed>(&mut self, seed: T) -> Result> { + if self.remaining == 0 { + return Ok(None); + } + self.remaining -= 1; + seed.deserialize(&mut *self.r).map(Some) + } + fn size_hint(&self) -> Option { + Some(self.remaining.min(1_048_576)) + } +} +impl<'de> MapAccess<'de> for Access<'_, 'de> { + type Error = Error; + fn next_key_seed>(&mut self, seed: T) -> Result> { + self.next_element_seed(seed) + } + fn next_value_seed>(&mut self, seed: T) -> Result { + seed.deserialize(&mut *self.r) + } + fn size_hint(&self) -> Option { + Some(self.remaining.min(1_048_576)) + } +} +impl<'de> de::Deserializer<'de> for &mut Reader<'de> { + type Error = Error; + fn is_human_readable(&self) -> bool { + false + } + fn deserialize_any>(self, v: V) -> Result { + match self.bytes.first() { + Some(&SEQ) => return self.collection(v, false), + Some(&MAP) => return self.collection(v, true), + _ => {} + } + if self.depth >= 256 { + return Err(bad()); + } + self.depth += 1; + let result = match self.tag()? { + UNIT => v.visit_unit(), + FALSE => v.visit_bool(false), + TRUE => v.visit_bool(true), + UINT => v.visit_u64(self.count()?), + INT => { + let n = self.count()?; + v.visit_i64(((n >> 1) as i64) ^ -((n & 1) as i64)) + } + FLOAT => v.visit_f64(f64::from_le_bytes( + self.take(8)?.try_into().map_err(|_| bad())?, + )), + STR => { + let index = usize::try_from(self.count()?).map_err(|_| bad())?; + v.visit_borrowed_str(self.strings.get(index).copied().ok_or_else(bad)?) + } + BYTES => { + let n = self.length()?; + v.visit_borrowed_bytes(self.take(n)?) + } + _ => Err(bad()), + }; + self.depth -= 1; + result + } + fn deserialize_seq>(self, v: V) -> Result { + self.collection(v, false) + } + fn deserialize_map>(self, v: V) -> Result { + self.collection(v, true) + } + fn deserialize_tuple>(self, n: usize, v: V) -> Result { + self.fixed(v, n) + } + fn deserialize_tuple_struct>( + self, + _: &'static str, + n: usize, + v: V, + ) -> Result { + self.fixed(v, n) + } + fn deserialize_struct>( + self, + _: &'static str, + fields: &'static [&'static str], + v: V, + ) -> Result { + self.fixed(v, fields.len()) + } + fn deserialize_option>(self, v: V) -> Result { + if self.depth >= 256 { + return Err(bad()); + } + self.depth += 1; + let result = match self.tag()? { + UNIT => v.visit_none(), + SOME => v.visit_some(&mut *self), + _ => Err(bad()), + }; + self.depth -= 1; + result + } + fn deserialize_newtype_struct>( + self, + _: &'static str, + v: V, + ) -> Result { + v.visit_newtype_struct(self) + } + fn deserialize_enum>( + self, + _: &'static str, + _: &'static [&'static str], + v: V, + ) -> Result { + if self.tag()? != ENUM || self.depth >= 256 { + return Err(bad()); + } + self.depth += 1; + let i = u32::try_from(self.count()?).map_err(|_| bad())?; + let result = v.visit_enum(Variant { r: self, index: i }); + self.depth -= 1; + result + } + fn deserialize_u64>(self, v: V) -> Result { + if self.bytes.first() != Some(&UINT) { + return self.deserialize_any(v); + } + self.bytes = &self.bytes[1..]; + v.visit_u64(self.count()?) + } + fn deserialize_i64>(self, v: V) -> Result { + if self.bytes.first() != Some(&INT) { + return self.deserialize_any(v); + } + self.bytes = &self.bytes[1..]; + let n = self.count()?; + v.visit_i64(((n >> 1) as i64) ^ -((n & 1) as i64)) + } + fn deserialize_bool>(self, v: V) -> Result { + match self.bytes.first() { + Some(&TRUE) | Some(&FALSE) => { + let b = self.bytes[0] == TRUE; + self.bytes = &self.bytes[1..]; + v.visit_bool(b) + } + _ => self.deserialize_any(v), + } + } + fn deserialize_str>(self, v: V) -> Result { + if self.bytes.first() != Some(&STR) { + return self.deserialize_any(v); + } + self.bytes = &self.bytes[1..]; + let i = usize::try_from(self.count()?).map_err(|_| bad())?; + v.visit_borrowed_str(self.strings.get(i).copied().ok_or_else(bad)?) + } + fn deserialize_string>(self, v: V) -> Result { + self.deserialize_str(v) + } + fn deserialize_u8>(self, v: V) -> Result { + self.deserialize_u64(v) + } + fn deserialize_u16>(self, v: V) -> Result { + self.deserialize_u64(v) + } + fn deserialize_u32>(self, v: V) -> Result { + self.deserialize_u64(v) + } + fn deserialize_i8>(self, v: V) -> Result { + self.deserialize_i64(v) + } + fn deserialize_i16>(self, v: V) -> Result { + self.deserialize_i64(v) + } + fn deserialize_i32>(self, v: V) -> Result { + self.deserialize_i64(v) + } + serde::forward_to_deserialize_any! { f32 f64 char bytes byte_buf unit unit_struct identifier ignored_any } +} +impl<'de> Reader<'de> { + fn fixed>(&mut self, v: V, n: usize) -> Result { + if self.depth >= 256 { + return Err(bad()); + } + self.depth += 1; + let mut access = Access { + r: self, + remaining: n, + }; + let result = v.visit_seq(&mut access); + let remaining = access.remaining; + self.depth -= 1; + if remaining != 0 { + return Err(bad()); + } + result + } + fn collection>(&mut self, v: V, map: bool) -> Result { + if self.depth >= 256 || self.tag()? != if map { MAP } else { SEQ } { + return Err(bad()); + } + self.depth += 1; + let n = usize::try_from(self.count()?).map_err(|_| bad())?; + // Fixed empty records occupy no payload bytes, so element counts + // have a separate bound instead of assuming one byte per element. + if n > 1_048_576 { + return Err(bad()); + } + let mut a = Access { + r: self, + remaining: n, + }; + let result = if map { + v.visit_map(&mut a) + } else { + v.visit_seq(&mut a) + }; + let left = a.remaining; + self.depth -= 1; + if left != 0 { + return Err(bad()); + } + result + } +} +struct Variant<'a, 'de> { + r: &'a mut Reader<'de>, + index: u32, +} +impl<'a, 'de> EnumAccess<'de> for Variant<'a, 'de> { + type Error = Error; + type Variant = Self; + fn variant_seed>(self, seed: V) -> Result<(V::Value, Self)> { + Ok((seed.deserialize(self.index.into_deserializer())?, self)) + } +} +impl<'de> VariantAccess<'de> for Variant<'_, 'de> { + type Error = Error; + fn unit_variant(self) -> Result<()> { + Ok(()) + } + fn newtype_variant_seed>(self, seed: T) -> Result { + seed.deserialize(&mut *self.r) + } + fn tuple_variant>(self, n: usize, v: V) -> Result { + de::Deserializer::deserialize_tuple(&mut *self.r, n, v) + } + fn struct_variant>( + self, + fields: &'static [&'static str], + v: V, + ) -> Result { + de::Deserializer::deserialize_struct(&mut *self.r, "", fields, v) + } +} + +#[cfg(test)] +mod tests { + use super::*; + #[derive(Debug, PartialEq, Serialize, Deserialize)] + enum Choice { + Empty, + Value(Option>), + Pair(String, u64), + Fields { value: f64 }, + } + #[test] + fn binary_cache_preserves_numbers_variants_options_and_tuple_keys() { + let choices = vec![ + Choice::Empty, + Choice::Value(None), + Choice::Value(Some(None)), + Choice::Value(Some(Some(i64::MIN))), + Choice::Pair("é".into(), u64::MAX), + Choice::Fields { value: -0.0 }, + ]; + let bytes = encode(&choices).unwrap(); + assert_eq!(decode::>(&bytes).unwrap(), choices); + let value = serde_json::json!({"signed":i64::MIN,"unsigned":u64::MAX,"float":1e-28,"empty":null,"array":[true,false,{},[]]}); + assert_eq!( + decode::(&encode(&value).unwrap()).unwrap(), + value + ); + let map = std::collections::HashMap::from([((42usize, "name".to_string()), Some(8usize))]); + assert_eq!( + decode::>>( + &encode(&map).unwrap() + ) + .unwrap(), + map + ); + for cut in 0..bytes.len() { + assert!(decode::>(&bytes[..cut]).is_err()); + } + let mut trailing = bytes; + trailing.push(UNIT); + assert!(decode::>(&trailing).is_err()); + assert!( + decode::>(&[SEQ, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255]) + .is_err() + ); + } +} + +#[cfg(test)] +mod string_table_tests { + use super::*; + #[test] + fn repeated_strings_are_interned_and_invalid_tables_are_rejected() { + let values = vec!["a long repeated property and qualified name".to_owned(); 100]; + let encoded = encode(&values).unwrap(); + assert!(encoded.len() < 300); + assert_eq!(decode::>(&encoded).unwrap(), values); + // No strings but a string reference, truncated string, invalid UTF-8, + // and an out-of-bounds reference to a one-entry table. + for bytes in [ + vec![0, STR, 0], + vec![1, 2, b'a'], + vec![1, 1, 255, UNIT], + vec![1, 1, b'a', STR, 1], + ] { + assert!(decode::(&bytes).is_err()); + } + } +} + +// Only active during this decoder's call. Table slices remain alive throughout +// it, so a borrowed string's address identifies its table entry. No raw pointer +// is dereferenced. Nested decodes get independent tables; the guard restores +// the previous context on both normal returns and unwinding. +type StringPool = std::collections::HashMap<(usize, usize), std::sync::Arc>; +thread_local! { + static SHARED_STRINGS: std::cell::RefCell> = const { std::cell::RefCell::new(None) }; +} +struct SharedStrings(Option); +impl SharedStrings { + fn enter() -> Self { + Self(SHARED_STRINGS.with(|v| v.replace(Some(Default::default())))) + } +} +impl Drop for SharedStrings { + fn drop(&mut self) { + SHARED_STRINGS.with(|v| { + v.replace(self.0.take()); + }); + } +} +pub(crate) fn shared_string<'de, D: serde::Deserializer<'de>>( + d: D, +) -> std::result::Result, D::Error> { + struct Text; + impl serde::de::Visitor<'_> for Text { + type Value = std::sync::Arc; + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("a string") + } + fn visit_str(self, s: &str) -> std::result::Result { + Ok(s.into()) + } + fn visit_borrowed_str( + self, + s: &str, + ) -> std::result::Result { + Ok(SHARED_STRINGS.with(|pool| { + let mut pool = pool.borrow_mut(); + let Some(pool) = pool.as_mut() else { + return s.into(); + }; + let value = pool + .entry((s.as_ptr() as usize, s.len())) + .or_insert_with(|| s.into()); + // Also safe for another serde source used within a decode. + if value.as_ref() != s { + *value = s.into(); + } + value.clone() + })) + } + } + d.deserialize_str(Text) +} + +#[cfg(test)] +mod shared_text_tests { + use super::*; + use std::sync::Arc; + #[derive(Serialize, Deserialize)] + struct Text(#[serde(deserialize_with = "shared_string")] Arc); + #[test] + fn repeated_text_is_shared_and_decode_contexts_do_not_escape() { + let source = vec![Text("repeated name".into()), Text("repeated name".into())]; + let bytes = encode(&source).unwrap(); + let first: Vec = decode(&bytes).unwrap(); + assert!(Arc::ptr_eq(&first[0].0, &first[1].0)); + assert!(SHARED_STRINGS.with(|s| s.borrow().is_none())); + let next: Vec = decode(&bytes).unwrap(); + assert!(!Arc::ptr_eq(&first[0].0, &next[0].0)); + assert!(decode::>(&bytes[..bytes.len() - 1]).is_err()); + assert!(SHARED_STRINGS.with(|s| s.borrow().is_none())); + let outer = SharedStrings::enter(); + { + let _inner = SharedStrings::enter(); + } + assert!(SHARED_STRINGS.with(|s| s.borrow().is_some())); + drop(outer); + assert!(SHARED_STRINGS.with(|s| s.borrow().is_none())); + } +} + +#[cfg(test)] +mod record_tests { + use super::*; + #[derive(Debug, PartialEq, Serialize, Deserialize)] + struct Empty {} + #[test] + fn fixed_records_preserve_zero_width_values_and_bound_counts() { + let values = vec![Empty {}, Empty {}, Empty {}]; + assert_eq!( + decode::>(&encode(&values).unwrap()).unwrap(), + values + ); + let mut w = Writer::default(); + w.count(0); + w.collection(SEQ, 1_048_577); + assert!(decode::>(&w.0).is_err()); + let tuple = (17u32, "text", Some(false)); + assert_eq!( + decode::<(u32, String, Option)>(&encode(&tuple).unwrap()).unwrap(), + (17, "text".into(), Some(false)) + ); + } +} diff --git a/crates/sysmlv2-model/src/check.rs b/crates/sysmlv2-model/src/check.rs index bb8d41c..b4935fe 100644 --- a/crates/sysmlv2-model/src/check.rs +++ b/crates/sysmlv2-model/src/check.rs @@ -2,12 +2,143 @@ use sysmlv2_syntax::diag::Diagnostic; +mod actions; +mod chains; +mod connectors; +mod dimensions; +mod distinguishability; +mod endpoints; +mod expressions; +pub(crate) mod facts; +mod invocations; +mod multiplicities; +mod relationships; +mod scalars; +mod specialization; +mod structural; +mod typing; +mod values; + +pub use distinguishability::InheritedNameCollision; +pub use typing::IncompatibleTyping; + +/// Every inherited-name collision among the user elements — the pairs +/// the semantic check reports as `validateNamespaceDistinguishibility` — +/// for repairs that spell the missing redefinition. +pub fn inherited_name_collisions( + r: &mut crate::json::ResolvedModel, +) -> Vec { + distinguishability::collisions(r) +} + +/// Whether `metaclass` is `base` or one of its specializations in the +/// KerML/SysML metamodel (`PortDefinition` conforms to `Definition`). +#[must_use] +pub fn metaclass_conforms(metaclass: &str, base: &str) -> bool { + crate::metaclass::conforms(metaclass, base) +} + +/// Every user usage typed by a definition its own kind cannot take — the +/// pairs the semantic check reports as `X must be typed by Y` — for +/// repairs that rewrite the usage keyword. +#[must_use] +pub fn incompatible_typings(r: &crate::json::ResolvedModel) -> Vec { + typing::incompatible_typings(r) +} + +/// Semantic diagnostics whose rule names occur in the pinned XMI. Labels +/// introduced by later validator versions are tracked separately in the +/// external-fixture contracts and do not enlarge the normative denominator. +pub const IMPLEMENTED_NORMATIVE_SEMANTIC_RULES: &[&str] = &[ + "validateAssertConstraintUsageReference", + "validateAssignmentActionUsageReferent", + "validateAssociationBinarySpecialization", + "validateAssociationEndTypes", + "validateAssociationRelatedTypes", + "validateBehaviorSpecialization", + "validateBindingConnectorIsBinary", + "validateCaseDefinitionOnlyOneObjective", + "validateCaseUsageOnlyOneObjective", + "validateClassSpecialization", + "validateConnectorRelatedFeatures", + "validateConstructorExpressionNoDuplicateFeatureRedefinition", + "validateControlNodeIncomingSuccessions", + "validateControlNodeOutgoingSuccessions", + "validateControlNodeOwningType", + "validateCrossSubsettingCrossedFeature", + "validateCrossSubsettingCrossingFeature", + "validateDataTypeSpecialization", + "validateDecisionNodeIncomingSuccessions", + "validateDecisionNodeOutgoingSuccessions", + "validateDefinitionVariationSpecialization", + "validateExhibitStateUsageReference", + "validateExpressionResultExpressionMembership", + "validateExpressionResultParameterMembership", + "validateFeatureChainingFeatureConformance", + "validateFeatureChainingFeatureNotOne", + "validateFeatureChainingFeaturesNotSelf", + "validateFeatureConstantIsVariable", + "validateFeatureCrossFeatureSpecialization", + "validateFeatureCrossFeatureType", + "validateFeatureIsVariable", + "validateFeatureOwnedCrossSubsetting", + "validateFeatureOwnedReferenceSubsetting", + "validateFeaturePortionNotVariable", + "validateFeatureReferenceExpressionReferentIsFeature", + "validateFeatureValueIsInitial", + "validateFeatureValueOverriding", + "validateForkNodeIncomingSuccessions", + "validateFunctionResultExpressionMembership", + "validateFunctionResultParameterMembership", + "validateIncludeUseCaseUsageReference", + "validateInstantiationExpressionInstantiatedType", + "validateInvocationExpressionInstantiatedType", + "validateJoinNodeOutgoingSuccessions", + "validateMergeNodeIncomingSuccessions", + "validateMergeNodeOutgoingSuccessions", + "validateMetadataFeatureAnnotatedElement", + "validateMetadataFeatureBody", + "validateNamespaceDistinguishibility", + "validateOccurrenceUsageIndividualDefinition", + "validateOccurrenceUsageIndividualUsage", + "validateOccurrenceUsageIsPortion", + "validatePerformActionUsageReference", + "validatePortDefinitionOwnedUsagesNotComposite", + "validatePortUsageIsReference", + "validatePortUsageNestedUsagesNotComposite", + "validateRedefinitionDirectionConformance", + "validateRedefinitionEndConformance", + "validateRedefinitionFeaturingTypes", + "validateRequirementDefinitionOnlyOneSubject", + "validateRequirementUsageOnlyOneSubject", + "validateRequirementVerificationMembershipOwningType", + "validateSatisfyRequirementUsageReference", + "validateStateDefinitionParallelSubactions", + "validateStateUsageParallelSubactions", + "validateStructureSpecialization", + "validateSubsettingConstantConformance", + "validateSubsettingFeaturingTypes", + "validateSubsettingUniquenessConformance", + "validateTransitionFeatureMembershipGuardExpression", + "validateTransitionUsageSuccession", + "validateTransitionUsageTriggerActions", + "validateTypeDifferencingTypesNotSelf", + "validateTypeIntersectingTypesNotSelf", + "validateTypeOwnedMultiplicity", + "validateTypeUnioningTypesNotSelf", + "validateUsageVariationSpecialization", + "validateViewDefinitionOnlyOneViewRendering", + "validateViewUsageOnlyOneViewRendering", +]; + /// Referential checks over a resolved multi-file model: -/// unresolved references, unresolvable alias targets, and circular -/// namespace imports, attributed to the unit they were written in (index -/// into [`crate::model::Model::units`]). +/// unresolved references, unresolvable alias targets, circular +/// namespace imports, and user root declarations that share a name with +/// a standard-library root (reported as library-winning or ambiguous), attributed to the +/// unit they were written in (index into [`crate::model::Model::units`]). /// -/// These are **warnings**: the resolver covers 99.9%+ of the corpus, but a +/// Unresolved names, aliases, import cycles and root collisions are warnings; +/// ambiguous references are errors. The resolver covers 99.9%+ of the corpus, but a /// small long tail of legitimate spellings is still beyond it (and some /// corpus files contain genuine reference errors) — so unresolved names /// must not fail conforming models. Library units are skipped. @@ -17,8 +148,9 @@ pub fn validate_model(model: &crate::model::Model) -> Vec<(usize, Diagnostic)> { } /// [`validate_model`] over an already-built [`crate::json::ResolvedModel`] — -/// lets one build serve both referential and semantic checks (drains the -/// builder's unresolved list; run this before [`validate_semantics_with`]). +/// lets one build serve both referential and semantic checks (the +/// builder's unresolved list stays readable; run this before +/// [`validate_semantics_with`]). pub fn validate_model_with( r: &mut crate::json::ResolvedModel, model: &crate::model::Model, @@ -31,21 +163,32 @@ pub fn validate_model_with( .iter() .map(|(unit, qn)| (*unit, qn.span.start)) .collect(); + let blocked: std::collections::HashMap<(usize, u32), (String, &'static str)> = report + .blocked + .iter() + .map(|b| { + let member = r + .element_qualified_name(b.member) + .unwrap_or_else(|| b.name.to_display_string()); + ((b.unit, b.name.span.start), (member, b.visibility)) + }) + .collect(); let mut out = Vec::new(); for (unit, qn) in report.unresolved { - if model.units()[unit].is_library || alias_spans.contains(&(unit, qn.span.start)) { + if model.is_library_unit(unit) || alias_spans.contains(&(unit, qn.span.start)) { continue; } - out.push(( - unit, - Diagnostic::warning( - qn.span, - format!("unresolved reference `{}`", qn.to_display_string()), + let message = match blocked.get(&(unit, qn.span.start)) { + Some((member, visibility)) => format!( + "unresolved reference `{}` — `{member}` exists but is {visibility}", + qn.to_display_string() ), - )); + None => format!("unresolved reference `{}`", qn.to_display_string()), + }; + out.push((unit, Diagnostic::warning(qn.span, message))); } for (unit, qn) in report.ambiguous { - if model.units()[unit].is_library { + if model.is_library_unit(unit) { continue; } out.push(( @@ -60,7 +203,7 @@ pub fn validate_model_with( )); } for (unit, qn) in report.unresolved_aliases { - if model.units()[unit].is_library { + if model.is_library_unit(unit) { continue; } out.push(( @@ -72,7 +215,7 @@ pub fn validate_model_with( )); } for (unit, qn) in report.import_cycles { - if model.units()[unit].is_library { + if model.is_library_unit(unit) { continue; } out.push(( @@ -87,11 +230,119 @@ pub fn validate_model_with( ), )); } + for s in report.shadowed_roots { + if model.is_library_unit(s.unit) { + continue; + } + let tail = if s.resolves_to_library { + "references resolve to the library" + } else { + "references to the name are ambiguous" + }; + out.push(( + s.unit, + Diagnostic::warning( + s.span, + format!( + "root {} `{}` shadows the standard library {} `{}`; {tail}", + root_kind_word(s.metaclass), + s.name, + root_kind_word(s.library_metaclass), + s.name, + ), + ), + )); + } // Report in source order per unit. out.sort_by_key(|(unit, d)| (*unit, d.span.start)); out } +/// The everyday word for a root declaration's metaclass in the +/// root-shadowing finding. +fn root_kind_word(metaclass: &str) -> &'static str { + match metaclass { + "Package" | "LibraryPackage" => "package", + "Namespace" => "namespace", + _ => "declaration", + } +} + +/// The rows of a builder table that user elements own, copied once so a +/// pass can evaluate against `&mut r.b` while walking them. Library rows +/// never produce findings; skipping them by reference leaves the shared +/// library prefix untouched. +pub(crate) fn user_rows<'a, T: Clone + 'a>( + b: &crate::json::Builder, + model: &crate::model::Model, + rows: impl IntoIterator, + owner: impl Fn(&T) -> usize, +) -> Vec { + rows.into_iter() + .filter(|row| !model.is_library_unit(b.unit_of_elem(owner(row)))) + .cloned() + .collect() +} + +/// A finding reporting the semantic rule `rule` names. The identifier +/// lands in the finding's `code`; it also stays spelled at the end of +/// the message, where the command-line and editor surfaces read it. +pub(crate) fn rule_error( + span: sysmlv2_syntax::Span, + rule: &'static str, + message: impl std::fmt::Display, +) -> Diagnostic { + Diagnostic::error(span, format!("{message} [{rule}]")).with_code(normative_rule(rule)) +} + +/// [`rule_error`] at warning severity. +pub(crate) fn rule_warning( + span: sysmlv2_syntax::Span, + rule: &'static str, + message: impl std::fmt::Display, +) -> Diagnostic { + Diagnostic::warning(span, format!("{message} [{rule}]")).with_code(normative_rule(rule)) +} + +/// The identifier of a rule in the spelling the pinned abstract syntax +/// uses. Two rules reached this implementation through an imported probe +/// suite that names them differently; their messages keep that spelling, +/// which the imported contracts are keyed by, while the finding carries +/// the pinned one. +fn normative_rule(rule: &'static str) -> &'static str { + match rule { + "validateViewDefinitionOnlyOnvViewRendering" => { + "validateViewDefinitionOnlyOneViewRendering" + } + "validateViewUsageOnlyOneRendering" => "validateViewUsageOnlyOneViewRendering", + other => other, + } +} + +/// The number an evaluated value is, as `f64` — the reading the bound +/// checks share. `None` for anything that is not a scalar number. +pub(crate) fn scalar_f64(v: &crate::eval::Value) -> Option { + match v { + crate::eval::Value::Integer(i) => Some(*i as f64), + crate::eval::Value::Rational(r) => Some(r.to_f64()), + crate::eval::Value::Real(f) => Some(*f), + _ => None, + } +} + +/// [`user_rows`] over a table keyed by owning element. +pub(crate) fn user_entries<'a, V: Clone + 'a>( + b: &crate::json::Builder, + model: &crate::model::Model, + entries: impl IntoIterator, +) -> Vec<(usize, V)> { + entries + .into_iter() + .filter(|(&e, _)| !model.is_library_unit(b.unit_of_elem(e))) + .map(|(&e, v)| (e, v.clone())) + .collect() +} + /// KerML 8.4-style semantic constraints over the resolved graph, /// attributed like [`validate_model`]. Checked: /// @@ -120,1049 +371,40 @@ pub fn validate_semantics(model: &crate::model::Model) -> Vec<(usize, Diagnostic } /// [`validate_semantics`] over an already-built [`crate::json::ResolvedModel`]. +/// Preserves import provenance: speculative validation lookups are not source +/// references and must not hide unused imports from later analyses. pub fn validate_semantics_with( r: &mut crate::json::ResolvedModel, model: &crate::model::Model, ) -> Vec<(usize, Diagnostic)> { let r = &mut *r; + let used_imports = r.b.used_imports.clone(); let mut out = Vec::new(); - // --- multiplicity bounds --- - for (owner, scope, mult) in r.b.multiplicities.clone() { - if model.units()[r.b.unit_of_elem(owner)].is_library { - continue; - } - let upper = crate::eval::evaluate_expr_in(&mut r.b, scope, &mult.upper).ok(); - let lower = match &mult.lower { - Some(l) => crate::eval::evaluate_expr_in(&mut r.b, scope, l).ok(), - None => None, - }; - let as_num = |v: &crate::eval::Value| match v { - crate::eval::Value::Integer(i) => Some(*i as f64), - crate::eval::Value::Rational(f) => Some(*f), - _ => None, - }; - let lo = lower.as_ref().and_then(as_num); - let hi = upper.as_ref().and_then(as_num); - if let Some(lo) = lo { - if lo < 0.0 { - out.push(( - r.b.unit_of_elem(owner), - Diagnostic::error(mult.span, "multiplicity lower bound is negative"), - )); - continue; - } - } - if let Some(hi) = hi { - if hi < 0.0 { - out.push(( - r.b.unit_of_elem(owner), - Diagnostic::error(mult.span, "multiplicity upper bound is negative"), - )); - continue; - } - } - if let (Some(lo), Some(hi)) = (lo, hi) { - if lo > hi { - out.push(( - r.b.unit_of_elem(owner), - Diagnostic::error( - mult.span, - format!("multiplicity lower bound {lo} exceeds upper bound {hi}"), - ), - )); - } - } - } - - // --- subclassification self-reference / cycles / duplicates --- - use std::collections::{HashMap, HashSet}; - let specs = r.b.spec_targets.clone(); - // Resolve every recorded target once. - let mut resolved: Vec<( - usize, - &'static str, - usize, - &sysmlv2_syntax::ast::QualifiedName, - )> = Vec::new(); - for (owner, kind, scope, qn) in &specs { - // Library-owned specializations can't produce findings (every check - // below skips library owners) and can't participate in a user-visible - // cycle (no library edge points into a user definition) — skipping - // them keeps the semantic pass proportional to the user model. - if model.units()[r.b.unit_of_elem(*owner)].is_library { - continue; - } - if let Some(t) = r.b.resolve(*scope, qn, 0) { - resolved.push((*owner, kind, t, qn)); - } - } - let mut subcl_edges: HashMap> = HashMap::new(); - let mut seen_per_owner: HashSet<(usize, &'static str, usize)> = HashSet::new(); - for (owner, kind, target, qn) in &resolved { - let unit = r.b.unit_of_elem(*owner); - let is_lib = model.units()[unit].is_library; - if *kind == "Subclassification" { - if target == owner && !is_lib { - out.push(( - unit, - Diagnostic::error( - qn.span, - format!("`{}` cannot specialize itself", qn.to_display_string()), - ), - )); - continue; - } - subcl_edges.entry(*owner).or_default().push(*target); - } - if !seen_per_owner.insert((*owner, kind, *target)) && !is_lib { - out.push(( - unit, - Diagnostic::warning( - qn.span, - format!("duplicate specialization of `{}`", qn.to_display_string()), - ), - )); - } - } - // Cycle detection over subclassification edges (self-edges reported above). - for (owner, kind, _, qn) in &resolved { - if *kind != "Subclassification" { - continue; - } - let unit = r.b.unit_of_elem(*owner); - if model.units()[unit].is_library { - continue; - } - // DFS from each of owner's supertypes back to owner. - let mut stack: Vec = subcl_edges.get(owner).cloned().unwrap_or_default(); - let mut seen: HashSet = HashSet::new(); - let mut cyclic = false; - while let Some(s) = stack.pop() { - if s == *owner { - cyclic = true; - break; - } - if seen.insert(s) { - if let Some(next) = subcl_edges.get(&s) { - stack.extend(next); - } - } - } - if cyclic { - out.push(( - unit, - Diagnostic::error( - qn.span, - "circular specialization: this definition transitively \ - specializes itself" - .to_string(), - ), - )); - } - } - - // --- metadata feature typing --- - // A metadata feature must be typed by exactly one metaclass — a - // `metadata def` (SysML) or `metaclass` (KerML). A typing that - // resolves to any other kind of element is provably wrong (error); - // unresolved targets stay referential warnings, per checker policy. - let mut metadata_typing_count: HashMap = HashMap::new(); - for (owner, kind, _, _) in &specs { - if *kind == "FeatureTyping" - && matches!(r.b.elements[*owner].ty, "MetadataUsage" | "MetadataFeature") - { - *metadata_typing_count.entry(*owner).or_insert(0) += 1; - } - } - let mut metadata_first_typing: HashSet = HashSet::new(); - for (owner, kind, target, qn) in &resolved { - if *kind != "FeatureTyping" - || !matches!(r.b.elements[*owner].ty, "MetadataUsage" | "MetadataFeature") - { - continue; - } - let unit = r.b.unit_of_elem(*owner); - if model.units()[unit].is_library { - continue; - } - let target_ty = r.b.elements[*target].ty; - if !matches!(target_ty, "MetadataDefinition" | "Metaclass") { - out.push(( - unit, - Diagnostic::error( - qn.span, - format!( - "metadata must be typed by a metadata definition or \ - metaclass; `{}` is a {}", - qn.to_display_string(), - target_ty - ), - ), - )); - } else if metadata_typing_count.get(owner).copied().unwrap_or(0) > 1 - && !metadata_first_typing.insert(*owner) - { - out.push(( - unit, - Diagnostic::error( - qn.span, - "metadata must be typed by exactly one metaclass".to_string(), - ), - )); - } - } - - // Explicit multiplicities by owner, for redefinition conformance. - let mults: HashMap = - r.b.multiplicities - .iter() - .map(|(o, s, m)| (*o, (*s, m.clone()))) - .collect(); - // Numeric bounds of a multiplicity: `[l..u]` directly, `[u]` is - // exact (`l = u`) except `[*]`, whose missing lower is 0. - let bounds = |r: &mut crate::json::ResolvedModel, - scope: usize, - m: &sysmlv2_syntax::ast::Multiplicity| - -> Option<(f64, f64)> { - let as_num = |v: crate::eval::Value| match v { - crate::eval::Value::Integer(i) => Some(i as f64), - crate::eval::Value::Rational(f) => Some(f), - _ => None, - }; - let hi = as_num(crate::eval::evaluate_expr_in(&mut r.b, scope, &m.upper).ok()?)?; - let lo = match &m.lower { - Some(l) => as_num(crate::eval::evaluate_expr_in(&mut r.b, scope, l).ok()?)?, - None if hi.is_infinite() => 0.0, - None => hi, - }; - Some((lo, hi)) - }; - - // --- redefinition type-compatibility --- - // A redefining feature's declared types should conform to the - // redefined feature's declared types (KerML 8.4 redefinition - // conformance). Checked only when both sides carry explicit typings - // and the target's type is user-owned — the explicit closure is - // complete between user types, while conformance to a *library* - // type may ride implied bases this walk cannot see (those stay - // silent). Deliberately NOT checked for `Subsetting`: KerML's - // multiple classification lets a value be both a `Cause` and a - // `Situation` without `Cause` specializing `Situation`, and the - // official `Model Library Example.sysml` uses exactly that pattern - // (`causes : Cause[*] :> situations`). Warnings, per checker policy. - for i in 0..r.b.spec_targets.len() { - let (owner, kind) = { - let t = &r.b.spec_targets[i]; - (t.0, t.1) - }; - if kind != "Redefinition" { - continue; - } - let unit = r.b.unit_of_elem(owner); - if model.units()[unit].is_library { - continue; - } - // The builder's pending pass already resolved this target with the - // owner excluded (`:>> x` names the *inherited* feature) — read the - // recorded outcome instead of re-resolving, which self-hits and - // falls through to full import scans (~0.2 ms per redefinition). - let Some(target) = r.b.spec_resolved.get(i).copied().flatten() else { - continue; // unresolved targets are the referential checks' job - }; - if target == owner { - continue; - } - let qn = r.b.spec_targets[i].3.clone(); - // Multiplicity conformance: when both sides declare - // explicit numeric multiplicities, the redefining range must - // lie within the redefined one. - if let (Some((os, om)), Some((ts, tm))) = (mults.get(&owner), mults.get(&target)) { - let (os, om, ts, tm) = (*os, om.clone(), *ts, tm.clone()); - let span = om.span; - if let (Some((olo, ohi)), Some((tlo, thi))) = (bounds(r, os, &om), bounds(r, ts, &tm)) { - if olo < tlo || ohi > thi { - out.push(( - unit, - Diagnostic::warning( - span, - format!( - "redefining multiplicity [{}..{}] is not within \ - the redefined feature's [{}..{}]", - olo, ohi, tlo, thi - ), - ), - )); - } - } - } - let own_types = r.b.direct_typing_elems(owner); - if own_types.is_empty() { - continue; - } - for tt in r.b.direct_typing_elems(target) { - if tt < r.b.lib_boundary { - continue; // may conform via implied bases - } - if own_types.iter().any(|&ot| r.b.conforms_upward(ot, tt)) { - continue; - } - out.push(( - unit, - Diagnostic::warning( - qn.span, - format!( - "feature redefines `{}` but none of its declared types \ - conform to the target's type `{}`", - qn.to_display_string(), - r.b.elements[tt] - .props - .get("declaredName") - .and_then(|v| v.as_str()) - .unwrap_or("") - ), - ), - )); - } - } - - // --- invocation arity --- - // A user-defined calculation invoked with fewer positional arguments - // than its declared `in`/`inout` parameters leaves the trailing - // parameters unbound — the result can never compute unless they carry - // defaults. Warnings, conservatively scoped: all-positional calls - // only (named arguments bind explicitly), lambda bodies skipped, - // zero-argument spellings skipped (type-reference idioms), and both - // caller and callee must be outside the standard library (KFL - // functions overload their parameter lists). - let mut value_exprs: Vec<(usize, usize, sysmlv2_syntax::ast::Expr)> = - r.b.values - .iter() - .map(|(o, (s, e))| (*o, *s, e.clone())) - .collect(); - value_exprs.extend(r.b.result_exprs.iter().cloned()); - for (owner, scope, expr) in value_exprs { - let unit = r.b.unit_of_elem(owner); - if model.units()[unit].is_library { - continue; - } - let mut sites = Vec::new(); - collect_invocations(&expr, &mut sites); - for (qn, n_args, span) in sites { - if n_args == 0 { - continue; - } - let Some(callee) = r.b.resolve(scope, qn, 0) else { - continue; // unresolved refs are the referential checks' job - }; - let Some(params) = r.b.in_params.get(&callee).cloned() else { - continue; // not a parameterized calculation - }; - if model.units()[r.b.unit_of_elem(callee)].is_library { - continue; - } - // Over-application: more positional arguments than declared - // parameters can never bind (the arrow spelling passes its - // target as the first argument — `x->f(a)` supplies two). - if n_args > params.len() { - out.push(( - unit, - Diagnostic::warning( - span, - format!( - "invocation of `{}` supplies {n_args} arguments for {} parameter(s)", - qn.to_display_string(), - params.len(), - ), - ), - )); - continue; - } - if n_args == params.len() { - continue; - } - // Unbound trailing parameters that all carry their own - // (default) values are fine. - let fields = r.b.ctor_fields.get(&callee); - let all_defaulted = params[n_args..].iter().all(|p| { - fields - .and_then(|fs| fs.iter().find(|(n, _)| n == p)) - .map(|(_, e)| r.b.values.contains_key(e)) - .unwrap_or(false) - }); - if all_defaulted { - continue; - } - out.push(( - unit, - Diagnostic::warning( - span, - format!( - "invocation of `{}` binds {n_args} of its {} parameters \ - (`{}` never bound)", - qn.to_display_string(), - params.len(), - params[n_args..].join("`, `") - ), - ), - )); - } - } - - // --- feature-value scalar conformance --- - // Narrowed to what is provable. A stricter static rule — the value - // expression's *declared* result type must conform to the feature's - // declared type — would reject 15 official corpus files whose bindings - // are legal under KerML multiple classification: a `Rational`-typed - // literal's value may well inhabit a sibling subtype of `Real` - // (`ScalarValues::Rational does not conform to EnumerationTest::Size` - // is exactly the corpus's enum-restriction idiom, and the ISO-8601 - // string encodings and metadata levels follow the same shape). What - // *is* provable is kind-level disjointness of the evaluated value: - // `ScalarValues` partitions its scalars into Boolean, String, and the - // Number tower, and a value of one partition is never an instance of - // a type in another; within the tower, a non-integral rational is - // never an instance of an `Integer`-conforming type. Declared types - // classify by simple scalar names over the explicit supertype closure - // (the solver's `declared_sort` discipline — works with or without - // the standard library); an untyped redefining feature borrows the - // redefinition target's declared types (one hop). Unclassifiable - // declared types, unevaluable values, quantities, sequences, and - // element values all stay silent. Warnings, per checker policy. - let value_sites: Vec<(usize, usize, sysmlv2_syntax::ast::Expr)> = - r.b.values - .iter() - .map(|(o, (s, e))| (*o, *s, e.clone())) - .collect(); - for (owner, scope, expr) in value_sites { - let unit = r.b.unit_of_elem(owner); - if model.units()[unit].is_library { - continue; - } - let mut tys = r.b.direct_typing_elems(owner); - if tys.is_empty() { - for t in r.b.redefinition_target_elems(owner) { - for ty in r.b.direct_typing_elems(t) { - if !tys.contains(&ty) { - tys.push(ty); - } - } - } - } - // Every declared type must classify — a type this walk cannot - // place may admit the value through bases it cannot see. - let kinds: Vec = tys - .iter() - .filter_map(|&ty| declared_scalar_kind(&mut r.b, ty)) - .collect(); - if kinds.is_empty() || kinds.len() != tys.len() { - continue; - } - let Ok(v) = crate::eval::evaluate_expr_in(&mut r.b, scope, &expr) else { - continue; // undecided, not wrong - }; - let value_kind = match &v { - crate::eval::Value::Boolean(_) => ScalarKind::Boolean, - crate::eval::Value::String(_) => ScalarKind::Str, - crate::eval::Value::Integer(_) => ScalarKind::Number { integral: true }, - crate::eval::Value::Rational(f) => ScalarKind::Number { - integral: f.fract() == 0.0 && f.is_finite(), - }, - _ => continue, // quantities, sequences, instances, elements - }; - let admits = |decl: ScalarKind| match (decl, value_kind) { - (ScalarKind::Boolean, ScalarKind::Boolean) => true, - (ScalarKind::Str, ScalarKind::Str) => true, - (ScalarKind::Number { integral: need }, ScalarKind::Number { integral: have }) => { - !need || have - } - _ => false, // cross-partition: provably disjoint - }; - if kinds.iter().any(|&k| admits(k)) { - continue; - } - let ty_name = r.b.elements[tys[0]] - .props - .get("declaredName") - .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string(); - let msg = match value_kind { - ScalarKind::Number { integral: false } - if matches!(kinds[0], ScalarKind::Number { .. }) => - { - format!( - "feature value {v} is not an integer and can never conform \ - to the declared type `{ty_name}`" - ) - } - _ => { - let vdesc = match value_kind { - ScalarKind::Boolean => "a Boolean", - ScalarKind::Str => "a String", - ScalarKind::Number { .. } => "a number", - }; - format!( - "feature value evaluates to {vdesc}, which can never \ - conform to the declared type `{ty_name}`" - ) - } - }; - out.push((unit, Diagnostic::warning(expr.span, msg))); - } - - // --- connector binary specialization (KerML - // checkConnectorBinarySpecialization) --- - // A connector with more than two ends must not specialize a *binary* - // connector: binary means a library binary-links family element, or a - // user connector-family element with exactly two ends (the two-end - // shape implies the binary library base). The n-ary declaration - // itself is legal — the offending edge is the typing/subsetting/ - // redefinition that demands binariness, so the diagnostic lands on - // that target's spelling. - { - let connector_family = |ty: &str| { - matches!( - ty, - "ConnectionUsage" - | "ConnectionDefinition" - | "InterfaceUsage" - | "InterfaceDefinition" - | "AllocationUsage" - | "AllocationDefinition" - | "Connector" - | "BindingConnector" - ) - }; - let end_count = |b: &crate::json::Builder, e: usize| { - b.elements[e] - .owned_relationships - .iter() - .filter(|&&rel| b.elements[rel].ty == "EndFeatureMembership") - .count() - }; - // The library binary-links family, resolved once (absent without - // the library — the user-side two-end test still applies). - let mut binary_lib: HashSet = HashSet::new(); - for qn in [ - "Links::binaryLinks", - "Links::BinaryLink", - "Connections::binaryConnections", - "Connections::BinaryConnection", - "Interfaces::binaryInterfaces", - "Interfaces::BinaryInterface", - ] { - if let Some(t) = r.b.resolve(0, &crate::json::lib_qn(qn), 0) { - binary_lib.insert(t); - } - } - let is_binary_node = |b: &mut crate::json::Builder, - binary_lib: &HashSet, - n: usize| { - binary_lib.contains(&n) || (connector_family(b.elements[n].ty) && end_count(b, n) == 2) - }; - for (owner, kind, target, qn) in &resolved { - if !matches!(*kind, "FeatureTyping" | "Subsetting" | "Redefinition") { - continue; - } - if !connector_family(r.b.elements[*owner].ty) || end_count(&r.b, *owner) <= 2 { - continue; - } - // Binary directly, or anywhere up the target's explicit closure. - let mut binary = is_binary_node(&mut r.b, &binary_lib, *target); - if !binary { - let mut seen: HashSet = HashSet::new(); - let mut stack = vec![*target]; - while let Some(n) = stack.pop() { - if !seen.insert(n) { - continue; - } - if is_binary_node(&mut r.b, &binary_lib, n) { - binary = true; - break; - } - stack.extend(r.b.explicit_supertype_elems(n)); - } - } - if binary { - let ends = end_count(&r.b, *owner); - out.push(( - r.b.unit_of_elem(*owner), - Diagnostic::warning( - qn.span, - format!( - "connector with {ends} ends specializes a binary connector (a binary connector cannot have more than two ends)" - ), - ), - )); - } - } - } - - // --- chain-target subsetting featuring accessibility (KerML - // validateSubsettingFeaturingTypes, narrowed to chain-written - // targets) --- - // `part m :> a.b;` subsets a feature reached *through* `a`, so the - // chain's root fixes the featuring context: some owning type of the - // subsetting feature must conform to the root's featuring type, or - // the subsetted feature is not accessible from the subsetter - // (nesting the subsetter in a conforming type fixes it). Lenient on - // unresolved roots, package-owned roots (featured by Base::Anything, - // accessible anywhere), and library featuring — the connector-end - // precedent. - { - let is_type = |ty: &str| { - ty.ends_with("Definition") - || ty.ends_with("Usage") - || matches!( - ty, - "Classifier" - | "Structure" - | "Class" - | "DataType" - | "Behavior" - | "Function" - | "Association" - | "AssociationStructure" - | "Interaction" - | "Metaclass" - | "Feature" - | "Step" - ) - }; - let owning_type = |r: &mut crate::json::ResolvedModel, e: usize| -> Option { - let mut cur = r.owner(crate::json::ElementRef(e)); - while let Some(o) = cur { - let ty = r.element_type(o); - if is_type(ty) { - return Some(o.0); - } - if matches!(ty, "Package" | "LibraryPackage" | "Namespace") { - return None; - } - cur = r.owner(o); - } - None - }; - for (owner, scope, links, span) in r.b.chain_subsettings.clone() { - let unit = r.b.unit_of_elem(owner); - if model.units()[unit].is_library { - continue; - } - let Some(root) = r.b.resolve(scope, &links[0], 0) else { - continue; - }; - let Some(root_type) = owning_type(r, root) else { - continue; - }; - if root_type < r.b.lib_boundary { - continue; - } - let mut anc = owning_type(r, owner); - let mut ok = false; - while let Some(t) = anc { - if r.b.conforms_upward(t, root_type) { - ok = true; - break; - } - anc = owning_type(r, t); - } - if !ok { - let root_name = r.b.elements[root_type] - .props - .get("declaredName") - .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string(); - out.push(( - unit, - Diagnostic::warning( - span, - format!( - "subsetted feature chain is featured in `{root_name}`, which \ - no owner of the subsetting feature conforms to (nest the \ - subsetting feature in a type conforming to `{root_name}`)" - ), - ), - )); - } - } - } - - // --- connector-end featuring accessibility (KerML canAccess / - // checkConnectorTypeFeaturing) --- - // A connector's related features must share a featuring context the - // connector can be featured within. Statically: some candidate type T - // — a lexical ancestor of the connector, or a featuring type of one of - // the related features (or its ancestors) — must *admit* every - // featured related feature, where T admits a feature featured in F - // when T conforms to F or T (or a supertype) owns a member typed by / - // referencing something conforming to F (the one-hop featuring lift: - // a part that performs/exhibits a behavior gives access to the - // behavior's features). Package-owned targets have no featuringTypes - // and are accessible from anywhere — that is what makes the corpus's - // sibling-namespace binds legal. Lenient by construction: unresolved - // targets, library featuring, explicit `featured by`, and unresolved - // chain roots all pass silently. - { - let n = r.b.elements.len(); - let mut rel_owner: Vec> = vec![None; n]; - for (i, e) in r.b.elements.iter().enumerate() { - for &rel in &e.owned_relationships { - rel_owner[rel] = Some(i); - } - } - let mut owned_of_rel: Vec> = vec![Vec::new(); n]; - for (i, e) in r.b.elements.iter().enumerate() { - if let Some(rel) = e.owning_relationship { - owned_of_rel[rel].push(i); - } - } - let by_id: HashMap = (0..n).map(|i| (r.b.elem_id(i), i)).collect(); - let is_featuring_membership = |ty: &str| { - ty.ends_with("Membership") - && !matches!(ty, "OwningMembership" | "Membership" | "VariantMembership") - }; - let deref = |b: &crate::json::Builder, v: &serde_json::Value| { - v.get("@id") - .and_then(|v| v.as_str()) - .and_then(|s| uuid::Uuid::parse_str(s).ok()) - .and_then(|id| by_id.get(&id).copied()) - .map(|i| (i, b.elements[i].ty)) - }; - let _ = &deref; - let rel_target = |b: &crate::json::Builder, e: usize, rel_ty: &str, key: &str| { - b.elements[e] - .owned_relationships - .iter() - .find(|&&rel| b.elements[rel].ty == rel_ty) - .and_then(|&rel| b.elements[rel].props.get(key)) - .and_then(|v| v.get("@id")) - .and_then(|v| v.as_str()) - .and_then(|s| uuid::Uuid::parse_str(s).ok()) - .and_then(|id| by_id.get(&id).copied()) - }; - let has_type_featuring = |b: &crate::json::Builder, e: usize| { - b.elements[e] - .owned_relationships - .iter() - .any(|&rel| b.elements[rel].ty == "TypeFeaturing") - }; - // Group ends by connector. - let mut per_connector: HashMap> = - HashMap::new(); - let mut order: Vec = Vec::new(); - for (connector, end_elem, span) in r.b.connector_ends.clone() { - per_connector - .entry(connector) - .or_insert_with(|| { - order.push(connector); - Vec::new() - }) - .push((end_elem, span)); - } - for connector in order { - let unit = r.b.unit_of_elem(connector); - if model.units()[unit].is_library { - continue; - } - let ends = &per_connector[&connector]; - // Featured related features: (target, its featuring type, span). - let mut featured: Vec<(usize, usize, sysmlv2_syntax::span::Span)> = Vec::new(); - let mut lenient = false; - for &(end_elem, span) in ends { - let Some(mut target) = - rel_target(&r.b, end_elem, "ReferenceSubsetting", "referencedFeature") - else { - continue; // empty or unresolved end - }; - // A chain end's featuring is the first link's. - if let Some(link_v) = r.b.elements[target] - .owned_relationships - .iter() - .find(|&&rel| r.b.elements[rel].ty == "FeatureChaining") - .and_then(|&rel| r.b.elements[rel].props.get("chainingFeature")) - .cloned() - { - let Some(link) = link_v - .get("@id") - .and_then(|v| v.as_str()) - .and_then(|s| uuid::Uuid::parse_str(s).ok()) - .and_then(|id| by_id.get(&id).copied()) - else { - lenient = true; - break; - }; - target = link; - } - if model.units()[r.b.unit_of_elem(target)].is_library { - continue; - } - if has_type_featuring(&r.b, target) { - lenient = true; - break; - } - let f = match r.b.elements[target].owning_relationship { - Some(rel) if is_featuring_membership(r.b.elements[rel].ty) => rel_owner[rel], - _ => None, // namespace-owned: featured by Anything - }; - let Some(f) = f else { continue }; - if model.units()[r.b.unit_of_elem(f)].is_library { - continue; - } - featured.push((target, f, span)); - } - if lenient || featured.is_empty() { - continue; - } - // Candidate contexts: lexical ancestors of the connector - // (through any membership) plus each featuring type and its - // lexical ancestors. - let mut candidates: Vec = Vec::new(); - let push_chain = |b: &crate::json::Builder, start: usize, out: &mut Vec| { - let mut cur = start; - for _ in 0..64 { - if !out.contains(&cur) { - out.push(cur); - } - let Some(rel) = b.elements[cur].owning_relationship else { - break; - }; - let Some(owner) = rel_owner[rel] else { break }; - cur = owner; - } - }; - push_chain(&r.b, connector, &mut candidates); - for &(_, f, _) in &featured { - push_chain(&r.b, f, &mut candidates); - } - // T admits a feature featured in F when T conforms to F, or a - // member of T (or of a type T explicitly specializes) is typed - // by / references something conforming to F. - let mut admits_cache: HashMap<(usize, usize), bool> = HashMap::new(); - let mut admits = |r: &mut crate::json::ResolvedModel, t: usize, f: usize| -> bool { - if let Some(&hit) = admits_cache.get(&(t, f)) { - return hit; - } - let mut ok = t == f || r.b.conforms_upward(t, f); - if !ok { - // One-hop featuring lift over T's own supertype closure. - let mut types: Vec = vec![t]; - let mut qi = 0; - while qi < types.len() && types.len() <= 64 { - let cur = types[qi]; - qi += 1; - for s in r.b.explicit_supertype_elems(cur) { - if !types.contains(&s) { - types.push(s); - } - } - } - 'outer: for &ty_el in &types { - for &rel in &r.b.elements[ty_el].owned_relationships.clone() { - for &m in &owned_of_rel[rel].clone() { - for key in ["type", "referencedFeature"] { - let rel_ty = if key == "type" { - "FeatureTyping" - } else { - "ReferenceSubsetting" - }; - if let Some(g) = rel_target(&r.b, m, rel_ty, key) { - if g == f || r.b.conforms_upward(g, f) { - ok = true; - break 'outer; - } - } - } - } - } - } - } - admits_cache.insert((t, f), ok); - ok - }; - // Pick the candidate that admits the most related features; - // the finding names the first feature it cannot reach. - let mut best: Option<(usize, usize)> = None; // (admitted, cand idx) - for (i, &t) in candidates.iter().enumerate() { - let admitted = featured - .iter() - .filter(|&&(_, f, _)| admits(r, t, f)) - .count(); - if best.is_none_or(|(b, _)| admitted > b) { - best = Some((admitted, i)); - } - } - let accessible = best.is_some_and(|(a, _)| a == featured.len()); - if !accessible { - let best_t = candidates[best.map_or(0, |(_, i)| i)]; - let (target, f, span) = *featured - .iter() - .find(|&&(_, f, _)| !admits(r, best_t, f)) - .unwrap_or(&featured[0]); - let name = |e: usize| { - r.b.elements[e] - .props - .get("declaredName") - .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string() - }; - out.push(( - unit, - Diagnostic::warning( - span, - format!( - "connector end references `{}`, which is featured in \ - `{}` — no featuring context of the connector reaches \ - it", - name(target), - name(f), - ), - ), - )); - } - } - } - + out.extend(multiplicities::validate(r, model)); + out.extend(specialization::validate(r, model)); + out.extend(invocations::validate(r, model)); + out.extend(scalars::validate(r, model)); + out.extend(chains::validate(r, model)); + // The immutable facts already index ownership and binary relationship + // targets for every later validator. Reuse them for connector checks too. + let facts = facts::Facts::new(&mut r.b); + out.extend(connectors::validate(r, model, &facts)); + out.extend(structural::validate(r, model, &facts)); + out.extend(endpoints::validate(r, model, &facts)); + out.extend(values::validate(r, model, &facts)); + out.extend(relationships::validate(r, model, &facts)); + out.extend(expressions::validate(r, model, &facts)); + out.extend(actions::validate(r, model, &facts)); + out.extend(typing::validate(r, model)); + out.extend(dimensions::validate(r, model)); + out.extend(distinguishability::validate(r, model)); out.sort_by_key(|(unit, d)| (*unit, d.span.start)); out.dedup_by(|a, b| a.0 == b.0 && a.1.span == b.1.span && a.1.message == b.1.message); + r.b.used_imports = used_imports; out } -/// The provably-disjoint `ScalarValues` partitions: Boolean, String, and -/// the Number tower (with `Integer`-and-below tracked for integrality). -#[derive(Clone, Copy, PartialEq)] -enum ScalarKind { - Boolean, - Str, - Number { integral: bool }, -} - -/// Classify a declared type into its scalar partition by walking the -/// explicit typing/specialization closure and matching the `ScalarValues` -/// simple names — the same name-based discipline as the solver's -/// `declared_sort`, so it works with or without the standard library. -/// Breadth-first, first match wins: the nearest scalar ancestor decides -/// integrality (`Size :> Real` classifies non-integral even though `Real` -/// has integral subtypes). `None` = not provably a scalar type. -fn declared_scalar_kind(b: &mut crate::json::Builder, ty: usize) -> Option { - use std::collections::{HashSet, VecDeque}; - let mut queue: VecDeque = VecDeque::new(); - queue.push_back(ty); - let mut seen: HashSet = HashSet::new(); - let mut steps = 0; - while let Some(t) = queue.pop_front() { - if !seen.insert(t) { - continue; - } - steps += 1; - if steps > 64 { - break; - } - let name = b.elements[t] - .props - .get("declaredName") - .and_then(|v| v.as_str()); - match name { - Some("Boolean") => return Some(ScalarKind::Boolean), - Some("String") => return Some(ScalarKind::Str), - Some("Integer" | "Natural" | "Positive") => { - return Some(ScalarKind::Number { integral: true }); - } - Some("NumericalValue" | "Number" | "Complex" | "Real" | "Rational") => { - return Some(ScalarKind::Number { integral: false }); - } - _ => {} - } - for s in b.explicit_supertype_elems(t) { - queue.push_back(s); - } - } - None -} - -/// Collect every all-positional invocation site in an expression: -/// `(callee, positional-argument count, span)`. Lambda bodies (`Body`, -/// arrow/collect/select bodies) are not entered — their invocations -/// bind through runtime parameters this static pass cannot see. -fn collect_invocations<'a>( - e: &'a sysmlv2_syntax::ast::Expr, - out: &mut Vec<( - &'a sysmlv2_syntax::ast::QualifiedName, - usize, - sysmlv2_syntax::Span, - )>, -) { - use sysmlv2_syntax::ast::{ArrowArgs, ExprKind, TargetRef}; - match &e.kind { - ExprKind::Literal(_) - | ExprKind::Null - | ExprKind::Ref(_) - | ExprKind::Extent { .. } - | ExprKind::MetadataAccess { .. } - | ExprKind::Body { .. } - | ExprKind::BodyTerminator => {} - ExprKind::Conditional { - cond, - then_branch, - else_branch, - } => { - collect_invocations(cond, out); - collect_invocations(then_branch, out); - collect_invocations(else_branch, out); - } - ExprKind::Binary { lhs, rhs, .. } => { - collect_invocations(lhs, out); - collect_invocations(rhs, out); - } - ExprKind::Unary { operand, .. } => collect_invocations(operand, out), - ExprKind::Classification { operand, .. } => { - if let Some(o) = operand { - collect_invocations(o, out); - } - } - ExprKind::ChainStep { target, .. } => collect_invocations(target, out), - ExprKind::Index { target, index } => { - collect_invocations(target, out); - collect_invocations(index, out); - } - ExprKind::Bracket { target, arg } => { - collect_invocations(target, out); - collect_invocations(arg, out); - } - ExprKind::Arrow { target, args, .. } => { - collect_invocations(target, out); - if let ArrowArgs::List(list) = args { - for a in list { - collect_invocations(&a.value, out); - } - } - } - ExprKind::Collect { target, .. } | ExprKind::Select { target, .. } => { - collect_invocations(target, out) - } - ExprKind::Invocation { ty, args } => { - if let (TargetRef::Name(qn), true) = (ty, args.iter().all(|a| a.name.is_none())) { - out.push((qn, args.len(), e.span)); - } - for a in args { - collect_invocations(&a.value, out); - } - } - ExprKind::Constructor { args, .. } => { - for a in args { - collect_invocations(&a.value, out); - } - } - ExprKind::Sequence(items) => { - for i in items { - collect_invocations(i, out); - } - } - } -} - /// Collect every feature reference of an expression, in source order: /// the `Ref` leaves. Lambda bodies are not entered (their references /// bind through runtime parameters), and a bracket's unit expression is @@ -1273,9 +515,17 @@ pub fn constraint_bindings( }; // An unvalued feature evaluates to itself as a bare element, // which renders opaquely (``) — that is the unbound - // case for diagnostic purposes, not a value worth showing. + // case for diagnostic purposes, not a value worth showing. A + // reference *through* an unbound feature is undetermined for the + // same reason and renders just as opaquely (``). let value = match r.evaluate_in(c.scope, &probe) { - Ok(crate::eval::Value::Element(_) | crate::eval::Value::Unbound(_)) | Err(_) => None, + Ok( + crate::eval::Value::Element(_) + | crate::eval::Value::Unbound(_) + | crate::eval::Value::UnboundMember(_) + | crate::eval::Value::Indeterminate, + ) + | Err(_) => None, Ok(v) => Some(v.to_string()), }; out.push(ConstraintBinding { @@ -1334,7 +584,7 @@ pub fn check_constraints(model: &crate::model::Model) -> Vec { let mut r = crate::json::ResolvedModel::build(model); let mut out = Vec::new(); for c in r.constraints() { - if model.units()[c.unit].is_library { + if model.is_library_unit(c.unit) { continue; } let verdict = constraint_verdict(&mut r, &c); @@ -1372,7 +622,7 @@ pub fn satisfaction_checks( let mut out = Vec::new(); for s in r.satisfactions() { for c in &s.constraints { - if model.units()[c.unit].is_library { + if model.is_library_unit(c.unit) { continue; } let verdict = match r.evaluate_in_with(c.scope, &c.expr, &s.overrides) { @@ -1428,3 +678,56 @@ pub fn constraint_verdict( Err(e) => ConstraintVerdict::Undecided(e.to_string()), } } + +#[cfg(test)] +mod tests { + use crate::{json::ResolvedModel, model::Model}; + + const LIBRARY: &str = "package L { + class A; + class B :> A; + feature n : A [1..2] = 1; + feature m : B [0..1] :> n; + function f { in x : A; return x; } + }"; + const USER: &str = "package U { + feature a : L::A [2..1]; + feature b :> L::n = 2; + }"; + + fn findings(model: &Model) -> Vec<(usize, String)> { + let mut r = ResolvedModel::build(model); + let before = crate::layered::copied_rows(); + let out = super::validate_semantics_with(&mut r, model); + assert_eq!( + crate::layered::copied_rows(), + before, + "a semantic pass must not copy any builder table" + ); + out.into_iter().map(|(u, d)| (u, d.message)).collect() + } + + #[test] + fn semantic_checks_walk_tables_without_copying_them() { + // Fresh build: library rows and user rows share one storage. + let mut cold = Model::new(); + cold.add_library_source("lib.kerml", LIBRARY); + cold.add_source("user.kerml", USER); + let cold_findings = findings(&cold); + assert!( + cold_findings + .iter() + .any(|(_, m)| m.contains("lower bound 2 exceeds upper bound 1")), + "{cold_findings:?}" + ); + // Prepared build: the library rows are a shared prefix. + let mut base = Model::new(); + base.add_library_source("lib.kerml", LIBRARY); + let prepared = base.prepare_library().unwrap(); + let mut warm = Model::new(); + prepared.install(&mut warm).unwrap(); + warm.add_source("user.kerml", USER); + assert!(ResolvedModel::build(&warm).b.library_facts.is_some()); + assert_eq!(findings(&warm), cold_findings); + } +} diff --git a/crates/sysmlv2-model/src/check/actions.rs b/crates/sysmlv2-model/src/check/actions.rs new file mode 100644 index 0000000..334cec2 --- /dev/null +++ b/crates/sysmlv2-model/src/check/actions.rs @@ -0,0 +1,312 @@ +//! Static action/state graph checks. No scheduling or behavioral execution. +use super::{ + expressions, + facts::{Facts, flag, is}, +}; +use crate::{ + json::{ElementRef, ResolvedModel}, + model::Model, +}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate( + r: &mut ResolvedModel, + model: &Model, + g: &Facts, +) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + let n = r.b.explicit_len(); + let mut incoming = vec![0; n]; + let mut outgoing = vec![0; n]; + let mut edges = Vec::new(); + for e in 0..n { + if !is(&r.b, e, "Succession") { + continue; + } + let ends: Vec<_> = g.members[e] + .iter() + .copied() + .filter(|&m| flag(&r.b, m, "isEnd")) + .collect(); + let [from, to] = ends.as_slice() else { + continue; + }; + let a = g.feature_target(&r.b, *from); + let z = g.feature_target(&r.b, *to); + let a = if a == *from { + g.owner[e] + .filter(|&p| is(&r.b, p, "TransitionUsage")) + .and_then(|p| { + g.relations(&r.b, p, "Membership", "memberElement") + .first() + .copied() + }) + } else { + Some(a) + }; + if let Some(a) = a { + if z != *to { + incoming[z] += 1; + outgoing[a] += 1; + edges.push((e, a, z, *from, *to)); + } + } + if let Some(t) = g.owner[e].filter(|&p| is(&r.b, p, "TransitionUsage")) { + let unit = r.b.unit_of_elem(t); + if !model.is_library_unit(unit) && z != *to && !g.effective_kind(&r.b, z, "ActionUsage") + { + out.push(( + unit, + super::rule_error( + g.span(&r.b, t), + "validateTransitionUsageSuccession", + "A transition's succession must target an action usage", + ), + )); + } + } + } + for (edge, a, z, from, to) in edges { + let unit = r.b.unit_of_elem(edge); + if model.is_library_unit(unit) { + continue; + } + for (end, required, rule) in [ + ( + to, + (1.0, 1.0), + is(&r.b, z, "ControlNode").then_some("validateControlNodeIncomingSuccessions"), + ), + ( + from, + (1.0, 1.0), + is(&r.b, a, "ControlNode").then_some("validateControlNodeOutgoingSuccessions"), + ), + ( + from, + (0.0, 1.0), + is(&r.b, z, "MergeNode").then_some("validateMergeNodeIncomingSuccessions"), + ), + ( + to, + (0.0, 1.0), + is(&r.b, a, "DecisionNode").then_some("validateDecisionNodeOutgoingSuccessions"), + ), + ] { + if let Some(rule) = rule { + if r.declared_multiplicity(ElementRef(end)) + .is_some_and(|m| m != required) + { + out.push(( + unit, + super::rule_error( + g.span(&r.b, edge), + rule, + format!( + "Succession end must have multiplicity {}..{}", + required.0, required.1 + ), + ), + )); + } + } + } + } + for e in 0..n { + let unit = r.b.unit_of_elem(e); + if model.is_library_unit(unit) { + continue; + } + let span = g.span(&r.b, e); + for (bad, rule) in [ + ( + is(&r.b, e, "ForkNode") && incoming[e] > 1, + "validateForkNodeIncomingSuccessions", + ), + ( + is(&r.b, e, "DecisionNode") && incoming[e] > 1, + "validateDecisionNodeIncomingSuccessions", + ), + ( + is(&r.b, e, "JoinNode") && outgoing[e] > 1, + "validateJoinNodeOutgoingSuccessions", + ), + ( + is(&r.b, e, "MergeNode") && outgoing[e] > 1, + "validateMergeNodeOutgoingSuccessions", + ), + ] { + if bad { + out.push(( + unit, + super::rule_error( + span, + rule, + format!( + "Control node has too many {} successions", + if rule.contains("Incoming") { + "incoming" + } else { + "outgoing" + } + ), + ), + )); + } + } + if is(&r.b, e, "TransitionUsage") { + let triggered = r.b.elements[e].owned_relationships.iter().any(|&rel| { + is(&r.b, rel, "TransitionFeatureMembership") + && r.b.elements[rel].props.get("kind").and_then(|x| x.as_str()) + == Some("trigger") + }); + if triggered + && g.relations(&r.b, e, "Membership", "memberElement") + .iter() + .any(|&s| !g.effective_kind(&r.b, s, "StateUsage")) + { + out.push(( + unit, + super::rule_error( + span, + "validateTransitionUsageTriggerActions", + "A triggered transition must have a state usage as its source", + ), + )); + } + } + let params: Vec<_> = g.members[e] + .iter() + .copied() + .filter(|&m| { + r.b.elements[m] + .owning_relationship + .is_some_and(|rel| is(&r.b, rel, "ParameterMembership")) + }) + .collect(); + if is(&r.b, e, "AssignmentActionUsage") { + if let Some((scope, expr)) = params + .first() + .and_then(|p| r.b.contract_exprs.get(p)) + .cloned() + { + if let Some(t) = expressions::referent(&mut r.b, scope, &expr) { + let rule = if !is(&r.b, t, "Feature") { + Some(( + "validateAssignmentActionUsageReferent", + "An assignment must refer to a feature", + )) + } else if !super::structural::variable(&r.b, g, t) { + Some(( + "validateAssignmentActionUsageReferentIsTimeVarying", + "An assignment referent must be time varying", + )) + } else { + None + }; + if let Some((rule, msg)) = rule { + out.push((unit, super::rule_error(expr.span, rule, msg))); + } + } + } + } + if is(&r.b, e, "SendActionUsage") { + let needs_payload = r.b.elements[e].owning_relationship.is_some_and(|rel| { + is(&r.b, rel, "StateSubactionMembership") + || is(&r.b, rel, "TransitionFeatureMembership") + }); + if needs_payload + && params + .first() + .is_some_and(|p| !r.b.contract_exprs.contains_key(p)) + { + out.push((unit, super::rule_error(span, "validateSendActionUsagePayloadArgument", "A send used as a state subaction or transition effect must supply a payload"))); + } + if let Some((scope, expr)) = params + .get(2) + .and_then(|p| r.b.contract_exprs.get(p)) + .cloned() + { + if expressions::referent(&mut r.b, scope, &expr) + .is_some_and(|t| g.effective_kind(&r.b, t, "PortUsage")) + { + out.push(( + unit, + super::rule_warning( + expr.span, + "validateSendActionUsageReceiver", + "Sending through a port should use 'via'", + ), + )); + } + } + } + if is(&r.b, e, "TriggerInvocationExpression") { + let kind = r.b.elements[e] + .props + .get("kind") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_owned(); + let Some((scope, expr)) = r.b.contract_exprs.get(&e).cloned() else { + continue; + }; + let (required, rule) = match kind.as_str() { + "after" => ( + "ISQ::DurationValue", + "validateTriggerInvocationActionAfterArgument", + ), + "at" => ( + "Time::TimeInstantValue", + "validateTriggerInvocationActionAtArgument", + ), + "when" => ( + "ScalarValues::Boolean", + "validateTriggerInvocationActionWhenArgument", + ), + _ => continue, + }; + let mut bad = expressions::wrong_type(&mut r.b, g, scope, &expr, required); + if kind == "after" { + if let Some(t) = expressions::library_type(&mut r.b, required) { + if let (Some(actual), Some(expected)) = ( + super::dimensions::known(r, scope, &expr), + r.quantity_dims_of_type(ElementRef(t)), + ) { + bad |= actual != expected; + } + } + } + if bad { + out.push(( + unit, + super::rule_error( + expr.span, + rule, + format!("A '{kind}' trigger argument must conform to {required}"), + ), + )); + } + } + } + for (e, (scope, expr)) in super::user_entries(&r.b, model, r.b.transition_guards.iter()) { + let unit = r.b.unit_of_elem(e); + let mut bad = expressions::wrong_type(&mut r.b, g, scope, &expr, "ScalarValues::Boolean"); + if let Some(t) = expressions::referent(&mut r.b, scope, &expr) { + bad |= r + .declared_multiplicity(ElementRef(t)) + .is_some_and(|m| m != (1.0, 1.0)); + } + if bad { + out.push(( + unit, + super::rule_error( + expr.span, + "validateTransitionFeatureMembershipGuardExpression", + "A transition guard must have a Boolean result with multiplicity 1..1", + ), + )); + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/chains.rs b/crates/sysmlv2-model/src/check/chains.rs new file mode 100644 index 0000000..fc9b84a --- /dev/null +++ b/crates/sysmlv2-model/src/check/chains.rs @@ -0,0 +1,105 @@ +//! Featuring accessibility of a chain-written subsetting target: the +//! chain's root fixes the featuring context, so some owning type of the +//! subsetting feature must conform to it. +use crate::{json::ResolvedModel, model::Model}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // --- chain-target subsetting featuring accessibility (KerML + // validateSubsettingFeaturingTypes, narrowed to chain-written + // targets) --- + // `part m :> a.b;` subsets a feature reached *through* `a`, so the + // chain's root fixes the featuring context: some owning type of the + // subsetting feature must conform to the root's featuring type, or + // the subsetted feature is not accessible from the subsetter + // (nesting the subsetter in a conforming type fixes it). Lenient on + // unresolved roots, package-owned roots (featured by Base::Anything, + // accessible anywhere), and library featuring — the connector-end + // precedent. + { + let is_type = |ty: &str| { + ty.ends_with("Definition") + || ty.ends_with("Usage") + || matches!( + ty, + "Classifier" + | "Structure" + | "Class" + | "DataType" + | "Behavior" + | "Function" + | "Association" + | "AssociationStructure" + | "Interaction" + | "Metaclass" + | "Feature" + | "Step" + ) + }; + let owning_type = |r: &mut crate::json::ResolvedModel, e: usize| -> Option { + let mut cur = r.owner(crate::json::ElementRef(e)); + while let Some(o) = cur { + let ty = r.element_type(o); + if is_type(ty) { + return Some(o.0); + } + if matches!(ty, "Package" | "LibraryPackage" | "Namespace") { + return None; + } + cur = r.owner(o); + } + None + }; + let sites: Vec<_> = + r.b.chain_subsettings + .iter() + .filter(|row| !model.is_library_unit(r.b.unit_of_elem(row.0))) + .cloned() + .collect(); + for (owner, scope, links, span) in sites { + let unit = r.b.unit_of_elem(owner); + if model.is_library_unit(unit) { + continue; + } + let Some(root) = r.b.resolve(scope, &links[0], 0) else { + continue; + }; + let Some(root_type) = owning_type(r, root) else { + continue; + }; + if root_type < r.b.lib_boundary { + continue; + } + let mut anc = owning_type(r, owner); + let mut ok = false; + while let Some(t) = anc { + if r.b.conforms_upward(t, root_type) { + ok = true; + break; + } + anc = owning_type(r, t); + } + if !ok { + let root_name = r.b.elements[root_type] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + out.push(( + unit, + Diagnostic::warning( + span, + format!( + "subsetted feature chain is featured in `{root_name}`, which \ + no owner of the subsetting feature conforms to (nest the \ + subsetting feature in a type conforming to `{root_name}`)" + ), + ), + )); + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/connectors.rs b/crates/sysmlv2-model/src/check/connectors.rs new file mode 100644 index 0000000..641c856 --- /dev/null +++ b/crates/sysmlv2-model/src/check/connectors.rs @@ -0,0 +1,226 @@ +//! Featuring accessibility of a connector's related features: some +//! candidate context — a lexical ancestor of the connector, or a +//! featuring type of one of the related features — must admit every one +//! of them. +use super::facts::Facts; +use crate::{json::ResolvedModel, model::Model}; +use std::collections::HashMap; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate( + r: &mut ResolvedModel, + model: &Model, + facts: &Facts, +) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // --- connector-end featuring accessibility (KerML canAccess / + // checkConnectorTypeFeaturing) --- + // A connector's related features must share a featuring context the + // connector can be featured within. Statically: some candidate type T + // — a lexical ancestor of the connector, or a featuring type of one of + // the related features (or its ancestors) — must *admit* every + // featured related feature, where T admits a feature featured in F + // when T conforms to F or T (or a supertype) owns a member typed by / + // referencing something conforming to F (the one-hop featuring lift: + // a part that performs/exhibits a behavior gives access to the + // behavior's features). Package-owned targets have no featuringTypes + // and are accessible from anywhere — that is what makes the corpus's + // sibling-namespace binds legal. Lenient by construction: unresolved + // targets, library featuring, explicit `featured by`, and unresolved + // chain roots all pass silently. + { + let is_featuring_membership = |ty: &str| { + ty.ends_with("Membership") + && !matches!(ty, "OwningMembership" | "Membership" | "VariantMembership") + }; + let rel_target = |b: &crate::json::Builder, e: usize, rel_ty: &str, key: &str| { + b.elements[e] + .owned_relationships + .iter() + .find(|&&rel| b.elements[rel].ty == rel_ty) + .and_then(|&rel| facts.target(b, rel, key)) + }; + let has_type_featuring = |b: &crate::json::Builder, e: usize| { + b.elements[e] + .owned_relationships + .iter() + .any(|&rel| b.elements[rel].ty == "TypeFeaturing") + }; + // Group ends by connector. + let mut per_connector: HashMap> = + HashMap::new(); + let mut order: Vec = Vec::new(); + for &(connector, end_elem, span) in + r.b.connector_ends + .iter() + .filter(|row| !model.is_library_unit(r.b.unit_of_elem(row.0))) + { + per_connector + .entry(connector) + .or_insert_with(|| { + order.push(connector); + Vec::new() + }) + .push((end_elem, span)); + } + for connector in order { + let unit = r.b.unit_of_elem(connector); + if model.is_library_unit(unit) { + continue; + } + let ends = &per_connector[&connector]; + // Featured related features: (target, its featuring type, span). + let mut featured: Vec<(usize, usize, sysmlv2_syntax::span::Span)> = Vec::new(); + let mut lenient = false; + for &(end_elem, span) in ends { + let Some(mut target) = + rel_target(&r.b, end_elem, "ReferenceSubsetting", "referencedFeature") + else { + continue; // empty or unresolved end + }; + // A chain end's featuring is the first link's. + if let Some(&rel) = r.b.elements[target] + .owned_relationships + .iter() + .find(|&&rel| r.b.elements[rel].ty == "FeatureChaining") + .filter(|&&rel| r.b.elements[rel].props.get("chainingFeature").is_some()) + { + let Some(link) = facts.target(&r.b, rel, "chainingFeature") else { + lenient = true; + break; + }; + target = link; + } + if model.is_library_unit(r.b.unit_of_elem(target)) { + continue; + } + if has_type_featuring(&r.b, target) { + lenient = true; + break; + } + let f = match r.b.elements[target].owning_relationship { + Some(rel) if is_featuring_membership(r.b.elements[rel].ty) => facts.owner[rel], + _ => None, // namespace-owned: featured by Anything + }; + let Some(f) = f else { continue }; + if model.is_library_unit(r.b.unit_of_elem(f)) { + continue; + } + featured.push((target, f, span)); + } + if lenient || featured.is_empty() { + continue; + } + // Candidate contexts: lexical ancestors of the connector + // (through any membership) plus each featuring type and its + // lexical ancestors. + let mut candidates: Vec = Vec::new(); + let push_chain = |b: &crate::json::Builder, start: usize, out: &mut Vec| { + let mut cur = start; + for _ in 0..64 { + if !out.contains(&cur) { + out.push(cur); + } + let Some(rel) = b.elements[cur].owning_relationship else { + break; + }; + let Some(owner) = facts.owner[rel] else { break }; + cur = owner; + } + }; + push_chain(&r.b, connector, &mut candidates); + for &(_, f, _) in &featured { + push_chain(&r.b, f, &mut candidates); + } + // T admits a feature featured in F when T conforms to F, or a + // member of T (or of a type T explicitly specializes) is typed + // by / references something conforming to F. + let mut admits_cache: HashMap<(usize, usize), bool> = HashMap::new(); + let mut admits = |r: &mut crate::json::ResolvedModel, t: usize, f: usize| -> bool { + if let Some(&hit) = admits_cache.get(&(t, f)) { + return hit; + } + let mut ok = t == f || r.b.conforms_upward(t, f); + if !ok { + // One-hop featuring lift over T's own supertype closure. + let mut types: Vec = vec![t]; + let mut qi = 0; + while qi < types.len() && types.len() <= 64 { + let cur = types[qi]; + qi += 1; + for s in r.b.explicit_supertype_elems(cur) { + if !types.contains(&s) { + types.push(s); + } + } + } + 'outer: for &ty_el in &types { + for ri in 0..r.b.elements[ty_el].owned_relationships.len() { + let rel = r.b.elements[ty_el].owned_relationships[ri]; + for mi in 0..r.b.elements[rel].children.len() { + let m = r.b.elements[rel].children[mi]; + for key in ["type", "referencedFeature"] { + let rel_ty = if key == "type" { + "FeatureTyping" + } else { + "ReferenceSubsetting" + }; + if let Some(g) = rel_target(&r.b, m, rel_ty, key) { + if g == f || r.b.conforms_upward(g, f) { + ok = true; + break 'outer; + } + } + } + } + } + } + } + admits_cache.insert((t, f), ok); + ok + }; + // Pick the candidate that admits the most related features; + // the finding names the first feature it cannot reach. + let mut best: Option<(usize, usize)> = None; // (admitted, cand idx) + for (i, &t) in candidates.iter().enumerate() { + let admitted = featured + .iter() + .filter(|&&(_, f, _)| admits(r, t, f)) + .count(); + if best.is_none_or(|(b, _)| admitted > b) { + best = Some((admitted, i)); + } + } + let accessible = best.is_some_and(|(a, _)| a == featured.len()); + if !accessible { + let best_t = candidates[best.map_or(0, |(_, i)| i)]; + let (target, f, span) = *featured + .iter() + .find(|&&(_, f, _)| !admits(r, best_t, f)) + .unwrap_or(&featured[0]); + let name = |e: usize| { + r.b.elements[e] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string() + }; + out.push(( + unit, + Diagnostic::warning( + span, + format!( + "connector end references `{}`, which is featured in \ + `{}` — no featuring context of the connector reaches \ + it", + name(target), + name(f), + ), + ), + )); + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/dimensions.rs b/crates/sysmlv2-model/src/check/dimensions.rs new file mode 100644 index 0000000..517fd07 --- /dev/null +++ b/crates/sysmlv2-model/src/check/dimensions.rs @@ -0,0 +1,311 @@ +//! Conservative dimensional inference for arithmetic over unbound quantities. +//! Unknown types stay unknown; no runtime value is invented to type-check an +//! expression. The existing quantity library supplies the dimension algebra. + +use crate::{ + eval::{self, Value}, + json::{ElementRef, ResolvedModel}, + model::Model, + quantity::QuantityDims, +}; +use std::collections::HashMap; +use sysmlv2_syntax::{Span, ast::*, diag::Diagnostic}; + +#[derive(Clone)] +enum Dimension { + Known(QuantityDims), + Zero, + Unknown, +} + +pub(super) fn known(r: &mut ResolvedModel, scope: usize, expr: &Expr) -> Option { + let mut infer = Inference { + model: r, + features: HashMap::new(), + types: HashMap::new(), + units: HashMap::new(), + findings: Vec::new(), + }; + match infer.expr(scope, expr) { + Dimension::Known(d) => Some(d), + _ => None, + } +} + +struct Inference<'a> { + model: &'a mut ResolvedModel, + features: HashMap, + types: HashMap, + units: HashMap, Dimension>, + findings: Vec<(Span, String)>, +} + +impl Inference<'_> { + fn feature(&mut self, e: usize) -> Dimension { + if let Some(d) = self.features.get(&e) { + return d.clone(); + } + // Also cuts recursive derived values and recursive type relationships. + self.features.insert(e, Dimension::Unknown); + let mut result = Dimension::Unknown; + for ty in self.model.b.direct_typing_elems(e) { + let dimension = if let Some(d) = self.types.get(&ty) { + d.clone() + } else { + let d = if crate::metaclass::conforms(self.model.b.elements[ty].ty, "DataType") { + if let Some(d) = self.model.quantity_dims_of_type(ElementRef(ty)) { + Dimension::Known(d) + } else { + // Real/Integer are not a proof of dimension one: + // quantity value types specialize the numeric tower. + // Only a measurement reference or an actual numeric + // value establishes a dimension here. + Dimension::Unknown + } + } else { + Dimension::Unknown + }; + self.types.insert(ty, d.clone()); + d + }; + if matches!(dimension, Dimension::Known(_)) { + result = dimension; + break; + } + } + if matches!(result, Dimension::Unknown) { + for base in self.model.b.explicit_specialization_elems(e) { + if matches!(base.0, "Subsetting" | "Redefinition") { + let d = self.feature(base.1); + if matches!(d, Dimension::Known(_)) { + result = d; + break; + } + } + } + } + if matches!(result, Dimension::Unknown) { + if let Some((scope, expr)) = self.model.b.values.get(&e).cloned() { + // Diagnostics belong to the value's own traversal, not every + // reference to it in a different file. + let before = self.findings.len(); + let d = self.expr(scope, &expr); + self.findings.truncate(before); + result = d; + } + } + self.features.insert(e, result.clone()); + result + } + + fn compatible(&mut self, left: Dimension, right: Dimension, span: Span) -> Dimension { + match (left, right) { + (Dimension::Known(a), Dimension::Known(b)) => { + if a != b { + self.findings.push(( + span, + format!( + "expression combines incompatible quantity dimensions `{}` and `{}`", + a.render(self.model), + b.render(self.model) + ), + )); + Dimension::Unknown + } else { + Dimension::Known(a) + } + } + (d, Dimension::Zero) | (Dimension::Zero, d) => d, + _ => Dimension::Unknown, + } + } + + fn target(&mut self, scope: usize, expr: &Expr) -> Option { + match &expr.kind { + ExprKind::Ref(qn) => self.model.b.resolve(scope, qn, 0), + ExprKind::ChainStep { + target, + member: TargetRef::Name(qn), + } => { + let target = self.target(scope, target)?; + self.model + .member_of(ElementRef(target), qn) + .map(|(e, _)| e.0) + } + _ => None, + } + } + + fn expr(&mut self, scope: usize, expr: &Expr) -> Dimension { + use BinaryOp as B; + use Dimension as D; + use ExprKind as E; + match &expr.kind { + E::Literal(Literal::Integer(_) | Literal::Real(_)) => { + match eval::evaluate_expr_in(&mut self.model.b, scope, expr) { + // A literal `0.0` canonicalizes to the integer arm; the + // double arm covers a computed approximate zero. + Ok(Value::Integer(0)) => D::Zero, + Ok(Value::Real(0.0)) => D::Zero, + _ => D::Known(QuantityDims::dimensionless()), + } + } + E::Ref(_) | E::ChainStep { .. } => self + .target(scope, expr) + .map_or(D::Unknown, |e| self.feature(e)), + E::Unary { + operand, + op: UnaryOp::Plus | UnaryOp::Minus, + } => self.expr(scope, operand), + E::Binary { op, lhs, rhs } => { + let a = self.expr(scope, lhs); + let b = self.expr(scope, rhs); + match op { + B::Add | B::Sub | B::Rem => self.compatible(a, b, expr.span), + B::Eq | B::NotEq | B::Lt | B::Gt | B::LtEq | B::GtEq => { + self.compatible(a, b, expr.span); + D::Unknown + } + B::Mul | B::Div => match (a, b) { + (D::Known(a), D::Known(b)) => { + a.product(&b, *op == B::Div).map_or(D::Unknown, D::Known) + } + (D::Zero, _) | (_, D::Zero) => D::Zero, + _ => D::Unknown, + }, + B::Pow | B::Caret => { + let exponent = match eval::evaluate_expr_in(&mut self.model.b, scope, rhs) { + Ok(Value::Integer(n)) => i32::try_from(n).ok(), + _ => None, + }; + match (a, exponent) { + (D::Known(a), Some(n)) => a.pow(n).map_or(D::Unknown, D::Known), + _ => D::Unknown, + } + } + _ => D::Unknown, + } + } + E::Bracket { target, arg } => { + self.expr(scope, target); + let unit_probe = Expr { + span: expr.span, + kind: E::Bracket { + target: Box::new(Expr { + span: target.span, + kind: E::Literal(Literal::Integer("1".into())), + }), + arg: arg.clone(), + }, + }; + match eval::evaluate_expr_in(&mut self.model.b, scope, &unit_probe) { + Ok(Value::Quantity(_, unit)) => { + // Measurement dimensions depend on resolved bases and + // exponents, not magnitude, scale, or display spelling. + // Repeated unit literals must not rewalk their library + // power-factor declarations for every occurrence. + let key: Vec<_> = + unit.dims.iter().map(|d| (d.elem, d.num, d.den)).collect(); + if let Some(d) = self.units.get(&key) { + d.clone() + } else { + let d = self + .model + .unit_quantity_dims(&unit) + .map_or(D::Unknown, D::Known); + self.units.insert(key, d.clone()); + d + } + } + _ => D::Unknown, + } + } + E::Conditional { + cond, + then_branch, + else_branch, + } => { + self.expr(scope, cond); + // A constant guard has only one reachable branch. Otherwise + // branches may legitimately be a union of differently-typed + // values: do not require their dimensions to agree. + match eval::evaluate_expr_in(&mut self.model.b, scope, cond) { + Ok(Value::Boolean(true)) => self.expr(scope, then_branch), + Ok(Value::Boolean(false)) => self.expr(scope, else_branch), + _ => { + let a = self.expr(scope, then_branch); + let b = self.expr(scope, else_branch); + match (a, b) { + (D::Known(a), D::Known(b)) if a == b => D::Known(a), + _ => D::Unknown, + } + } + } + } + E::Invocation { args, .. } | E::Constructor { args, .. } => { + for arg in args { + self.expr(scope, &arg.value); + } + D::Unknown + } + E::Sequence(items) => { + for item in items { + self.expr(scope, item); + } + D::Unknown + } + E::Index { target, index } => { + self.expr(scope, index); + self.expr(scope, target) + } + E::Unary { operand, .. } => { + self.expr(scope, operand); + D::Unknown + } + // Lambda bodies need their own parameter scope. Unmodelled + // operators are deliberately unknown rather than guessed. + _ => D::Unknown, + } + } +} + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + if r.resolve_qualified("Quantities::QuantityValue").is_none() { + return Vec::new(); + } + let mut sites: Vec<_> = + r.b.values + .iter() + .filter(|(e, _)| !model.is_library_unit(r.b.unit_of_elem(**e))) + .map(|(&e, (s, x))| (e, *s, x.clone())) + .collect(); + sites.extend( + r.b.result_exprs + .iter() + .filter(|row| !model.is_library_unit(r.b.unit_of_elem(row.0))) + .cloned(), + ); + sites.sort_by_key(|(e, _, x)| (*e, x.span.start)); + let mut infer = Inference { + model: r, + features: HashMap::new(), + types: HashMap::new(), + units: HashMap::new(), + findings: Vec::new(), + }; + let mut out = Vec::new(); + for (owner, scope, expr) in sites { + let unit = infer.model.b.unit_of_elem(owner); + if model.is_library_unit(unit) { + continue; + } + infer.expr(scope, &expr); + out.extend( + infer + .findings + .drain(..) + .map(|(span, message)| (unit, Diagnostic::warning(span, message))), + ); + } + out +} diff --git a/crates/sysmlv2-model/src/check/distinguishability.rs b/crates/sysmlv2-model/src/check/distinguishability.rs new file mode 100644 index 0000000..c42c16f --- /dev/null +++ b/crates/sysmlv2-model/src/check/distinguishability.rs @@ -0,0 +1,617 @@ +//! Namespace distinguishability over inherited members — KerML +//! `validateNamespaceDistinguishibility` (the rule name as the pinned XMI +//! spells it): every membership of a namespace must be distinguishable +//! from every other, inherited memberships included. The syntax stage +//! already checks a namespace's *owned* members against each other; this +//! pass adds the two inherited shapes for user types: +//! +//! - an owned member reusing an inherited member's name (or short name) +//! without redefining or subsetting it — `part def Leaf :> Mid { part +//! portions; }` against `Mid`'s `portions`; +//! - a type inheriting one name from two places at once — a usage typed by +//! `Leaf` above inherits both `portions`, or two unrelated bases each +//! supply a same-named feature neither redefines. +//! +//! The candidate set is the resolver's own inherited-member enumeration +//! (`Builder::inherited_bindings`, implied library bases included), whose +//! removal pass already applies KerML `removeRedefinedFeatures`. The one +//! removal that is *not* normative — a same-named usage-family member +//! shadowing an inherited one because its owner conforms — is recorded by +//! that pass as an implicit redefinition; lookup keeps honoring it (it is +//! what makes `downlinkPort` resolve unambiguously inside the subclass), +//! and this check reports it as the collision the reference validator +//! reports. Both shapes are warnings, the reference validator's severity +//! for inherited collisions (the owned-member collision the syntax stage +//! reports is an error there too). +//! +//! Equal names are legal when the two member elements' metaclasses do not +//! conform either way (KerML `Membership::isDistinguishableFrom`); the +//! check reads that from the generated metaclass hierarchy. Names are the +//! members' declared names and short names, or the effective name of an +//! unnamed redefinition (`attribute :>> x` binds `x`). Alias memberships +//! are not enumerated on either side: an owned `alias` against an +//! inherited name stays unreported here. The enumerations this pass asks +//! for stay memoized on the builder, so a long-lived host pays for them +//! once and its later inherited-member queries reuse them. +use std::{ + borrow::Cow, + collections::{BTreeMap, HashSet}, +}; + +use crate::{ + json::{Builder, ElementRef, ResolvedModel}, + metaclass::conforms, + model::Model, +}; +use sysmlv2_syntax::{Span, diag::Diagnostic}; + +const RULE: &str = "validateNamespaceDistinguishibility"; + +/// One inherited-name collision — the semantic check's finding, exposed +/// for repairs that spell the missing redefinition. +#[derive(Clone, Debug)] +pub struct InheritedNameCollision { + /// The owned member reusing an inherited name, or (when `hidden` is + /// `None`) the type inheriting one name from two members. + pub element: ElementRef, + /// The inherited member the owned `element` hides — the redefinition + /// target a repair would spell. + pub hidden: Option, + /// The colliding name (a declared name or short name). + pub name: String, + /// Index into [`crate::model::Model::units`] of `element`'s unit. + pub unit: usize, + /// The declared name of `element` as written. + pub span: Span, + /// The finding's text, without the rule tag. + pub message: String, + /// The `:>>` target spelling — `hidden`'s simple name when it alone + /// binds the name in `element`'s namespace, its qualified name + /// otherwise — when `element` may redefine `hidden` without tripping + /// a checker rule a spelled redefinition is subject to: both are + /// features and `hidden` is no variant; an end is redefined by an end + /// (`validateRedefinitionEndConformance`); spelled directions agree or + /// `hidden`'s is `inout` (`validateRedefinitionDirectionConformance`); + /// `element` binds no value over a bound (non-default) value of + /// `hidden` or its redefinition chain (`validateFeatureValueOverriding`); + /// each user type `hidden` declares admits some type `element` + /// declares (redefinition type-compatibility); explicit multiplicities + /// nest (redefinition multiplicity conformance). `None` when any of + /// these would reject the repair, when `element` hides members from + /// unrelated bases (redefining one leaves the others), or when the + /// target has no spelling. Hidden members along one specialization + /// chain get the nearest as target, by qualified name: once the + /// chain's own collisions are repaired that redefinition covers them. + pub redefinition_target: Option, +} + +fn prop_str<'a>(b: &'a Builder, e: usize, key: &str) -> Option<&'a str> { + b.elements[e].props.get(key).and_then(|a| a.as_str()) +} + +/// The lookup names an element binds: its declared name — or, unnamed, +/// the effective name it takes from its first redefinition or reference +/// target — and, when it differs, its declared short name (both bind in +/// the same name space). +fn declared_keys(b: &Builder, e: usize) -> impl Iterator> { + let name: Option> = match prop_str(b, e, "declaredName") { + Some(n) => Some(Cow::Borrowed(n)), + None => b.effective_name(e).map(Cow::Owned), + }; + let short = prop_str(b, e, "declaredShortName") + .filter(|s| name.as_deref() != Some(*s)) + .map(Cow::Borrowed); + name.into_iter().chain(short) +} + +fn display_name(b: &Builder, e: usize) -> String { + prop_str(b, e, "declaredName") + .or_else(|| prop_str(b, e, "declaredShortName")) + .map_or_else(|| "".to_string(), str::to_string) +} + +/// Whether the two elements' metaclasses conform one way or the other — +/// the metaclass half of KerML `Membership::isDistinguishableFrom`. +fn overlapping(b: &Builder, x: usize, y: usize) -> bool { + let (tx, ty) = (b.elements[x].ty, b.elements[y].ty); + conforms(tx, ty) || conforms(ty, tx) +} + +/// Whether `e` reuses an inherited name through a redefinition the +/// specification implies rather than one the modeller spells — the +/// normative implicit redefinitions the resolver's specialization index +/// does not record as `Redefinition` relationships: +/// - a parameter of a behavior or step redefines the general's parameter +/// at the same position (KerML `checkFeatureParameterRedefinition`), a +/// result parameter the general's result (`checkFeatureResultRedefinition`); +/// - an end feature redefines the general's end at the same position +/// (`checkFeatureEndRedefinition`), so `end source : P;` in an interface +/// definition legally reuses `BinaryInterface`'s end names; +/// - a case objective (SysML `checkRequirementUsageObjectiveRedefinition`), +/// a state's entry/do/exit action (`checkActionUsageStateActionRedefinition`), +/// a view rendering (`checkRenderingUsageRedefinition`) and a result +/// expression redefine the inherited member of their role; +/// - a metadata body usage `text = "…"` is an `OwnedRedefinition` of the +/// metadata definition's feature by the grammar (`MetadataBodyUsage`), +/// which the lowering spells as a same-named usage. +fn implicitly_redefines(b: &Builder, e: usize) -> bool { + let elem = &b.elements[e]; + let owner_ty = b.owner_elem(e).map(|o| b.elements[o].ty); + let in_behavior = owner_ty.is_some_and(|t| conforms(t, "Behavior") || conforms(t, "Step")); + if in_behavior && elem.props.get("direction").is_some_and(|d| d.is_string()) { + return true; + } + if elem.props.get("isEnd").and_then(|v| v.as_bool()) == Some(true) { + return true; + } + if elem.owning_relationship.is_some_and(|r| { + matches!( + b.elements[r].ty, + "ReturnParameterMembership" + | "ObjectiveMembership" + | "StateSubactionMembership" + | "ViewRenderingMembership" + | "ResultExpressionMembership" + ) + }) { + return true; + } + owner_ty.is_some_and(|t| conforms(t, "MetadataFeature")) +} + +/// Whether `reuser` spells a redefinition or subsetting of `hidden` — +/// the legal ways to carry its name (lookup already removed the +/// redefined ones; the subsetting escape is the reference validator's +/// leniency). A typing (`feature f : A::f`) is neither. +fn explicitly_specializes(b: &mut Builder, reuser: usize, hidden: usize) -> bool { + b.indexed_specialization_targets(reuser, &["Subsetting", "Redefinition"]) + .contains(&hidden) +} + +/// Everything `e` transitively redefines (KerML `allRedefinedFeaturesOf` +/// without `e` itself). +fn redefinition_closure(b: &mut Builder, e: usize) -> HashSet { + let mut closure = HashSet::new(); + let mut stack = b.indexed_redefinition_targets(e); + while let Some(t) = stack.pop() { + if closure.insert(t) { + stack.extend(b.indexed_redefinition_targets(t)); + } + } + closure +} + +/// Whether the type whose body is `scope` owns a feature directly +/// redefining something in `closure` — such a type does not inherit any +/// member whose redefinition closure meets that feature (KerML +/// `removeRedefinedFeatures`, second condition), so nothing below it does +/// either. +fn removes_at(b: &mut Builder, scope: usize, closure: &HashSet) -> bool { + let Some(owner) = b.scope_owner(scope) else { + return false; + }; + b.owned_member_elems(owner, true).into_iter().any(|f| { + b.indexed_redefinition_targets(f) + .iter() + .any(|t| closure.contains(t)) + }) +} + +/// Whether some heritage path from `scope` reaches `target` without +/// passing through a type that removes a member of `closure` on the way +/// — implied bases included; cycles end at the visited set. +fn heritage_reaches( + b: &mut Builder, + scope: usize, + target: usize, + closure: &HashSet, +) -> bool { + let mut seen: HashSet = HashSet::from([scope]); + let mut stack = vec![scope]; + while let Some(s) = stack.pop() { + for base in b.base_scopes_split(s).0 { + if base == target { + return true; + } + if seen.insert(base) && !removes_at(b, base, closure) { + stack.push(base); + } + } + } + false +} + +/// Whether `dropped` never reaches `scope`'s type the normative way: KerML +/// `inheritedMemberships` is computed type by type, and a type whose owned +/// feature directly redefines a feature in an inherited member's +/// redefinition closure does not inherit that member — so a member both +/// the nearer `other` and `dropped` derive from one feature (sibling +/// redefinitions, `attribute h redefines header;` at two levels of a +/// redefinition chain) is gone at the level that spells the nearer one, +/// and at every other level that spells a sibling. Two unrelated bases +/// each redefining `Anything::self` are not that shape, and neither is a +/// diamond that also reaches `dropped`'s declaring type around every +/// removing level. +fn removed_at_nearer_level(b: &mut Builder, scope: usize, dropped: usize, other: usize) -> bool { + let direct = b.indexed_redefinition_targets(other); + if direct.is_empty() { + return false; + } + let closure = redefinition_closure(b, dropped); + if !direct.iter().any(|t| closure.contains(t)) { + return false; + } + let Some(target) = b + .owner_elem(dropped) + .and_then(|o| b.elem_scope.get(&o).copied()) + else { + return false; + }; + !heritage_reaches(b, scope, target, &closure) +} + +/// Among same-named inherited members hiding one owned member, the one +/// declared nearest — whose owner conforms to every other's — names the +/// finding; the first otherwise. +fn nearest(b: &mut Builder, candidates: &[usize]) -> usize { + let owners: Vec> = candidates.iter().map(|&c| b.owner_elem(c)).collect(); + for (i, &c) in candidates.iter().enumerate() { + let Some(oc) = owners[i] else { continue }; + if owners + .iter() + .flatten() + .all(|&o| o == oc || b.indexed_conforms(oc, o)) + { + return c; + } + } + candidates[0] +} + +/// The declaring namespaces of two members, qualified when their plain +/// names coincide (`Q1::N` and `Q2::N`). +fn declaring_pair(r: &mut ResolvedModel, a: usize, b2: usize) -> (String, String) { + let (oa, ob) = (r.b.owner_elem(a), r.b.owner_elem(b2)); + let plain = |r: &ResolvedModel, o: Option| { + o.map_or_else(|| "".to_string(), |o| display_name(&r.b, o)) + }; + let (mut na, mut nb) = (plain(r, oa), plain(r, ob)); + if na == nb { + if let (Some(oa), Some(ob)) = (oa, ob) { + if let (Some(qa), Some(qb)) = ( + r.element_qualified_name(ElementRef(oa)), + r.element_qualified_name(ElementRef(ob)), + ) { + (na, nb) = (qa, qb); + } + } + } + (na, nb) +} + +/// See [`InheritedNameCollision::redefinition_target`]. `simple` says the +/// hidden member's own name resolves to it alone from `element`'s +/// namespace, so the short spelling is safe. +fn redefinition_target( + r: &mut ResolvedModel, + element: usize, + hidden: usize, + simple: bool, +) -> Option { + let b = &r.b; + if !conforms(b.elements[element].ty, "Feature") || !conforms(b.elements[hidden].ty, "Feature") { + return None; + } + if b.elements[hidden] + .owning_relationship + .is_some_and(|rel| b.elements[rel].ty == "VariantMembership") + { + return None; + } + let flag = + |e: usize, key: &str| b.elements[e].props.get(key).and_then(|v| v.as_bool()) == Some(true); + if flag(hidden, "isEnd") && !flag(element, "isEnd") { + return None; + } + let (from, to) = ( + prop_str(b, element, "direction"), + prop_str(b, hidden, "direction"), + ); + if from.is_some() && to.is_some() && from != to && to != Some("inout") { + return None; + } + if b.values.contains_key(&element) { + let mut chain = redefinition_closure(&mut r.b, hidden); + chain.insert(hidden); + if chain + .iter() + .any(|&h| r.b.values.contains_key(&h) && !r.b.default_values.contains(&h)) + { + return None; + } + } + let lib_boundary = r.b.lib_boundary; + let mine = r.typings(ElementRef(element)); + let theirs = r.typings(ElementRef(hidden)); + for &h in &theirs { + // Conformance to a library type may ride implied bases the + // explicit closure cannot see; the checker skips those too. + if h.0 < lib_boundary || mine.is_empty() { + continue; + } + if !mine.iter().any(|&t| r.conforms(t, h)) { + return None; + } + } + if r.b.declares_multiplicity(element) && r.b.declares_multiplicity(hidden) { + let (Some((lo, hi)), Some((tlo, thi))) = ( + r.declared_multiplicity(ElementRef(element)), + r.declared_multiplicity(ElementRef(hidden)), + ) else { + return None; + }; + if lo < tlo || hi > thi { + return None; + } + } + if simple { + r.element_name(ElementRef(hidden)) + .map(sysmlv2_syntax::ast::escape_name) + .or_else(|| r.element_qualified_name(ElementRef(hidden))) + } else { + r.element_qualified_name(ElementRef(hidden)) + } +} + +fn span_of(b: &Builder, e: usize) -> Option { + b.decl_spans + .get(&e) + .or_else(|| b.member_spans.get(&e)) + .copied() +} + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + collisions(r) + .into_iter() + .filter(|c| !model.is_library_unit(c.unit)) + .map(|c| (c.unit, super::rule_warning(c.span, RULE, &c.message))) + .collect() +} + +/// Every inherited-name collision among the user elements, in element +/// order — owned-member collisions of a type first, then the names it +/// inherits twice, each in name order. +pub fn collisions(r: &mut ResolvedModel) -> Vec { + let mut out = Vec::new(); + let lib_boundary = r.b.lib_boundary; + for e in lib_boundary..r.b.explicit_len() { + let unit = r.b.unit_of_elem(e); + if !conforms(r.b.elements[e].ty, "Type") { + continue; + } + let Some(&scope) = r.b.elem_scope.get(&e) else { + continue; + }; + let bindings = r.b.inherited_bindings(scope, true); + if bindings.members.is_empty() && bindings.implicit_redefinitions.is_empty() { + continue; + } + let owned = r.b.owned_member_elems(e, false); + let owned_set: HashSet = owned.iter().copied().collect(); + + // Candidate pairs, gathered under one immutable borrow of the + // builder. Only names some *user* element declares can collide + // reportably (a pair of library members is left alone below), so + // library members are indexed only under those names. + // Shape 1: `(hidden inherited member, owned member, key, whether + // the key names nothing else in the namespace — one owned member + // and the hidden one — so the hidden one's simple name resolves + // to it once the redefining feature is set aside)`. + let mut hidden: Vec<(usize, usize, Cow, bool)> = Vec::new(); + // Shape 2: `(member, member, key, from the implicit-redefinition + // record)` — both inherited; a recorded pair is oriented + // `(dropped, shadowing)`, a by-name pair is not oriented. + let mut pairs: Vec<(usize, usize, Cow, bool)> = Vec::new(); + { + let b = &r.b; + let mut user_names: HashSet> = HashSet::new(); + for &o in &owned { + user_names.extend(declared_keys(b, o)); + } + for &(m, _) in &bindings.members { + if m >= lib_boundary { + user_names.extend(declared_keys(b, m)); + } + } + let mut by_name: BTreeMap, Vec> = BTreeMap::new(); + for &(m, _) in &bindings.members { + for key in declared_keys(b, m) { + if m >= lib_boundary || user_names.contains(&key) { + by_name.entry(key).or_default().push(m); + } + } + } + let simple = |key: &Cow, hidden: usize| { + by_name + .get(key) + .is_none_or(|ms| ms.iter().all(|&x| x == hidden || owned_set.contains(&x))) + && owned + .iter() + .filter(|&&x| declared_keys(b, x).any(|k| k == *key)) + .count() + == 1 + }; + for &(dropped, shadowing) in &bindings.implicit_redefinitions { + if !overlapping(b, dropped, shadowing) { + continue; + } + let key = declared_keys(b, shadowing) + .find(|k| declared_keys(b, dropped).any(|d| d == *k)); + let Some(key) = key else { continue }; + if owned_set.contains(&shadowing) { + let simple = simple(&key, dropped); + hidden.push((dropped, shadowing, key, simple)); + } else if !owned_set.contains(&dropped) + && shadowing >= lib_boundary + && !implicitly_redefines(b, shadowing) + { + // A library-written same-name usage is one of the + // implied redefinitions (result parameters, ends), + // spelled in units the reference validator accepts. + pairs.push((dropped, shadowing, key, true)); + } + } + for &o in &owned { + for key in declared_keys(b, o) { + let Some(ms) = by_name.get(&key) else { + continue; + }; + for &m in ms { + if m != o && !owned_set.contains(&m) && overlapping(b, o, m) { + let simple = simple(&key, m); + hidden.push((m, o, key.clone(), simple)); + } + } + } + } + for (key, ms) in &by_name { + for (i, &a) in ms.iter().enumerate() { + for &b2 in &ms[i + 1..] { + // Two inherited ends (or parameters) of one name from + // unrelated bases are both positionally redefined by + // the type's own ends (parameters) — `interface : I + // connect a to b` inherits `source` from + // `BinaryInterface` and from `I`, and its two spelled + // ends redefine both. A pair of library members is not + // reported either: a conforming model inherits none + // (the library's own redefinitions see to that), and a + // non-conforming one (`individual def X :> anAttributeDef`, + // whose `self` then arrives from both `DataValue` and + // `Occurrence`) already carries the specialization or + // typing error the pair would only echo. + if a != b2 + && (a >= lib_boundary || b2 >= lib_boundary) + && !owned_set.contains(&a) + && !owned_set.contains(&b2) + && overlapping(b, a, b2) + && !(implicitly_redefines(b, a) && implicitly_redefines(b, b2)) + { + pairs.push((a, b2, key.clone(), false)); + } + } + } + } + } + if hidden.is_empty() && pairs.is_empty() { + continue; + } + let hidden: Vec<(usize, usize, String, bool)> = hidden + .into_iter() + .map(|(m, o, k, simple)| (m, o, k.into_owned(), simple)) + .collect(); + let mut pairs: Vec<(usize, usize, String, bool)> = pairs + .into_iter() + .map(|(a, b2, k, oriented)| (a, b2, k.into_owned(), oriented)) + .collect(); + pairs.sort_by(|x, y| x.2.cmp(&y.2)); + // One report per (namespace, name): the owned shape first, then + // the inherited one, both in name order. + let mut reported: HashSet = HashSet::new(); + + let mut by_owned: BTreeMap<(String, usize), (Vec, bool)> = BTreeMap::new(); + for (m, o, key, simple) in hidden { + if !implicitly_redefines(&r.b, o) && !explicitly_specializes(&mut r.b, o, m) { + let entry = by_owned.entry((key, o)).or_insert((Vec::new(), simple)); + entry.0.push(m); + entry.1 &= simple; + } + } + // A member colliding under two of its names (` b` against both + // `a` and `b`) would need two redefinitions in one fix; none is + // offered, the findings stand. + let mut keys_per_owned: BTreeMap = BTreeMap::new(); + for (_, o) in by_owned.keys() { + *keys_per_owned.entry(*o).or_default() += 1; + } + for ((name, o), (ms, simple)) in by_owned { + if reported.contains(&name) { + continue; + } + let Some(span) = span_of(&r.b, o) else { + continue; + }; + reported.insert(name.clone()); + let near = nearest(&mut r.b, &ms); + let from = r.b.owner_elem(near).map_or_else( + || "".to_string(), + |owner| display_name(&r.b, owner), + ); + let one_chain = keys_per_owned[&o] == 1 + && ms.iter().all(|&m| { + m == near + || match (r.b.owner_elem(near), r.b.owner_elem(m)) { + (Some(a), Some(b)) => r.conforms(ElementRef(a), ElementRef(b)), + _ => false, + } + }); + let redefinition_target = one_chain + .then(|| redefinition_target(r, o, near, simple && ms.len() == 1)) + .flatten(); + let hint = if !conforms(r.b.elements[o].ty, "Feature") { + "rename it" + } else if redefinition_target.is_some() { + "redefine it (`:>>`) or rename it" + } else { + "rename it, or redefine it (`:>>`) with a conforming declaration" + }; + out.push(InheritedNameCollision { + element: ElementRef(o), + hidden: Some(ElementRef(near)), + name: name.clone(), + unit, + span, + message: format!( + "`{name}` duplicates the inherited member name from `{from}` — {hint}" + ), + redefinition_target, + }); + } + + let Some(span) = span_of(&r.b, e) else { + continue; + }; + for (a, b2, name, oriented) in pairs { + if reported.contains(&name) { + continue; + } + // A recorded pair is `(dropped, shadowing)`; a by-name pair + // may be either way round, so both orientations are tried. + let cleared = explicitly_specializes(&mut r.b, b2, a) + || removed_at_nearer_level(&mut r.b, scope, a, b2) + || (!oriented + && (explicitly_specializes(&mut r.b, a, b2) + || removed_at_nearer_level(&mut r.b, scope, b2, a))); + if cleared { + continue; + } + reported.insert(name.clone()); + let (mut na, mut nb) = declaring_pair(r, a, b2); + if na > nb { + std::mem::swap(&mut na, &mut nb); + } + out.push(InheritedNameCollision { + element: ElementRef(e), + hidden: None, + name: name.clone(), + unit, + span, + message: format!( + "`{name}` is inherited from both `{na}` and `{nb}` — the two member \ + names are indistinguishable" + ), + redefinition_target: None, + }); + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/endpoints.rs b/crates/sysmlv2-model/src/check/endpoints.rs new file mode 100644 index 0000000..faf2376 --- /dev/null +++ b/crates/sysmlv2-model/src/check/endpoints.rs @@ -0,0 +1,51 @@ +//! Reference-property metaclasses from the KerML abstract syntax. This also +//! checks standalone relationships, which are not owned by their specific type. +use super::facts::{Facts, is}; +use crate::{json::ResolvedModel, model::Model}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &ResolvedModel, model: &Model, g: &Facts) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + for (e, relation) in r.b.elements.iter().enumerate().take(r.b.explicit_len()) { + let unit = r.b.unit_of_elem(e); + if model.is_library_unit(unit) { + continue; + } + let properties: &[(&str, &str)] = match relation.ty { + "Specialization" => &[("specific", "Type"), ("general", "Type")], + "Subclassification" => &[ + ("subclassifier", "Classifier"), + ("superclassifier", "Classifier"), + ], + "FeatureTyping" => &[("typedFeature", "Feature"), ("type", "Type")], + "Subsetting" => &[ + ("subsettingFeature", "Feature"), + ("subsettedFeature", "Feature"), + ], + "Redefinition" => &[ + ("redefiningFeature", "Feature"), + ("redefinedFeature", "Feature"), + ], + "ReferenceSubsetting" => &[ + ("subsettingFeature", "Feature"), + ("referencedFeature", "Feature"), + ], + "Conjugation" => &[("conjugatedType", "Type"), ("originalType", "Type")], + "FeatureInverting" => &[ + ("featureInverted", "Feature"), + ("invertingFeature", "Feature"), + ], + "Disjoining" => &[("typeDisjoined", "Type"), ("disjoiningType", "Type")], + "TypeFeaturing" => &[("featureOfType", "Feature"), ("featuringType", "Type")], + _ => &[], + }; + for &(property, expected) in properties { + if let Some(t) = g.target(&r.b, e, property) { + if !is(&r.b, t, expected) { + out.push((unit, Diagnostic::error(g.span(&r.b, e), format!("{}::{property} must refer to a {expected} [relationship-endpoint-metaclass]", relation.ty)))); + } + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/expressions.rs b/crates/sysmlv2-model/src/check/expressions.rs new file mode 100644 index 0000000..bcabaed --- /dev/null +++ b/crates/sysmlv2-model/src/check/expressions.rs @@ -0,0 +1,464 @@ +//! Static expression contracts, independent of whether values can be evaluated. +use super::facts::{Facts, is}; +use crate::{json::ResolvedModel, model::Model}; +use std::collections::HashSet; +use sysmlv2_syntax::{ + ast::{BinaryOp, ClassificationOp, Expr, ExprKind, Literal, Name, QualifiedName, TargetRef}, + diag::Diagnostic, + visit::{self, Visit}, +}; + +pub(super) fn library_type(b: &mut crate::json::Builder, fqn: &str) -> Option { + let span = sysmlv2_syntax::Span::default(); + b.resolve( + 0, + &QualifiedName { + is_global: true, + span, + segments: fqn + .split("::") + .map(|s| Name { + value: s.into(), + span, + }) + .collect(), + }, + 0, + ) +} +pub(super) fn referent(b: &mut crate::json::Builder, scope: usize, expr: &Expr) -> Option { + fn spine(expr: &Expr) -> Option> { + match &expr.kind { + ExprKind::Ref(qn) => Some(vec![qn.clone()]), + ExprKind::ChainStep { + target, + member: TargetRef::Name(qn), + } => { + let mut parts = spine(target)?; + parts.push(qn.clone()); + Some(parts) + } + _ => None, + } + } + match &expr.kind { + ExprKind::Ref(qn) => b.resolve(scope, qn, 0), + ExprKind::ChainStep { + target, + member: TargetRef::Name(qn), + } => b.resolve_chain_member(scope, spine(target).as_deref(), qn), + _ => None, + } +} + +/// Known result types, without evaluating or supplying values to unbound inputs. +pub(super) fn types( + b: &mut crate::json::Builder, + g: &Facts, + scope: usize, + expr: &Expr, + depth: usize, +) -> Vec { + if depth > 32 { + return Vec::new(); + } + let scalar = match &expr.kind { + ExprKind::Literal(Literal::Bool(_)) => Some("ScalarValues::Boolean"), + ExprKind::Literal(Literal::String(_)) => Some("ScalarValues::String"), + ExprKind::Literal(Literal::Integer(_)) => Some("ScalarValues::Integer"), + ExprKind::Literal(Literal::Real(_)) => Some("ScalarValues::Real"), + ExprKind::Binary { + op: + BinaryOp::Eq + | BinaryOp::NotEq + | BinaryOp::Same + | BinaryOp::NotSame + | BinaryOp::Lt + | BinaryOp::LtEq + | BinaryOp::Gt + | BinaryOp::GtEq + | BinaryOp::CondAnd + | BinaryOp::CondOr + | BinaryOp::Implies + | BinaryOp::Xor, + .. + } => Some("ScalarValues::Boolean"), + ExprKind::Classification { + op: ClassificationOp::IsType | ClassificationOp::HasType, + .. + } => Some("ScalarValues::Boolean"), + _ => None, + }; + if let Some(name) = scalar { + return library_type(b, name).into_iter().collect(); + } + match &expr.kind { + ExprKind::Ref(_) | ExprKind::ChainStep { .. } => { + let Some(e) = referent(b, scope, expr) else { + return Vec::new(); + }; + let ts = g.typed(b, e); + if !ts.is_empty() { + return ts; + } + if let Some((s, value)) = b.values.get(&e).cloned() { + return types(b, g, s, &value, depth + 1); + } + } + ExprKind::Constructor { ty, .. } + | ExprKind::Classification { + op: ClassificationOp::As, + ty, + .. + } => { + if let Some(qn) = ty.as_name() { + return b.resolve(scope, qn, 0).into_iter().collect(); + } + } + ExprKind::Invocation { ty, .. } => { + if let Some(t) = ty.as_name().and_then(|qn| b.resolve(scope, qn, 0)) { + return g + .effective_members(b, t) + .into_iter() + .filter(|&m| { + b.elements[m] + .owning_relationship + .is_some_and(|rel| is(b, rel, "ReturnParameterMembership")) + }) + .flat_map(|m| g.typed(b, m)) + .collect(); + } + } + ExprKind::Binary { + lhs, + rhs, + op: + BinaryOp::Add + | BinaryOp::Sub + | BinaryOp::Mul + | BinaryOp::Div + | BinaryOp::Rem + | BinaryOp::Pow + | BinaryOp::Caret, + } => { + let a = types(b, g, scope, lhs, depth + 1); + let z = types(b, g, scope, rhs, depth + 1); + if !a.is_empty() && a == z { + return a; + } + let numeric = |t| { + [ + "ScalarValues::Integer", + "ScalarValues::Real", + "ScalarValues::Rational", + "ScalarValues::Natural", + "ScalarValues::Positive", + ] + .iter() + .any(|n| g.named(b, t, n)) + }; + if !a.is_empty() && !z.is_empty() && a.iter().chain(&z).all(|&t| numeric(t)) { + return library_type(b, "ScalarValues::Real").into_iter().collect(); + } + } + ExprKind::Index { target, .. } + | ExprKind::Unary { + operand: target, .. + } => return types(b, g, scope, target, depth + 1), + _ => {} + } + Vec::new() +} + +/// Whether a known static result fails a required type. An unresolved type is +/// undecided, including when the standard library is unavailable. +pub(super) fn wrong_type( + b: &mut crate::json::Builder, + g: &Facts, + scope: usize, + expr: &Expr, + required: &str, +) -> bool { + if matches!( + expr.kind, + ExprKind::Literal( + Literal::Integer(_) | Literal::Real(_) | Literal::String(_) | Literal::Infinity + ) + ) && matches!( + required, + "ScalarValues::Boolean" | "ISQ::DurationValue" | "Time::TimeInstantValue" + ) { + return true; + } + let Some(required) = library_type(b, required) else { + return false; + }; + let actual = types(b, g, scope, expr, 0); + !actual.is_empty() + && !actual + .iter() + .any(|&t| b.conforms_upward_semantic(t, required)) +} + +/// Model-level evaluability is distinct from the toolkit's ability to execute a +/// user calculation. Recursion and unresolved prerequisites remain undecided. +pub(super) fn model_level( + b: &mut crate::json::Builder, + g: &Facts, + scope: usize, + expr: &Expr, + depth: usize, +) -> Option { + if depth > 32 { + return None; + } + let mut all = |xs: Vec<&Expr>| { + let mut unknown = false; + for x in xs { + match model_level(b, g, scope, x, depth + 1) { + Some(false) => return Some(false), + None => unknown = true, + Some(true) => {} + } + } + if unknown { None } else { Some(true) } + }; + match &expr.kind { + ExprKind::Literal(_) | ExprKind::Null | ExprKind::MetadataAccess { .. } => Some(true), + ExprKind::Binary { lhs, rhs, .. } => all(vec![lhs, rhs]), + ExprKind::Unary { + op: sysmlv2_syntax::ast::UnaryOp::Tilde, + operand, + } if matches!( + operand.kind, + ExprKind::Literal(Literal::Integer(_) | Literal::Real(_)) + ) => + { + Some(false) + } + ExprKind::Unary { operand, .. } => all(vec![operand]), + ExprKind::Conditional { + cond, + then_branch, + else_branch, + } => all(vec![cond, then_branch, else_branch]), + ExprKind::Sequence(xs) => all(xs.iter().collect()), + ExprKind::Constructor { args, .. } => all(args.iter().map(|a| &a.value).collect()), + ExprKind::Index { target, index } => all(vec![target, index]), + ExprKind::Bracket { target, arg } => all(vec![target, arg]), + ExprKind::Collect { target, .. } + | ExprKind::Select { target, .. } + | ExprKind::ChainStep { target, .. } => all(vec![target]), + ExprKind::Classification { operand: None, .. } => Some(true), + ExprKind::Classification { + operand: Some(operand), + .. + } => all(vec![operand]), + ExprKind::Ref(qn) => { + let e = b.resolve(scope, qn, 0)?; + if !is(b, e, "Feature") || is(b, e, "MetadataFeature") || is(b, e, "EnumerationUsage") { + return Some(true); + } + if let Some(o) = g.featuring(b, e) { + return Some(is(b, o, "Metaclass") || is(b, o, "MetadataFeature")); + } + let (s, value) = b.values.get(&e)?.clone(); + model_level(b, g, s, &value, depth + 1) + } + ExprKind::Invocation { ty, args } => { + let t = b.resolve(scope, ty.as_name()?, 0)?; + let model_function = ["BaseFunctions", "DataFunctions", "ControlFunctions"] + .iter() + .any(|pkg| g.owner[t].is_some_and(|o| g.named(b, o, pkg))) + && t < b.lib_boundary; + if !model_function { + return Some(false); + } + for a in args { + if model_level(b, g, scope, &a.value, depth + 1) != Some(true) { + return None; + } + } + Some(true) + } + _ => None, + } +} + +struct Expressions<'a>(Vec<&'a Expr>); +impl<'a> Visit<'a> for Expressions<'a> { + fn visit_expr(&mut self, expr: &'a Expr) { + self.0.push(expr); + // These expressions introduce a new lexical scope. Their lowered + // result expressions are checked separately with that scope. + if !matches!( + expr.kind, + ExprKind::Body { .. } | ExprKind::Collect { .. } | ExprKind::Select { .. } + ) { + visit::walk_expr(self, expr); + } + } +} +pub(super) fn validate( + r: &mut ResolvedModel, + model: &Model, + g: &Facts, +) -> Vec<(usize, Diagnostic)> { + let mut roots: Vec<_> = super::user_entries(&r.b, model, r.b.values.iter()) + .into_iter() + .map(|(o, (s, e))| (o, s, e)) + .collect(); + roots.extend(super::user_rows( + &r.b, + model, + r.b.result_exprs.iter(), + |row| row.0, + )); + roots.extend( + super::user_entries(&r.b, model, r.b.contract_exprs.iter()) + .into_iter() + .map(|(e, (s, x))| (e, s, x)), + ); + roots.sort_by_key(|(o, _, e)| (*o, e.span.start)); + let mut out = Vec::new(); + for (owner, scope, expr) in roots { + let unit = r.b.unit_of_elem(owner); + let mut expressions = Expressions(Vec::new()); + expressions.visit_expr(&expr); + for expr in expressions.0 { + let mut report = |rule: &'static str, message: &str| { + out.push((unit, super::rule_error(expr.span, rule, message))) + }; + match &expr.kind { + ExprKind::ChainStep { .. } => { + if let Some(t) = referent(&mut r.b, scope, expr) { + if !is(&r.b, t, "Feature") { + report( + "validateFeatureChainExpressionFeatureConformance", + "A feature-chain expression must select a feature", + ); + } + } + } + ExprKind::Classification { + op: ClassificationOp::As, + operand: Some(operand), + ty, + } => { + if let Some(t) = ty.as_name().and_then(|qn| r.b.resolve(scope, qn, 0)) { + let a = types(&mut r.b, g, scope, operand, 0); + if super::relationships::incompatible(&mut r.b, g, &a, &[t]) { + out.push(( + unit, + super::rule_warning( + expr.span, + "validateOperatorExpressionCastConformance", + "Cast types should conform in at least one direction", + ), + )); + } + } + } + ExprKind::Ref(name) => { + if let Some(t) = r.b.resolve(scope, name, 0) { + if !is(&r.b, t, "Feature") { + report( + "validateFeatureReferenceExpressionReferentIsFeature", + "A feature reference expression must name a feature", + ); + } + } + } + ExprKind::Constructor { ty, args } => { + if let TargetRef::Name(name) = &**ty { + if let Some(t) = r.b.resolve(scope, name, 0) { + if !is(&r.b, t, "Type") { + report( + "validateInstantiationExpressionInstantiatedType", + "A constructor must instantiate a type", + ); + } + } + } + let mut names = HashSet::new(); + for arg in args { + if let Some(name) = &arg.name { + if !names.insert(name.to_display_string()) { + report( + "validateConstructorExpressionNoDuplicateFeatureRedefinition", + "A constructor cannot bind a feature more than once", + ); + } + } + } + } + ExprKind::Invocation { ty, .. } => { + if let Some(t) = ty.as_name().and_then(|name| r.b.resolve(scope, name, 0)) { + if !is(&r.b, t, "Behavior") + && !is(&r.b, t, "Step") + && (!is(&r.b, t, "Feature") || !g.typed(&r.b, t).is_empty()) + && !g.typed(&r.b, t).iter().any(|&t| is(&r.b, t, "Behavior")) + { + report( + "validateInvocationExpressionInstantiatedType", + "An invocation must invoke a behavior or behavioral feature", + ); + } + } + } + ExprKind::Bracket { arg, .. } + if matches!( + arg.kind, + ExprKind::Literal(Literal::Integer(_) | Literal::Real(_)) + ) => + { + let (rule, message) = + if model.unit(unit).unit.dialect == sysmlv2_syntax::ast::Dialect::Kerml { + ( + "validateOperatorExpressionBracketOperator", + "Square brackets do not index a sequence; use #(index)", + ) + } else { + ( + "validateOperatorExpressionQuantity", + "A quantity unit must be a measurement reference", + ) + }; + out.push((unit, super::rule_warning(arg.span, rule, message))); + } + _ => {} + } + } + } + let filters: Vec<_> = + r.b.filter_exprs + .iter() + .filter_map(|(scope, expr)| { + let unit = r.b.unit_of_elem(r.b.nearest_scope_owner(*scope)?); + (!model.is_library_unit(unit)).then(|| (unit, *scope, expr.clone())) + }) + .collect(); + for (unit, scope, expr) in filters { + if wrong_type(&mut r.b, g, scope, &expr, "ScalarValues::Boolean") { + out.push(( + unit, + super::rule_error( + expr.span, + "validateElementFilterMembershipIsBoolean", + "An element filter must have a Boolean result", + ), + )); + } + if model_level(&mut r.b, g, scope, &expr, 0) == Some(false) { + out.push(( + unit, + super::rule_error( + expr.span, + "validateElementFilterMembershipIsModelLevelEvaluable", + "An element filter must be model-level evaluable", + ), + )); + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/facts.rs b/crates/sysmlv2-model/src/check/facts.rs new file mode 100644 index 0000000..7089974 --- /dev/null +++ b/crates/sysmlv2-model/src/check/facts.rs @@ -0,0 +1,457 @@ +//! Read-only graph indexes shared by static validators. Constructed once per +//! analysis, so edits and library replay cannot leave stale semantic facts. +mod id_index; + +use crate::{json::Builder, layered::LayeredVec, metaclass}; +use std::collections::HashSet; +use sysmlv2_syntax::Span; + +#[derive(Clone, Default, serde::Serialize, serde::Deserialize)] +pub(crate) struct Facts { + ids: id_index::IdIndex, + pub owner: LayeredVec>, + pub members: crate::flat::Rows, + pub supers: crate::flat::Rows, + contexts: crate::flat::Rows, + outgoing: crate::flat::Rows, + targets: crate::flat::Rows<(crate::properties::Key, usize)>, +} +impl Facts { + pub(crate) fn contains_id(&self, id: &uuid::Uuid) -> bool { + self.ids.get(id).is_some() + } + pub fn new(b: &mut Builder) -> Self { + // The explicit elements only: the implied relationships the + // derivation layer may have appended are not the model the checks + // read. + let n = b.explicit_len(); + let mut facts = b.library_facts.as_deref().cloned().unwrap_or_default(); + let start = facts.owner.len(); + let mut ids = std::mem::take(&mut facts.ids); + for i in start..n { + ids.insert(b.elem_id(i), i); + } + let mut targets = facts.targets; + for e in b.elements.iter().take(n).skip(start) { + targets.push( + e.props + .references() + .filter_map(|(k, id)| ids.get(&id).copied().map(|t| (k, t))) + .collect(), + ); + } + // Only the new elements own new relationships; the library prefix + // keeps its shared owner column. + let mut relation_owner = vec![None; n - start]; + for (owner, e) in b.elements.iter().enumerate().take(n).skip(start) { + for &rel in &e.owned_relationships { + if rel >= start { + relation_owner[rel - start] = Some(owner); + } + } + } + let owner_of = |rel: usize| { + if rel < start { + facts.owner[rel] + } else { + relation_owner[rel - start] + } + }; + let mut owner = facts.owner.clone(); + for (i, e) in b.elements.iter().enumerate().take(n).skip(start) { + owner.push( + e.owning_relationship + .and_then(owner_of) + .or_else(|| owner_of(i)), + ); + } + let mut members = facts.members; + members.resize(n); + for (i, e) in b.elements.iter().enumerate().take(n).skip(start) { + if e.owning_relationship + .is_some_and(|rel| is(b, rel, "Membership")) + { + if let Some(o) = owner[i] { + members.row_mut(o).push(i); + } + } + } + let mut supers = facts.supers; + supers.resize(n); + let mut outgoing = facts.outgoing; + for e in b.elements.iter().take(n).skip(start) { + outgoing.push(e.owned_relationships.to_vec()); + } + let mut changed = HashSet::new(); + // Read resolved graph edges, including prefix metadata and standalone + // relationships which do not all have a spec_targets entry. + for (rel_index, rel) in b.elements.iter().enumerate().take(n).skip(start) { + let keys = match rel.ty { + "FeatureTyping" | "ConjugatedPortTyping" => ("typedFeature", "type"), + "Subclassification" => ("subclassifier", "superclassifier"), + "Subsetting" => ("subsettingFeature", "subsettedFeature"), + "Redefinition" => ("redefiningFeature", "redefinedFeature"), + "ReferenceSubsetting" => ("subsettingFeature", "referencedFeature"), + "Specialization" => ("specific", "general"), + "Conjugation" => ("conjugatedType", "originalType"), + "TypeFeaturing" => ("featureOfType", "featuringType"), + "FeatureInverting" => ("featureInverted", "invertingFeature"), + _ => continue, + }; + let target = |key: &str| { + targets[rel_index] + .iter() + .find(|(k, _)| k.name() == key) + .map(|(_, t)| *t) + }; + if let Some(e) = target(keys.0) { + if !outgoing[e].contains(&rel_index) { + outgoing.row_mut(e).push(rel_index); + } + } + if let (Some(e), Some(t)) = (target(keys.0), target(keys.1)) { + if metaclass::conforms(rel.ty, "Specialization") && !supers[e].contains(&t) { + supers.row_mut(e).push(t); + if e < start { + changed.insert(e); + } + } + } + } + let mut contexts = facts.contexts; + contexts.resize(n); + for e in (start..n).chain(changed) { + let mut ts = supers[e].to_vec(); + ts.extend(b.context_bases(e)); + ts.sort_unstable(); + ts.dedup(); + contexts.set(e, ts); + } + Self { + targets, + outgoing, + contexts, + ids, + owner, + members, + supers, + } + } + pub(crate) fn freeze(&mut self) { + self.ids.freeze(); + self.targets.freeze(); + self.owner.freeze(); + self.members.freeze(); + self.supers.freeze(); + self.contexts.freeze(); + self.outgoing.freeze(); + } + pub(crate) fn valid(&self, n: usize) -> bool { + self.targets.len() == n + && self.targets.iter().flatten().all(|(_, t)| *t < n) + && self.owner.len() == n + && self.members.len() == n + && self.supers.len() == n + && self.contexts.len() == n + && self.outgoing.len() == n + && self.ids.values().all(|&i| i < n) + && self.owner.iter().all(|o| o.is_none_or(|i| i < n)) + && self + .members + .iter() + .chain(self.supers.iter()) + .chain(self.contexts.iter()) + .chain(self.outgoing.iter()) + .flatten() + .all(|&i| i < n) + } + pub fn target(&self, _b: &Builder, e: usize, key: &str) -> Option { + self.targets[e] + .iter() + .find(|(k, _)| k.name() == key) + .map(|(_, t)| *t) + } + pub fn relations(&self, b: &Builder, e: usize, kind: &str, key: &str) -> Vec { + self.outgoing[e] + .iter() + .filter(|&&r| is(b, r, kind)) + .filter_map(|&r| self.target(b, r, key)) + .collect() + } + pub fn context(&self, e: usize) -> Vec { + self.walk(e, &self.contexts) + } + pub fn closure(&self, e: usize) -> Vec { + self.walk(e, &self.supers) + } + fn walk(&self, e: usize, edges: &crate::flat::Rows) -> Vec { + let mut seen = HashSet::new(); + let mut out = Vec::new(); + let mut stack = vec![e]; + while let Some(e) = stack.pop() { + if seen.insert(e) { + out.push(e); + stack.extend(edges[e].iter().copied()); + } + } + out + } + /// Direction as seen through the specializing/typing context. Conjugation + /// reverses in/out; conflicting paths leave the fact undecided. + pub fn direction_through<'a>( + &self, + b: &'a Builder, + owner: usize, + target: usize, + ) -> Option<&'a str> { + let direction = b.elements[target].props.get("direction")?.as_str()?; + let featuring = self.featuring(b, target)?; + let mut seen = HashSet::new(); + let mut stack = vec![(owner, false)]; + let mut result = None; + while let Some((e, flipped)) = stack.pop() { + if !seen.insert((e, flipped)) { + continue; + } + if e == featuring { + let d = match (direction, flipped) { + ("in", true) => "out", + ("out", true) => "in", + _ => direction, + }; + if result.is_some_and(|old| old != d) { + return None; + } + result = Some(d); + } + for &rel in &self.outgoing[e] { + for (kind, key, flip) in [ + ("FeatureTyping", "type", false), + ("Subclassification", "superclassifier", false), + ("Subsetting", "subsettedFeature", false), + ("Redefinition", "redefinedFeature", false), + ("Conjugation", "originalType", true), + ] { + if is(b, rel, kind) { + if let Some(t) = self.target(b, rel, key) { + stack.push((t, flipped ^ flip)); + } + } + } + } + } + result + } + pub fn effective_kind(&self, b: &Builder, e: usize, kind: &str) -> bool { + let mut seen = HashSet::new(); + let mut stack = vec![e]; + while let Some(e) = stack.pop() { + if !seen.insert(e) { + continue; + } + if is(b, e, kind) { + return true; + } + stack.extend( + self.supers[e] + .iter() + .copied() + .filter(|&t| is(b, t, "Feature")), + ); + let chain: Vec<_> = self.outgoing[e] + .iter() + .copied() + .filter(|&r| is(b, r, "FeatureChaining")) + .collect(); + if chain + .iter() + .all(|&r| self.target(b, r, "chainingFeature").is_some()) + { + if let Some(t) = chain + .last() + .and_then(|&r| self.target(b, r, "chainingFeature")) + { + stack.push(t); + } + } + } + false + } + pub fn typed(&self, b: &Builder, e: usize) -> Vec { + let mut result = Vec::new(); + let mut seen = HashSet::new(); + let mut stack = vec![e]; + while let Some(e) = stack.pop() { + if !seen.insert(e) { + continue; + } + for &r in &self.outgoing[e] { + if is(b, r, "FeatureTyping") { + if let Some(t) = self.target(b, r, "type") { + if !result.contains(&t) { + result.push(t); + } + } + } else if is(b, r, "Subsetting") { + for key in ["subsettedFeature", "redefinedFeature", "referencedFeature"] { + if let Some(t) = self.target(b, r, key) { + stack.push(t); + } + } + } else if is(b, r, "Conjugation") { + if let Some(t) = self.target(b, r, "originalType") { + if is(b, t, "Feature") { + stack.push(t); + } + } + } + } + // A partially unresolved chain has no known terminal feature. + let chain: Vec<_> = b.elements[e] + .owned_relationships + .iter() + .copied() + .filter(|&rel| is(b, rel, "FeatureChaining")) + .collect(); + if chain + .iter() + .all(|&rel| self.target(b, rel, "chainingFeature").is_some()) + { + if let Some(t) = chain + .last() + .and_then(|&rel| self.target(b, rel, "chainingFeature")) + { + stack.push(t); + } + } + } + result + .iter() + .copied() + .filter(|t| { + !result + .iter() + .any(|other| other != t && self.closure(*other).contains(t)) + }) + .collect() + } + /// Effective members, removing inherited features replaced by redefinitions. + pub fn effective_members(&self, b: &Builder, e: usize) -> Vec { + let own_ends = self.members[e] + .iter() + .filter(|&&m| flag(b, m, "isEnd")) + .count(); + let all: Vec<_> = self + .closure(e) + .into_iter() + .flat_map(|t| { + let mut end_index = 0; + self.members[t].iter().copied().filter(move |&m| { + if flag(b, m, "isEnd") { + end_index += 1; + if t != e && end_index <= own_ends { + return false; + } + } + true + }) + }) + .collect(); + let all: Vec<_> = all + .iter() + .copied() + .filter(|&m| { + let role = b.elements[m].owning_relationship.map(|r| b.elements[r].ty); + if !matches!(role, Some("SubjectMembership" | "ObjectiveMembership")) { + return true; + } + !all.iter().any(|&other| { + other != m + && b.elements[other] + .owning_relationship + .map(|r| b.elements[r].ty) + == role + && self.owner[other] + .zip(self.owner[m]) + .is_some_and(|(a, z)| a != z && self.closure(a).contains(&z)) + }) + }) + .collect(); + let hidden: HashSet<_> = all.iter().flat_map(|&m| self.redefined(b, m)).collect(); + let mut seen = HashSet::new(); + all.into_iter() + .filter(|m| !hidden.contains(m) && seen.insert(*m)) + .collect() + } + pub fn redefined(&self, b: &Builder, e: usize) -> Vec { + let mut seen = HashSet::from([e]); + let mut stack = self.relations(b, e, "Redefinition", "redefinedFeature"); + let mut out = Vec::new(); + while let Some(t) = stack.pop() { + if seen.insert(t) { + out.push(t); + stack.extend(self.relations(b, t, "Redefinition", "redefinedFeature")); + } + } + out + } + pub fn feature_target(&self, b: &Builder, e: usize) -> usize { + let mut e = e; + let mut seen = HashSet::new(); + while seen.insert(e) { + let next = self.relations(b, e, "ReferenceSubsetting", "referencedFeature"); + if let [t] = next.as_slice() { + e = *t; + } else { + break; + } + } + e + } + pub fn named(&self, b: &Builder, e: usize, fqn: &str) -> bool { + let mut current = Some(e); + for name in fqn.rsplit("::") { + let Some(i) = current else { + return false; + }; + if b.elements[i] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + != Some(name) + { + return false; + } + current = self.owner[i]; + } + true + } + pub fn featuring(&self, b: &Builder, e: usize) -> Option { + let rel = b.elements[e].owning_relationship?; + if is(b, rel, "FeatureMembership") { + self.owner[e] + } else { + None + } + } + pub fn span(&self, b: &Builder, e: usize) -> Span { + let mut current = Some(e); + let mut seen = HashSet::new(); + while let Some(e) = current { + if !seen.insert(e) { + break; + } + if let Some(span) = b.decl_spans.get(&e).or_else(|| b.member_spans.get(&e)) { + return *span; + } + current = self.owner[e]; + } + Span::default() + } +} +pub(super) fn is(b: &Builder, e: usize, kind: &str) -> bool { + metaclass::conforms(b.elements[e].ty, kind) +} +pub(super) fn flag(b: &Builder, e: usize, key: &str) -> bool { + b.elements[e].props.get(key).and_then(|x| x.as_bool()) == Some(true) +} diff --git a/crates/sysmlv2-model/src/check/facts/id_index.rs b/crates/sysmlv2-model/src/check/facts/id_index.rs new file mode 100644 index 0000000..77dfd1d --- /dev/null +++ b/crates/sysmlv2-model/src/check/facts/id_index.rs @@ -0,0 +1,181 @@ +//! Sorted immutable identity table with private additions. Snapshot reads check +//! ordering once and query the stored rows without rehashing library identities. +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{collections::HashMap, sync::Arc}; +use uuid::Uuid; + +// Restrict a lookup to one of 4096 ordered UUID-prefix ranges. This keeps +// direct-table lookup short without reconstructing a hash map on every load. +const BUCKETS: usize = 4096; +fn bucket(id: &Uuid) -> usize { + (id.as_u128() >> 116) as usize +} +fn offsets(rows: &[(Uuid, usize)]) -> Vec { + let mut offsets = vec![0; BUCKETS + 1]; + let mut i = 0; + for (bucket_index, offset) in offsets.iter_mut().enumerate().skip(1) { + while i < rows.len() && bucket(&rows[i].0) < bucket_index { + i += 1; + } + *offset = i; + } + offsets +} +#[derive(Serialize, Deserialize)] +struct Table { + rows: Vec<(Uuid, usize)>, + offsets: Vec, +} +impl Table { + fn new(rows: Vec<(Uuid, usize)>) -> Self { + Self { + offsets: offsets(&rows), + rows, + } + } +} +impl Default for Table { + fn default() -> Self { + Self::new(Vec::new()) + } +} + +#[derive(Clone, Default)] +pub(super) struct IdIndex { + base: Arc, + local: HashMap, +} +impl IdIndex { + pub(super) fn get(&self, id: &Uuid) -> Option<&usize> { + self.local.get(id).or_else(|| { + let bucket = bucket(id); + let rows = &self.base.rows[self.base.offsets[bucket]..self.base.offsets[bucket + 1]]; + rows.binary_search_by_key(id, |(id, _)| *id) + .ok() + .map(|i| &rows[i].1) + }) + } + pub(super) fn insert(&mut self, id: Uuid, index: usize) { + self.local.insert(id, index); + } + pub(super) fn values(&self) -> impl Iterator { + self.base + .rows + .iter() + .map(|(_, i)| i) + .chain(self.local.values()) + } + fn rows(&self) -> Vec<(Uuid, usize)> { + let mut rows: Vec<_> = self + .base + .rows + .iter() + .copied() + .filter(|(id, _)| !self.local.contains_key(id)) + .chain(self.local.iter().map(|(&id, &i)| (id, i))) + .collect(); + rows.sort_unstable_by_key(|&(id, _)| id); + rows + } + pub(super) fn freeze(&mut self) { + if !self.local.is_empty() { + self.base = Arc::new(Table::new(self.rows())); + self.local.clear(); + self.local.shrink_to_fit(); + } + } +} +impl Serialize for IdIndex { + fn serialize(&self, s: S) -> Result { + if self.local.is_empty() { + self.base.serialize(s) + } else { + Table::new(self.rows()).serialize(s) + } + } +} +impl<'de> Deserialize<'de> for IdIndex { + fn deserialize>(d: D) -> Result { + let table = Table::deserialize(d)?; + if table.rows.windows(2).any(|r| r[0].0 >= r[1].0) { + return Err(serde::de::Error::custom("unsorted or duplicate identities")); + } + if table.offsets != offsets(&table.rows) { + return Err(serde::de::Error::custom("invalid identity prefix offsets")); + } + Ok(Self { + base: Arc::new(table), + local: HashMap::new(), + }) + } +} +#[cfg(test)] +mod tests { + use super::*; + use crate::cache_codec; + #[test] + fn identity_table_preserves_overrides_and_shared_prefix() { + let mut index = IdIndex::default(); + for n in 1..=100 { + index.insert(Uuid::from_u128(n), n as usize); + } + index.freeze(); + let mut decoded: IdIndex = + cache_codec::decode(&cache_codec::encode(&index).unwrap()).unwrap(); + let retained = decoded.clone(); + assert!(Arc::ptr_eq(&decoded.base, &retained.base)); + decoded.insert(Uuid::from_u128(2), 202); + decoded.insert(Uuid::from_u128(101), 101); + for n in 1..=101 { + assert_eq!( + decoded.get(&Uuid::from_u128(n)), + Some(&(if n == 2 { 202 } else { n as usize })) + ); + } + assert!(decoded.get(&Uuid::nil()).is_none()); + let replay: IdIndex = cache_codec::decode(&cache_codec::encode(&decoded).unwrap()).unwrap(); + assert_eq!(replay.get(&Uuid::from_u128(2)), Some(&202)); + decoded.freeze(); + assert_eq!(decoded.base.rows.len(), 101); + assert_eq!(retained.get(&Uuid::from_u128(2)), Some(&2)); + assert!(retained.get(&Uuid::from_u128(101)).is_none()); + } + #[test] + fn identity_prefix_bounds_cover_empty_ranges_and_both_extremes() { + let mut index = IdIndex::default(); + let ids = [ + Uuid::nil(), + Uuid::from_u128(3 << 116), + Uuid::from_u128((3 << 116) + 9), + Uuid::from_u128(u128::MAX), + ]; + for (i, id) in ids.iter().enumerate() { + index.insert(*id, i); + } + index.freeze(); + let bytes = cache_codec::encode(&index).unwrap(); + let replay: IdIndex = cache_codec::decode(&bytes).unwrap(); + for (i, id) in ids.iter().enumerate() { + assert_eq!(replay.get(id), Some(&i)); + } + assert!(replay.get(&Uuid::from_u128(2 << 116)).is_none()); + assert!(replay.get(&Uuid::from_u128((3 << 116) + 5)).is_none()); + let mut table: Table = cache_codec::decode(&bytes).unwrap(); + table.offsets[3] = usize::MAX; + assert!(cache_codec::decode::(&cache_codec::encode(&table).unwrap()).is_err()); + table.offsets.clear(); + assert!(cache_codec::decode::(&cache_codec::encode(&table).unwrap()).is_err()); + } + #[test] + fn malformed_identity_order_is_rejected() { + for rows in [ + vec![(Uuid::from_u128(2), 0usize), (Uuid::from_u128(1), 1)], + vec![(Uuid::nil(), 0), (Uuid::nil(), 1)], + ] { + assert!( + cache_codec::decode::(&cache_codec::encode(&Table::new(rows)).unwrap()) + .is_err() + ); + } + } +} diff --git a/crates/sysmlv2-model/src/check/invocations.rs b/crates/sysmlv2-model/src/check/invocations.rs new file mode 100644 index 0000000..0a20199 --- /dev/null +++ b/crates/sysmlv2-model/src/check/invocations.rs @@ -0,0 +1,207 @@ +//! Invocation arity: a user-defined callable invoked with fewer +//! positional arguments than it declares parameters, or with a named +//! binding that names no parameter or names one twice. +use crate::{json::ResolvedModel, model::Model}; +use std::collections::HashSet; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // --- invocation arity --- + // A user-defined calculation invoked with fewer positional arguments + // than its declared `in`/`inout` parameters leaves the trailing + // parameters unbound — the result can never compute unless they carry + // defaults. Named bindings must name a parameter exactly once. + // Warnings are conservatively scoped: lambda bodies skipped, and both + // caller and callee must be outside the standard library (KFL + // functions overload their parameter lists). + let mut value_exprs: Vec<(usize, usize, sysmlv2_syntax::ast::Expr)> = + r.b.values + .iter() + .filter(|(o, _)| !model.is_library_unit(r.b.unit_of_elem(**o))) + .map(|(o, (s, e))| (*o, *s, e.clone())) + .collect(); + value_exprs.extend( + r.b.result_exprs + .iter() + .filter(|row| !model.is_library_unit(r.b.unit_of_elem(row.0))) + .cloned(), + ); + for (owner, scope, expr) in value_exprs { + let unit = r.b.unit_of_elem(owner); + if model.is_library_unit(unit) { + continue; + } + let mut sites = Vec::new(); + collect_invocations(&expr, &mut sites); + for (qn, args, span) in sites { + let Some(callee) = r.b.resolve(scope, qn, 0) else { + continue; + }; + let Some(params) = r.b.in_params.get(&callee).cloned() else { + continue; + }; + if model.is_library_unit(r.b.unit_of_elem(callee)) { + continue; // Library signatures can overload or use variadics. + } + if args.iter().any(|a| a.name.is_some()) + && !matches!( + r.b.elements[callee].ty, + "CalculationDefinition" | "CalculationUsage" | "Function" | "Expression" + ) + { + // Requirements/cases also bind implicit subject parameters; + // in_params alone is not their complete callable signature. + continue; + } + let mut bound = HashSet::new(); + let mut positional = 0; + let mut invalid = false; + for arg in args { + let name = match &arg.name { + Some(name) => name.to_display_string(), + None => { + let Some(name) = params.get(positional) else { + out.push((unit, Diagnostic::warning(span, format!( + "invocation of `{}` supplies {} arguments for {} parameter(s)", + qn.to_display_string(), args.len(), params.len() + )))); + invalid = true; + break; + }; + positional += 1; + name.clone() + } + }; + let message = if !params.contains(&name) { + Some(format!( + "invocation of `{}` names unknown parameter `{name}`", + qn.to_display_string() + )) + } else if !bound.insert(name.clone()) { + Some(format!( + "invocation of `{}` binds parameter `{name}` more than once", + qn.to_display_string() + )) + } else { + None + }; + if let Some(message) = message { + out.push((unit, Diagnostic::warning(arg.value.span, message))); + invalid = true; + } + } + if invalid { + continue; + } + let fields = r.b.ctor_fields.get(&callee); + let missing: Vec<_> = params + .iter() + .filter(|name| { + !bound.contains(*name) + && !fields + .and_then(|fs| fs.iter().find(|(n, _)| n == *name)) + .is_some_and(|(_, e)| r.b.values.contains_key(e)) + }) + .cloned() + .collect(); + if !missing.is_empty() { + out.push(( + unit, + Diagnostic::warning( + span, + format!( + "invocation of `{}` binds {} of its {} parameters (`{}` never bound)", + qn.to_display_string(), + bound.len(), + params.len(), + missing.join("`, `") + ), + ), + )); + } + } + } + out +} + +/// Collect every all-positional invocation site in an expression: +/// `(callee, positional-argument count, span)`. Lambda bodies (`Body`, +/// arrow/collect/select bodies) are not entered — their invocations +/// bind through runtime parameters this static pass cannot see. +fn collect_invocations<'a>( + e: &'a sysmlv2_syntax::ast::Expr, + out: &mut Vec<( + &'a sysmlv2_syntax::ast::QualifiedName, + &'a [sysmlv2_syntax::ast::Arg], + sysmlv2_syntax::Span, + )>, +) { + use sysmlv2_syntax::ast::{ArrowArgs, ExprKind, TargetRef}; + match &e.kind { + ExprKind::Literal(_) + | ExprKind::Null + | ExprKind::Ref(_) + | ExprKind::Extent { .. } + | ExprKind::MetadataAccess { .. } + | ExprKind::Body { .. } + | ExprKind::BodyTerminator => {} + ExprKind::Conditional { + cond, + then_branch, + else_branch, + } => { + collect_invocations(cond, out); + collect_invocations(then_branch, out); + collect_invocations(else_branch, out); + } + ExprKind::Binary { lhs, rhs, .. } => { + collect_invocations(lhs, out); + collect_invocations(rhs, out); + } + ExprKind::Unary { operand, .. } => collect_invocations(operand, out), + ExprKind::Classification { operand, .. } => { + if let Some(o) = operand { + collect_invocations(o, out); + } + } + ExprKind::ChainStep { target, .. } => collect_invocations(target, out), + ExprKind::Index { target, index } => { + collect_invocations(target, out); + collect_invocations(index, out); + } + ExprKind::Bracket { target, arg } => { + collect_invocations(target, out); + collect_invocations(arg, out); + } + ExprKind::Arrow { target, args, .. } => { + collect_invocations(target, out); + if let ArrowArgs::List(list) = args { + for a in list { + collect_invocations(&a.value, out); + } + } + } + ExprKind::Collect { target, .. } | ExprKind::Select { target, .. } => { + collect_invocations(target, out) + } + ExprKind::Invocation { ty, args } => { + if let TargetRef::Name(qn) = &**ty { + out.push((qn, args, e.span)); + } + for a in args { + collect_invocations(&a.value, out); + } + } + ExprKind::Constructor { args, .. } => { + for a in args { + collect_invocations(&a.value, out); + } + } + ExprKind::Sequence(items) => { + for i in items { + collect_invocations(i, out); + } + } + } +} diff --git a/crates/sysmlv2-model/src/check/multiplicities.rs b/crates/sysmlv2-model/src/check/multiplicities.rs new file mode 100644 index 0000000..d7a0873 --- /dev/null +++ b/crates/sysmlv2-model/src/check/multiplicities.rs @@ -0,0 +1,84 @@ +//! Multiplicity bounds. A bound that provably evaluates to something +//! other than a natural number, to a negative number, or to a lower end +//! above the upper end is an error; a bound that does not evaluate — an +//! unbound feature, a symbolic expression — stays undecided. +use super::user_rows; +use crate::{json::ResolvedModel, model::Model}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + let sites = user_rows(&r.b, model, r.b.multiplicities.iter(), |row| row.0); + for (owner, scope, mult) in sites { + let upper = crate::eval::evaluate_expr_in(&mut r.b, scope, &mult.upper).ok(); + let lower = match &mult.lower { + Some(l) => crate::eval::evaluate_expr_in(&mut r.b, scope, l).ok(), + None => None, + }; + // Unknown symbolic bounds remain undecided. A known scalar of the + // wrong kind, fractional count, or collection is not a multiplicity. + // Infinity denotes an unbounded upper end, never a lower end. + for (value, upper_end, span) in [ + (upper.as_ref(), true, mult.upper.span), + ( + lower.as_ref(), + false, + mult.lower.as_ref().map_or(mult.span, |e| e.span), + ), + ] { + use crate::eval::Value; + let invalid = match value { + None | Some(Value::Indeterminate | Value::Unbound(_) | Value::UnboundMember(_)) => { + false + } + Some(Value::Integer(_)) => false, + Some(Value::Rational(v)) => !v.is_integer(), + Some(Value::Real(v)) => { + !(v.is_finite() && v.fract() == 0.0 || upper_end && *v == f64::INFINITY) + } + Some(_) => true, + }; + if invalid { + out.push(( + r.b.unit_of_elem(owner), + Diagnostic::error( + span, + "multiplicity bound must be a Natural number (or `*` for the upper bound)", + ), + )); + } + } + let lo = lower.as_ref().and_then(super::scalar_f64); + let hi = upper.as_ref().and_then(super::scalar_f64); + if let Some(lo) = lo { + if lo < 0.0 { + out.push(( + r.b.unit_of_elem(owner), + Diagnostic::error(mult.span, "multiplicity lower bound is negative"), + )); + continue; + } + } + if let Some(hi) = hi { + if hi < 0.0 { + out.push(( + r.b.unit_of_elem(owner), + Diagnostic::error(mult.span, "multiplicity upper bound is negative"), + )); + continue; + } + } + if let (Some(lo), Some(hi)) = (lo, hi) { + if lo > hi { + out.push(( + r.b.unit_of_elem(owner), + Diagnostic::error( + mult.span, + format!("multiplicity lower bound {lo} exceeds upper bound {hi}"), + ), + )); + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/relationships.rs b/crates/sysmlv2-model/src/check/relationships.rs new file mode 100644 index 0000000..49f2762 --- /dev/null +++ b/crates/sysmlv2-model/src/check/relationships.rs @@ -0,0 +1,402 @@ +//! Declared and implied relationship contracts over resolved graph facts. +use super::{ + expressions, + facts::{Facts, flag, is}, +}; +use crate::{ + json::{Builder, ResolvedModel}, + model::Model, +}; +use sysmlv2_syntax::{ + Span, + ast::{Expr, ExprKind, TargetRef}, + diag::Diagnostic, +}; + +pub(super) fn featured_within(b: &Builder, g: &Facts, feature: usize, context: usize) -> bool { + let mut featuring = g.relations(b, feature, "TypeFeaturing", "featuringType"); + if let Some(o) = g.featuring(b, feature) { + featuring.push(o); + } + if featuring.is_empty() { + return true; + } + let mut current = Some(context); + let mut seen = std::collections::HashSet::new(); + while let Some(context) = current { + if !seen.insert(context) { + break; + } + let contexts = g.context(context); + if featuring.iter().any(|f| contexts.contains(f)) { + return true; + } + current = g.owner[context]; + } + false +} + +/// Binding is symmetric and permits multiple classification. Unknown types do +/// not prove a mismatch; every known type on either side needs a conforming peer. +pub(super) fn incompatible(b: &mut Builder, g: &Facts, a: &[usize], z: &[usize]) -> bool { + if a.is_empty() || z.is_empty() { + return false; + } + !a.iter().any(|&x| { + z.iter().any(|&y| { + g.context(x).contains(&y) + || g.context(y).contains(&x) + || b.conforms_upward_semantic(x, y) + || b.conforms_upward_semantic(y, x) + }) + }) +} +fn subject(b: &Builder, g: &Facts, e: usize) -> Option { + g.effective_members(b, e).into_iter().find(|&m| { + b.elements[m] + .owning_relationship + .is_some_and(|r| is(b, r, "SubjectMembership")) + }) +} +pub(super) fn validate( + r: &mut ResolvedModel, + model: &Model, + g: &Facts, +) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + let mut errors = Vec::new(); + let mut bindings: Vec<(usize, Span, Vec, Vec)> = Vec::new(); + for e in 0..r.b.explicit_len() { + let b = &r.b; + let unit = b.unit_of_elem(e); + if model.is_library_unit(unit) { + continue; + } + let span = g.span(b, e); + let mut report = |rule, msg| errors.push((unit, span, rule, msg)); + let ends: Vec<_> = if is(b, e, "Association") || is(b, e, "Connector") { + g.effective_members(b, e) + .into_iter() + .filter(|&m| flag(b, m, "isEnd")) + .collect() + } else { + Vec::new() + }; + if is(b, e, "BindingConnector") { + if !ends.is_empty() && ends.len() != 2 { + report( + "validateBindingConnectorIsBinary", + "A binding connector must have exactly two ends", + ); + } + if let [a, z] = ends.as_slice() { + bindings.push((unit, span, g.typed(b, *a), g.typed(b, *z))); + } + } + if is(b, e, "Connector") && !flag(b, e, "isAbstract") && ends.len() == 1 { + report( + "validateConnectorRelatedFeatures", + "A concrete connector must relate at least two features", + ); + } + if is(b, e, "Association") + && ends.len() > 2 + && g.closure(e) + .iter() + .any(|&t| g.named(b, t, "Links::BinaryLink")) + { + report( + "validateAssociationBinarySpecialization", + "An association with more than two ends cannot specialize BinaryLink", + ); + } + let inline_cross = b.owned_cross_features.get(&e).copied(); + if let Some(cross) = inline_cross { + let mut a = g.typed(b, e); + let mut z = g.typed(b, cross); + a.sort_unstable(); + a.dedup(); + z.sort_unstable(); + z.dedup(); + if !a.is_empty() && !z.is_empty() && a != z { + report( + "validateFeatureCrossFeatureType", + "An inline cross feature must have the same types as its end feature", + ); + } + if !g + .relations(b, e, "CrossSubsetting", "crossedFeature") + .is_empty() + { + report( + "feature-cross-feature-single", + "An end cannot declare both an inline cross feature and a cross subsetting", + ); + } + } + for crossed in g.relations(b, e, "CrossSubsetting", "crossedFeature") { + let owner_ends = g + .featuring(b, e) + .map(|o| { + g.effective_members(b, o) + .into_iter() + .filter(|&m| flag(b, m, "isEnd")) + .count() + }) + .unwrap_or(0); + if !flag(b, e, "isEnd") || owner_ends < 2 { + report( + "validateCrossSubsettingCrossingFeature", + "A crossing feature must be an end of a type with at least two ends", + ); + } else { + let links = g.relations(b, crossed, "FeatureChaining", "chainingFeature"); + let other = g + .featuring(b, e) + .map(|o| { + g.effective_members(b, o) + .into_iter() + .filter(|&m| flag(b, m, "isEnd") && m != e) + .collect::>() + }) + .unwrap_or_default(); + if links.len() != 2 || (other.len() == 1 && links.first() != other.first()) { + report( + "validateCrossSubsettingCrossedFeature", + "A cross subsetting must chain through an opposite end to a feature", + ); + } + if let Some(&terminal) = links.last() { + for redefined in g.redefined(b, e) { + for old_cross in + g.relations(b, redefined, "CrossSubsetting", "crossedFeature") + { + if let Some(old_terminal) = g + .relations(b, old_cross, "FeatureChaining", "chainingFeature") + .last() + { + if !g.closure(terminal).contains(old_terminal) { + report( + "validateFeatureCrossFeatureSpecialization", + "A cross feature must specialize the cross feature of the redefined end", + ); + } + } + } + } + } + let mut a = g.typed(b, e); + let mut z = g.typed(b, crossed); + a.sort_unstable(); + a.dedup(); + z.sort_unstable(); + z.dedup(); + if !a.is_empty() && !z.is_empty() && a != z { + report( + "validateFeatureCrossFeatureType", + "A cross feature must have the same types as its end feature", + ); + } + } + } + let chain = g.relations(b, e, "FeatureChaining", "chainingFeature"); + for pair in chain.windows(2) { + if !is(b, pair[1], "Feature") || !featured_within(b, g, pair[1], pair[0]) { + report( + "validateFeatureChainingFeatureConformance", + "Each chain member must be a feature accessible through the preceding feature", + ); + } + } + for original in g.relations(b, e, "Conjugation", "originalType") { + if is(b, e, "Feature") && is(b, original, "Classifier") && g.typed(b, e).is_empty() { + report( + "validateFeatureHasType", + "Conjugating a classifier does not provide a feature type", + ); + } + if is(b, e, "Structure") && !g.closure(original).iter().any(|&t| is(b, t, "Structure")) + { + report( + "validateClassifierDefaultSupertype", + "A structure must directly or indirectly specialize Objects::Object", + ); + } + } + if is(b, e, "Specialization") { + let specific = [ + "specific", + "subclassifier", + "subsettingFeature", + "typedFeature", + "redefiningFeature", + ] + .iter() + .find_map(|key| g.target(b, e, key)); + if let Some(s) = specific { + if !g.relations(b, s, "Conjugation", "originalType").is_empty() { + report( + "validateSpecializationSpecificNotConjugated", + "A conjugated type cannot be the specific type of a specialization", + ); + } + } + } + if r.b.elements[e].ty == "RequirementUsage" { + if let (Some(s), Some(parent)) = + (subject(b, g, e), g.owner[e].and_then(|o| subject(b, g, o))) + { + bindings.push((unit, span, g.typed(b, s), g.typed(b, parent))); + } + } + } + for (i, (e, kind, _, qn)) in r.b.spec_targets.iter().enumerate() { + if *kind != "Subsetting" { + continue; + } + let Some(t) = r.b.spec_resolved.get(i).copied().flatten() else { + continue; + }; + let unit = r.b.unit_of_elem(*e); + if model.is_library_unit(unit) { + continue; + } + if let Some(context) = g.featuring(&r.b, *e) { + if !featured_within(&r.b, g, t, context) { + errors.push(( + unit, + qn.span, + "validateSubsettingFeaturingTypes", + "A subsetted feature must be accessible in the subsetting feature's context", + )); + } + } + } + for end in 0..r.b.explicit_len() { + let b = &r.b; + let unit = b.unit_of_elem(end); + if model.is_library_unit(unit) || !is(b, end, "FlowEnd") { + continue; + } + if !g + .relations(b, end, "ReferenceSubsetting", "referencedFeature") + .is_empty() + { + continue; + } + let Some(flow) = g.owner[end] else { + continue; + }; + let Some(context) = g.featuring(b, flow) else { + continue; + }; + for &member in &g.members[end] { + for target in g.relations(b, member, "Redefinition", "redefinedFeature") { + if let Some(featuring) = g.featuring(b, target) { + if featured_within(b, g, target, context) { + if !b.payload_flows.contains(&flow) { + continue; + } + errors.push((unit, g.span(b, flow), "validateFlowEndSubsetting", "A flow end must identify a participant's payload feature using dot notation")); + } else { + let rule = if is(b, featuring, "Classifier") { + "validateFlowEndSubsetting" + } else { + "validateFlowEndImplicitSubsetting" + }; + errors.push((unit, g.span(b, flow), rule, "A nested flow end must identify an accessible feature using dot notation")); + } + } + } + } + } + for (e, (scope, expr)) in super::user_entries(&r.b, model, r.b.values.iter()) { + let unit = r.b.unit_of_elem(e); + if let ExprKind::Ref(_) = &expr.kind { + if let (Some(context), Some(t)) = ( + g.featuring(&r.b, e), + expressions::referent(&mut r.b, scope, &expr), + ) { + if !featured_within(&r.b, g, t, context) { + errors.push(( + unit, + expr.span, + "validateConnectorTypeFeaturing", + "A bound feature reference must be accessible in the binding's context", + )); + } + } + } + } + for (e, scope, expr) in super::user_rows(&r.b, model, r.b.result_exprs.iter(), |row| row.0) { + let unit = r.b.unit_of_elem(e); + let returns: Vec<_> = g + .effective_members(&r.b, e) + .into_iter() + .filter(|&m| { + r.b.elements[m] + .owning_relationship + .is_some_and(|rel| is(&r.b, rel, "ReturnParameterMembership")) + }) + .collect(); + if let [ret] = returns.as_slice() { + let a = g.typed(&r.b, *ret); + let z = expressions::types(&mut r.b, g, scope, &expr, 0); + bindings.push((unit, expr.span, a, z)); + } + } + for (e, scope, target) in super::user_rows(&r.b, model, r.b.satisfy_by.iter(), |row| row.0) { + let unit = r.b.unit_of_elem(e); + if let (Some(s), TargetRef::Name(qn)) = + (subject(&r.b, g, g.feature_target(&r.b, e)), target) + { + let span = qn.span; + let a = g.typed(&r.b, s); + let z = expressions::types( + &mut r.b, + g, + scope, + &Expr { + kind: ExprKind::Ref(qn), + span, + }, + 0, + ); + bindings.push((unit, span, a, z)); + } + } + for (unit, span, a, z) in bindings { + if incompatible(&mut r.b, g, &a, &z) { + let names = |ts: &[usize]| { + ts.iter() + .map(|&t| { + r.b.elements[t] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + .unwrap_or("") + }) + .collect::>() + .join(", ") + }; + out.push(( + unit, + super::rule_warning( + span, + "validateBindingConnectorTypeConformance", + format!( + "Bound feature types ({}) and ({}) should conform", + names(&a), + names(&z) + ), + ), + )); + } + } + out.extend( + errors + .into_iter() + .map(|(u, s, rule, msg)| (u, super::rule_error(s, rule, msg))), + ); + out +} diff --git a/crates/sysmlv2-model/src/check/scalars.rs b/crates/sysmlv2-model/src/check/scalars.rs new file mode 100644 index 0000000..e4887e8 --- /dev/null +++ b/crates/sysmlv2-model/src/check/scalars.rs @@ -0,0 +1,209 @@ +//! Feature-value scalar conformance: a bound value whose evaluated +//! scalar partition can never inhabit any of the feature's declared +//! types. +use crate::{json::ResolvedModel, model::Model}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // --- feature-value scalar conformance --- + // Narrowed to what is provable. A stricter static rule — the value + // expression's *declared* result type must conform to the feature's + // declared type — would reject 15 official corpus files whose bindings + // are legal under KerML multiple classification: a `Rational`-typed + // literal's value may well inhabit a sibling subtype of `Real` + // (`ScalarValues::Rational does not conform to EnumerationTest::Size` + // is exactly the corpus's enum-restriction idiom, and the ISO-8601 + // string encodings and metadata levels follow the same shape). What + // *is* provable is kind-level disjointness of the evaluated value: + // `ScalarValues` partitions its scalars into Boolean, String, and the + // Number tower, and a value of one partition is never an instance of + // a type in another; within the tower, a non-integral rational is + // never an instance of an `Integer`-conforming type. Declared types + // classify by simple scalar names over the explicit supertype closure + // (the solver's `declared_sort` discipline — works with or without + // the standard library); an untyped redefining feature borrows the + // redefinition target's declared types (one hop). Unclassifiable + // declared types, unevaluable values, quantities, sequences, and + // element values all stay silent. Warnings, per checker policy. + let value_sites: Vec<(usize, usize, sysmlv2_syntax::ast::Expr)> = + r.b.values + .iter() + .filter(|(o, _)| !model.is_library_unit(r.b.unit_of_elem(**o))) + .map(|(o, (s, e))| (*o, *s, e.clone())) + .collect(); + for (owner, scope, expr) in value_sites { + let unit = r.b.unit_of_elem(owner); + if model.is_library_unit(unit) { + continue; + } + let mut tys = r.b.direct_typing_elems(owner); + if tys.is_empty() { + for t in r.b.redefinition_target_elems(owner) { + for ty in r.b.direct_typing_elems(t) { + if !tys.contains(&ty) { + tys.push(ty); + } + } + } + } + // Every declared type must classify — a type this walk cannot + // place may admit the value through bases it cannot see. + let kinds: Vec = tys + .iter() + .filter_map(|&ty| declared_scalar_kind(&mut r.b, ty)) + .collect(); + if kinds.is_empty() || kinds.len() != tys.len() { + continue; + } + let Ok(v) = crate::eval::evaluate_expr_in(&mut r.b, scope, &expr) else { + continue; // undecided, not wrong + }; + let Some(value_kind) = value_scalar_kind(&v) else { + continue; // quantities, sequences, instances, elements + }; + if kinds.iter().any(|&k| scalar_kind_admits(k, value_kind)) { + continue; + } + let ty_name = r.b.elements[tys[0]] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + .unwrap_or("") + .to_string(); + let msg = match value_kind { + ScalarKind::Number { integral: false } + if matches!(kinds[0], ScalarKind::Number { .. }) => + { + format!( + "feature value {v} is not an integer and can never conform \ + to the declared type `{ty_name}`" + ) + } + _ => { + let vdesc = match value_kind { + ScalarKind::Boolean => "a Boolean", + ScalarKind::Str => "a String", + ScalarKind::Number { .. } => "a number", + }; + format!( + "feature value evaluates to {vdesc}, which can never \ + conform to the declared type `{ty_name}`" + ) + } + }; + out.push((unit, Diagnostic::warning(expr.span, msg))); + } + out +} + +/// The provably-disjoint `ScalarValues` partitions: Boolean, String, and +/// the Number tower (with `Integer`-and-below tracked for integrality). +#[derive(Clone, Copy, PartialEq)] +enum ScalarKind { + Boolean, + Str, + Number { integral: bool }, +} + +/// The partition an evaluated value inhabits — `None` for the values +/// the conformance check stays silent on (quantities, sequences, +/// instances, elements). +fn value_scalar_kind(v: &crate::eval::Value) -> Option { + use crate::eval::Value; + Some(match v { + Value::Boolean(_) => ScalarKind::Boolean, + Value::String(_) => ScalarKind::Str, + Value::Integer(_) => ScalarKind::Number { integral: true }, + Value::Rational(r) => ScalarKind::Number { + integral: r.is_integer(), + }, + Value::Real(f) => ScalarKind::Number { + integral: f.fract() == 0.0 && f.is_finite(), + }, + _ => return None, + }) +} + +/// Whether a declared partition admits a value's: same partition, and +/// within the Number tower an integral requirement met by an integral +/// value. Cross-partition pairs are provably disjoint. +fn scalar_kind_admits(decl: ScalarKind, value: ScalarKind) -> bool { + match (decl, value) { + (ScalarKind::Boolean, ScalarKind::Boolean) => true, + (ScalarKind::Str, ScalarKind::Str) => true, + (ScalarKind::Number { integral: need }, ScalarKind::Number { integral: have }) => { + !need || have + } + _ => false, + } +} + +impl crate::json::ResolvedModel { + /// The feature-value scalar-conformance verdict the semantic check + /// would reach for `value` bound to a feature declaring exactly + /// `declared` as its types: `Some(false)` when the check would + /// report the value as never conforming, `Some(true)` when some + /// declared type admits it, `None` where the check stays silent + /// (no declared type, a declared type it cannot classify, or a + /// non-scalar value). Lets a fix that writes a typing verify its + /// result against the value before offering it. + pub fn scalar_value_admitted( + &mut self, + declared: &[crate::json::ElementRef], + value: &crate::eval::Value, + ) -> Option { + let kinds: Vec = declared + .iter() + .filter_map(|t| declared_scalar_kind(&mut self.b, t.0)) + .collect(); + if kinds.is_empty() || kinds.len() != declared.len() { + return None; + } + let value_kind = value_scalar_kind(value)?; + Some(kinds.iter().any(|&k| scalar_kind_admits(k, value_kind))) + } +} + +/// Classify a declared type into its scalar partition by walking the +/// explicit typing/specialization closure and matching the `ScalarValues` +/// simple names — the same name-based discipline as the solver's +/// `declared_sort`, so it works with or without the standard library. +/// Breadth-first, first match wins: the nearest scalar ancestor decides +/// integrality (`Size :> Real` classifies non-integral even though `Real` +/// has integral subtypes). `None` = not provably a scalar type. +fn declared_scalar_kind(b: &mut crate::json::Builder, ty: usize) -> Option { + use std::collections::{HashSet, VecDeque}; + let mut queue: VecDeque = VecDeque::new(); + queue.push_back(ty); + let mut seen: HashSet = HashSet::new(); + let mut steps = 0; + while let Some(t) = queue.pop_front() { + if !seen.insert(t) { + continue; + } + steps += 1; + if steps > 64 { + break; + } + let name = b.elements[t] + .props + .get("declaredName") + .and_then(|v| v.as_str()); + match name { + Some("Boolean") => return Some(ScalarKind::Boolean), + Some("String") => return Some(ScalarKind::Str), + Some("Integer" | "Natural" | "Positive") => { + return Some(ScalarKind::Number { integral: true }); + } + Some("NumericalValue" | "Number" | "Complex" | "Real" | "Rational") => { + return Some(ScalarKind::Number { integral: false }); + } + _ => {} + } + for s in b.explicit_supertype_elems(t) { + queue.push_back(s); + } + } + None +} diff --git a/crates/sysmlv2-model/src/check/specialization.rs b/crates/sysmlv2-model/src/check/specialization.rs new file mode 100644 index 0000000..37d985b --- /dev/null +++ b/crates/sysmlv2-model/src/check/specialization.rs @@ -0,0 +1,345 @@ +//! Checks over the declared specialization edges of an element — +//! subclassification cycles and duplicates, the metaclass a metadata +//! feature is typed by, the conformance a redefinition owes its target, +//! and the binariness a connector inherits through one. +use super::user_rows; +use crate::{json::ResolvedModel, model::Model}; +use std::collections::{HashMap, HashSet}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // --- subclassification self-reference / cycles / duplicates --- + // Library-owned specializations can't produce findings (every check + // below skips library owners) and can't participate in a user-visible + // cycle (no library edge points into a user definition) — skipping + // them keeps the semantic pass proportional to the user model. + let specs = user_rows(&r.b, model, r.b.spec_targets.iter(), |row| row.0); + // Resolve every recorded target once. + let mut resolved: Vec<( + usize, + &'static str, + usize, + &sysmlv2_syntax::ast::QualifiedName, + )> = Vec::new(); + for (owner, kind, scope, qn) in &specs { + if let Some(t) = r.b.resolve(*scope, qn, 0) { + resolved.push((*owner, kind, t, qn)); + } + } + let mut subcl_edges: HashMap> = HashMap::new(); + let mut seen_per_owner: HashSet<(usize, &'static str, usize)> = HashSet::new(); + for (owner, kind, target, qn) in &resolved { + let unit = r.b.unit_of_elem(*owner); + let is_lib = model.is_library_unit(unit); + if *kind == "Subclassification" { + if target == owner && !is_lib { + out.push(( + unit, + Diagnostic::error( + qn.span, + format!("`{}` cannot specialize itself", qn.to_display_string()), + ), + )); + continue; + } + subcl_edges.entry(*owner).or_default().push(*target); + } + if !seen_per_owner.insert((*owner, kind, *target)) && !is_lib { + out.push(( + unit, + Diagnostic::warning( + qn.span, + format!("duplicate specialization of `{}`", qn.to_display_string()), + ), + )); + } + } + // Cycle detection over subclassification edges (self-edges reported above). + for (owner, kind, _, qn) in &resolved { + if *kind != "Subclassification" { + continue; + } + let unit = r.b.unit_of_elem(*owner); + if model.is_library_unit(unit) { + continue; + } + // DFS from each of owner's supertypes back to owner. + let mut stack: Vec = subcl_edges.get(owner).cloned().unwrap_or_default(); + let mut seen: HashSet = HashSet::new(); + let mut cyclic = false; + while let Some(s) = stack.pop() { + if s == *owner { + cyclic = true; + break; + } + if seen.insert(s) { + if let Some(next) = subcl_edges.get(&s) { + stack.extend(next); + } + } + } + if cyclic { + out.push(( + unit, + Diagnostic::error( + qn.span, + "circular specialization: this definition transitively \ + specializes itself" + .to_string(), + ), + )); + } + } + + // --- metadata feature typing --- + // A metadata feature must be typed by exactly one metaclass — a + // `metadata def` (SysML) or `metaclass` (KerML). A typing that + // resolves to any other kind of element is provably wrong (error); + // unresolved targets stay referential warnings, per checker policy. + let mut metadata_typing_count: HashMap = HashMap::new(); + for (owner, kind, _, _) in &specs { + if *kind == "FeatureTyping" + && matches!(r.b.elements[*owner].ty, "MetadataUsage" | "MetadataFeature") + { + *metadata_typing_count.entry(*owner).or_insert(0) += 1; + } + } + let mut metadata_first_typing: HashSet = HashSet::new(); + for (owner, kind, target, qn) in &resolved { + if *kind != "FeatureTyping" + || !matches!(r.b.elements[*owner].ty, "MetadataUsage" | "MetadataFeature") + { + continue; + } + let unit = r.b.unit_of_elem(*owner); + if model.is_library_unit(unit) { + continue; + } + let target_ty = r.b.elements[*target].ty; + if !matches!(target_ty, "MetadataDefinition" | "Metaclass") { + out.push(( + unit, + Diagnostic::error( + qn.span, + format!( + "metadata must be typed by a metadata definition or \ + metaclass; `{}` is a {}", + qn.to_display_string(), + target_ty + ), + ), + )); + } else if metadata_typing_count.get(owner).copied().unwrap_or(0) > 1 + && !metadata_first_typing.insert(*owner) + { + out.push(( + unit, + Diagnostic::error( + qn.span, + "metadata must be typed by exactly one metaclass".to_string(), + ), + )); + } + } + + // Numeric bounds of a multiplicity: `[l..u]` directly, `[u]` is + // exact (`l = u`) except `[*]`, whose missing lower is 0. + let bounds = |r: &mut crate::json::ResolvedModel, + scope: usize, + m: &sysmlv2_syntax::ast::Multiplicity| + -> Option<(f64, f64)> { + let hi = + super::scalar_f64(&crate::eval::evaluate_expr_in(&mut r.b, scope, &m.upper).ok()?)?; + let lo = match &m.lower { + Some(l) => super::scalar_f64(&crate::eval::evaluate_expr_in(&mut r.b, scope, l).ok()?)?, + None if hi.is_infinite() => 0.0, + None => hi, + }; + Some((lo, hi)) + }; + + // --- redefinition type-compatibility --- + // A redefining feature's declared types should conform to the + // redefined feature's declared types (KerML 8.4 redefinition + // conformance). Checked only when both sides carry explicit typings + // and the target's type is user-owned — the explicit closure is + // complete between user types, while conformance to a *library* + // type may ride implied bases this walk cannot see (those stay + // silent). Deliberately NOT checked for `Subsetting`: KerML's + // multiple classification lets a value be both a `Cause` and a + // `Situation` without `Cause` specializing `Situation`, and the + // official `Model Library Example.sysml` uses exactly that pattern + // (`causes : Cause[*] :> situations`). Warnings, per checker policy. + for i in 0..r.b.spec_targets.len() { + let (owner, kind) = { + let t = &r.b.spec_targets[i]; + (t.0, t.1) + }; + if !matches!(kind, "Redefinition" | "Subsetting") { + continue; + } + let unit = r.b.unit_of_elem(owner); + if model.is_library_unit(unit) { + continue; + } + // The builder's pending pass already resolved this target with the + // owner excluded (`:>> x` names the *inherited* feature) — read the + // recorded outcome instead of re-resolving, which self-hits and + // falls through to full import scans (~0.2 ms per redefinition). + let Some(target) = r.b.spec_resolved.get(i).copied().flatten() else { + continue; // unresolved targets are the referential checks' job + }; + if target == owner { + continue; + } + let qn = r.b.spec_targets[i].3.clone(); + // Multiplicity conformance: when both sides declare + // explicit numeric multiplicities, the redefining range must + // lie within the redefined one. + // Copied out of the table because evaluating the bounds needs + // the builder mutably; only the two clauses in play are copied. + let declared = |r: &mut crate::json::ResolvedModel, e: usize| { + r.b.declared_multiplicity_of(e).map(|(s, m)| (s, m.clone())) + }; + if let (Some((os, om)), Some((ts, tm))) = (declared(r, owner), declared(r, target)) { + let span = om.span; + if let (Some((olo, ohi)), Some((tlo, thi))) = (bounds(r, os, &om), bounds(r, ts, &tm)) { + // A subset may have fewer values; only redefinition must + // preserve the lower bound as well as the upper bound. + if (kind == "Redefinition" && olo < tlo) || ohi > thi { + out.push(( + unit, + Diagnostic::warning( + span, + if kind == "Redefinition" { + format!("redefining multiplicity [{olo}..{ohi}] is not within the redefined feature's [{tlo}..{thi}]") + } else { + format!("subsetting multiplicity upper bound {ohi} exceeds the subsetted feature's upper bound {thi}") + }, + ), + )); + } + } + } + if kind == "Subsetting" { + continue; // Multiple classification permits heterogeneous types. + } + let own_types = r.b.direct_typing_elems(owner); + if own_types.is_empty() { + continue; + } + for tt in r.b.direct_typing_elems(target) { + if tt < r.b.lib_boundary { + continue; // may conform via implied bases + } + if own_types.iter().any(|&ot| r.b.conforms_upward(ot, tt)) { + continue; + } + out.push(( + unit, + Diagnostic::warning( + qn.span, + format!( + "feature redefines `{}` but none of its declared types \ + conform to the target's type `{}`", + qn.to_display_string(), + r.b.elements[tt] + .props + .get("declaredName") + .and_then(|v| v.as_str()) + .unwrap_or("") + ), + ), + )); + } + } + // --- connector binary specialization (KerML + // checkConnectorBinarySpecialization) --- + // A connector with more than two ends must not specialize a *binary* + // connector: binary means a library binary-links family element, or a + // user connector-family element with exactly two ends (the two-end + // shape implies the binary library base). The n-ary declaration + // itself is legal — the offending edge is the typing/subsetting/ + // redefinition that demands binariness, so the diagnostic lands on + // that target's spelling. + { + let connector_family = |ty: &str| { + matches!( + ty, + "ConnectionUsage" + | "ConnectionDefinition" + | "InterfaceUsage" + | "InterfaceDefinition" + | "AllocationUsage" + | "AllocationDefinition" + | "Connector" + | "BindingConnector" + ) + }; + let end_count = |b: &crate::json::Builder, e: usize| { + b.elements[e] + .owned_relationships + .iter() + .filter(|&&rel| b.elements[rel].ty == "EndFeatureMembership") + .count() + }; + // The library binary-links family, resolved once (absent without + // the library — the user-side two-end test still applies). + let mut binary_lib: HashSet = HashSet::new(); + for qn in [ + "Links::binaryLinks", + "Links::BinaryLink", + "Connections::binaryConnections", + "Connections::BinaryConnection", + "Interfaces::binaryInterfaces", + "Interfaces::BinaryInterface", + ] { + if let Some(t) = r.b.resolve(0, &crate::json::lib_qn(qn), 0) { + binary_lib.insert(t); + } + } + let is_binary_node = |b: &mut crate::json::Builder, + binary_lib: &HashSet, + n: usize| { + binary_lib.contains(&n) || (connector_family(b.elements[n].ty) && end_count(b, n) == 2) + }; + for (owner, kind, target, qn) in &resolved { + if !matches!(*kind, "FeatureTyping" | "Subsetting" | "Redefinition") { + continue; + } + if !connector_family(r.b.elements[*owner].ty) || end_count(&r.b, *owner) <= 2 { + continue; + } + // Binary directly, or anywhere up the target's explicit closure. + let mut binary = is_binary_node(&mut r.b, &binary_lib, *target); + if !binary { + let mut seen: HashSet = HashSet::new(); + let mut stack = vec![*target]; + while let Some(n) = stack.pop() { + if !seen.insert(n) { + continue; + } + if is_binary_node(&mut r.b, &binary_lib, n) { + binary = true; + break; + } + stack.extend(r.b.explicit_supertype_elems(n)); + } + } + if binary { + let ends = end_count(&r.b, *owner); + out.push(( + r.b.unit_of_elem(*owner), + Diagnostic::warning( + qn.span, + format!( + "connector with {ends} ends specializes a binary connector (a binary connector cannot have more than two ends)" + ), + ), + )); + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/structural.rs b/crates/sysmlv2-model/src/check/structural.rs new file mode 100644 index 0000000..c5eae94 --- /dev/null +++ b/crates/sysmlv2-model/src/check/structural.rs @@ -0,0 +1,668 @@ +//! Static ownership, specialization, and feature-property constraints. +use super::facts::{Facts, flag, is}; +use crate::{ + json::{Builder, ResolvedModel}, + model::Model, +}; +use sysmlv2_syntax::{Span, diag::Diagnostic}; + +fn occurrence(b: &Builder, g: &Facts, e: usize) -> bool { + is(b, e, "Class") + || is(b, e, "OccurrenceUsage") + || g.typed(b, e).iter().any(|&t| is(b, t, "Class")) +} +pub(super) fn variable(b: &Builder, g: &Facts, e: usize) -> bool { + if flag(b, e, "isVariable") { + return true; + } + if !is(b, e, "Usage") { + return false; + } + // SysML derives variability from an occurrence owning type. A portion + // is a time slice/snapshot rather than a variable feature. + !flag(b, e, "isPortion") + && !b.elements[e] + .props + .get("portionKind") + .is_some_and(|p| p.is_string()) + && g.featuring(b, e).is_some_and(|o| occurrence(b, g, o)) +} +pub(super) fn validate(r: &ResolvedModel, model: &Model, g: &Facts) -> Vec<(usize, Diagnostic)> { + let b = &r.b; + let mut out = Vec::new(); + let mut report = |e: usize, span: Span, rule: &'static str, msg: &str| { + let unit = b.unit_of_elem(e); + if !model.is_library_unit(unit) { + out.push((unit, super::rule_error(span, rule, msg))); + } + }; + for (i, (e, kind, _, qn)) in b.spec_targets.iter().enumerate() { + if !matches!(*kind, "Subclassification" | "Subsetting") || !is(b, *e, "Classifier") { + continue; + } + let Some(t) = b.spec_resolved.get(i).copied().flatten() else { + continue; + }; + let cases = [ + ( + is(b, *e, "DataType") && (is(b, t, "Class") || is(b, t, "Association")), + "validateDataTypeSpecialization", + "A data type cannot specialize a class or association", + ), + ( + is(b, *e, "Class") + && (is(b, t, "DataType") + || (is(b, t, "Association") && !is(b, *e, "Association"))), + "validateClassSpecialization", + "A class cannot specialize a data type or an unrelated association family", + ), + ( + is(b, *e, "Structure") && is(b, t, "Behavior") && !is(b, t, "Structure"), + "validateStructureSpecialization", + "A structure cannot specialize a behavior", + ), + ( + is(b, *e, "Behavior") && is(b, t, "Structure") && !is(b, t, "Behavior"), + "validateBehaviorSpecialization", + "A behavior cannot specialize a structure", + ), + ]; + for (bad, rule, msg) in cases { + if bad { + report(*e, qn.span, rule, msg); + } + } + } + for (i, (e, kind, _, qn)) in b.spec_targets.iter().enumerate() { + let Some(t) = b.spec_resolved.get(i).copied().flatten() else { + continue; + }; + if !matches!(*kind, "Subsetting" | "Redefinition") { + continue; + } + if *kind == "Redefinition" { + if g.featuring(b, *e).is_some() && g.featuring(b, *e) == g.featuring(b, t) { + report( + *e, + qn.span, + "validateRedefinitionFeaturingTypes", + "Redefining and redefined features cannot have the same owning type", + ); + } + if flag(b, t, "isEnd") && !flag(b, *e, "isEnd") { + report( + *e, + qn.span, + "validateRedefinitionEndConformance", + "A feature redefining an end must itself be an end", + ); + } + let from = b.elements[*e] + .props + .get("direction") + .and_then(|v| v.as_str()); + let to = g + .featuring(b, *e) + .and_then(|o| g.direction_through(b, o, t)); + if from.is_some() && to.is_some() && from != to && to != Some("inout") { + report( + *e, + qn.span, + "validateRedefinitionDirectionConformance", + "A redefining feature must have a compatible direction", + ); + } + if g.featuring(b, *e).is_none() && g.featuring(b, t).is_none() { + report( + *e, + qn.span, + "validateRedefinitionFeaturingTypes", + "A package-level feature cannot redefine another package-level feature", + ); + } + } + if flag(b, *e, "isVariable") && !flag(b, *e, "isConstant") && flag(b, t, "isConstant") { + report( + *e, + qn.span, + "validateSubsettingConstantConformance", + "A variable subset of a constant feature must be constant", + ); + } + if b.elements[*e] + .props + .get("isUnique") + .and_then(|v| v.as_bool()) + == Some(false) + && flag(b, t, "isUnique") + { + report( + *e, + qn.span, + "validateSubsettingUniquenessConformance", + "A subset of a unique feature must be unique", + ); + } + } + // Owners of result expressions, indexed once for the per-type walk. + let result_owners: std::collections::HashSet = + b.result_exprs.iter().map(|(o, _, _)| *o).collect(); + for e in 0..b.explicit_len() { + if model.is_library_unit(b.unit_of_elem(e)) { + continue; + } + let span = g.span(b, e); + let ty = b.elements[e].ty; + let variation = flag(b, e, "isVariation") || is(b, e, "EnumerationDefinition"); + if variation { + for &m in &g.members[e] { + if is(b, m, "Usage") + && !is(b, m, "MetadataUsage") + && !is(b, m, "EnumerationUsage") + && b.elements[m].owning_relationship.is_some_and(|rel| { + is(b, rel, "FeatureMembership") && !is(b, rel, "VariantMembership") + }) + { + report( + m, + g.span(b, m), + if is(b, e, "Definition") { + "validateDefinitionVariationMembership" + } else { + "validateUsageVariationMembership" + }, + "A usage owned by a variation must be a variant", + ); + } + } + if g.supers[e] + .iter() + .any(|&s| flag(b, s, "isVariation") || is(b, s, "EnumerationDefinition")) + { + report( + e, + span, + if is(b, e, "Definition") { + "validateDefinitionVariationSpecialization" + } else { + "validateUsageVariationSpecialization" + }, + "A variation cannot specialize another variation", + ); + } + } + for (kind, membership, rule) in [ + ( + "CaseDefinition", + "ObjectiveMembership", + "validateCaseDefinitionOnlyOneObjective", + ), + ( + "CaseUsage", + "ObjectiveMembership", + "validateCaseUsageOnlyOneObjective", + ), + ( + "RequirementDefinition", + "SubjectMembership", + "validateRequirementDefinitionOnlyOneSubject", + ), + ( + "RequirementUsage", + "SubjectMembership", + "validateRequirementUsageOnlyOneSubject", + ), + ] { + if !is(b, e, kind) { + continue; + } + let owns_role = g.members[e].iter().any(|&m| { + b.elements[m] + .owning_relationship + .is_some_and(|rel| is(b, rel, membership)) + }); + if !owns_role + && g.effective_members(b, e) + .iter() + .filter(|&&m| { + b.elements[m] + .owning_relationship + .is_some_and(|rel| is(b, rel, membership)) + }) + .count() + > 1 + { + report( + e, + span, + rule, + "At most one effective member with this parameter role is allowed", + ); + } + } + for (kind, key, one, self_rule) in [ + ( + "Unioning", + "unioningType", + "validateOwnedUnioningNotOne", + "validateTypeUnioningTypesNotSelf", + ), + ( + "Intersecting", + "intersectingType", + "validateOwnedIntersectingNotOne", + "validateTypeIntersectingTypesNotSelf", + ), + ( + "Differencing", + "differencingType", + "validateOwnedDifferencingNotOne", + "validateTypeDifferencingTypesNotSelf", + ), + ] { + let targets = g.relations(b, e, kind, key); + if targets.len() == 1 { + report( + e, + span, + one, + "A type operation must have zero or at least two operands", + ); + } + if targets.contains(&e) { + report( + e, + span, + self_rule, + "A type operation cannot name its own type as an operand", + ); + } + } + if ty == "LibraryPackage" && flag(b, e, "isStandard") { + report( + e, + span, + "validateLibraryPackageNotStandard", + "A user library package must not be marked standard", + ); + } + if is(b, e, "Feature") { + let is_var = variable(b, g, e); + if flag(b, e, "isVariable") && !g.featuring(b, e).is_some_and(|o| occurrence(b, g, o)) { + report( + e, + span, + "validateFeatureIsVariable", + "A variable feature must be owned by an occurrence type", + ); + } + if flag(b, e, "isVariable") && flag(b, e, "isPortion") { + report( + e, + span, + "validateFeaturePortionNotVariable", + "A portion cannot be variable", + ); + } + if flag(b, e, "isConstant") && !is_var { + report( + e, + span, + "validateFeatureConstantIsVariable", + "Only a variable feature can be constant", + ); + } + for &rel in &b.elements[e].owned_relationships { + if b.elements[rel].ty == "FeatureValue" && flag(b, rel, "isInitial") && !is_var { + report( + e, + span, + "validateFeatureValueIsInitial", + "An initialized feature must be variable", + ); + } + } + } + if is(b, e, "OccurrenceUsage") { + let typed = g.typed(b, e); + let n = typed + .iter() + .filter(|&&t| flag(b, t, "isIndividual") && is(b, t, "Definition")) + .count(); + if n > 1 { + report( + e, + span, + "validateOccurrenceUsageIndividualDefinition", + "At most one individual definition may type an occurrence", + ); + } + if flag(b, e, "isIndividual") && n != 1 && !typed.is_empty() { + report( + e, + span, + "validateOccurrenceUsageIndividualUsage", + "An individual usage must be typed by one individual definition", + ); + } + if b.elements[e] + .props + .get("portionKind") + .is_some_and(|p| p.is_string()) + && !g.featuring(b, e).is_some_and(|o| { + is(b, o, "OccurrenceDefinition") || is(b, o, "OccurrenceUsage") + }) + { + report( + e, + span, + "validateOccurrenceUsageIsPortion", + "A snapshot or timeslice must be owned by an occurrence definition or usage", + ); + } + } + if let Some(owner) = g.owner[e] { + if is(b, e, "Usage") && !is(b, e, "PortUsage") && flag(b, e, "isComposite") { + let rule = match b.elements[owner].ty { + "PortDefinition" => Some("validatePortDefinitionOwnedUsagesNotComposite"), + "PortUsage" => Some("validatePortUsageNestedUsagesNotComposite"), + _ => None, + }; + if let Some(rule) = rule { + report( + e, + span, + rule, + "A non-port usage owned by a port must be referential", + ); + } + } + if is(b, e, "PortUsage") + && (is(b, owner, "PortDefinition") || is(b, owner, "PortUsage")) + && g.owner[owner] + .is_some_and(|o| is(b, o, "PortDefinition") || is(b, o, "PortUsage")) + && b.elements[e] + .owning_relationship + .is_some_and(|rel| b.elements[rel].ty == "VariantMembership") + && flag(b, e, "isComposite") + { + report( + e, + span, + "validatePortUsageIsReference", + "A port nested in a port must be referential", + ); + } + if flag(b, e, "isEnd") + && (is(b, owner, "InterfaceDefinition") || is(b, owner, "InterfaceUsage")) + && !is(b, e, "PortUsage") + { + let rule = if is(b, owner, "InterfaceDefinition") { + "validateInterfaceDefinitionEnd" + } else { + "validateInterfaceUsageEnd" + }; + report(e, span, rule, "An interface end must be a port"); + } + } + let required = match ty { + "PerformActionUsage" => Some(("ActionUsage", "validatePerformActionUsageReference")), + "ExhibitStateUsage" => Some(("StateUsage", "validateExhibitStateUsageReference")), + "IncludeUseCaseUsage" => Some(("UseCaseUsage", "validateIncludeUseCaseUsageReference")), + "SatisfyRequirementUsage" => Some(( + "RequirementUsage", + "validateSatisfyRequirementUsageReference", + )), + "AssertConstraintUsage" => { + Some(("ConstraintUsage", "validateAssertConstraintUsageReference")) + } + "EventOccurrenceUsage" => { + Some(("OccurrenceUsage", "validateEventOccurrenceUsageReferent")) + } + _ => None, + }; + if let Some((required, rule)) = required { + for target in g.relations(b, e, "ReferenceSubsetting", "referencedFeature") { + if !g.effective_kind(b, target, required) { + report(e, span, rule, &format!("{ty} must reference a {required}")); + } + } + } + if is(b, e, "ViewDefinition") || is(b, e, "ViewUsage") { + let count = g.members[e] + .iter() + .filter(|&&m| { + b.elements[m] + .owning_relationship + .is_some_and(|rel| b.elements[rel].ty == "ViewRenderingMembership") + }) + .count(); + if count > 1 { + report( + e, + span, + if is(b, e, "ViewDefinition") { + "validateViewDefinitionOnlyOnvViewRendering" + } else { + "validateViewUsageOnlyOneRendering" + }, + "A view may have at most one rendering", + ); + } + } + if is(b, e, "Function") || is(b, e, "Expression") { + let results = g + .closure(e) + .into_iter() + .filter(|t| result_owners.contains(t)) + .count(); + if results > 1 { + report( + e, + span, + if is(b, e, "Function") { + "validateFunctionResultExpressionMembership" + } else { + "validateExpressionResultExpressionMembership" + }, + "Only one owned or inherited result expression is allowed", + ); + } + let returns = g.members[e] + .iter() + .filter(|&&m| { + b.elements[m] + .owning_relationship + .is_some_and(|r| b.elements[r].ty == "ReturnParameterMembership") + }) + .count(); + if returns > 1 { + report( + e, + span, + if is(b, e, "Function") { + "validateFunctionResultParameterMembership" + } else { + "validateExpressionResultParameterMembership" + }, + "Only one return parameter is allowed", + ); + } + } + if is(b, e, "Type") + && g.members[e] + .iter() + .filter(|&&m| is(b, m, "Multiplicity")) + .count() + > 1 + { + report( + e, + span, + "validateTypeOwnedMultiplicity", + "Only one multiplicity is allowed", + ); + } + for (rel, rule) in [ + ( + "ReferenceSubsetting", + "validateFeatureOwnedReferenceSubsetting", + ), + ("CrossSubsetting", "validateFeatureOwnedCrossSubsetting"), + ] { + if b.elements[e] + .owned_relationships + .iter() + .filter(|&&r| b.elements[r].ty == rel) + .count() + > 1 + { + report( + e, + span, + rule, + "At most one relationship of this kind is allowed", + ); + } + } + let chain = g.relations(b, e, "FeatureChaining", "chainingFeature"); + if b.elements[e] + .owned_relationships + .iter() + .filter(|&&r| b.elements[r].ty == "FeatureChaining") + .count() + == 1 + { + report( + e, + span, + "validateFeatureChainingFeatureNotOne", + "A feature chain must have at least two features", + ); + } + if chain.contains(&e) { + report( + e, + span, + "validateFeatureChainingFeaturesNotSelf", + "A feature cannot chain through itself", + ); + } + if is(b, e, "StateDefinition") || is(b, e, "StateUsage") { + let definition = is(b, e, "StateDefinition"); + for kind in ["entry", "do", "exit"] { + let n = g.members[e] + .iter() + .filter(|&&m| { + b.elements[m].owning_relationship.is_some_and(|r| { + b.elements[r].ty == "StateSubactionMembership" + && b.elements[r].props.get("kind").and_then(|v| v.as_str()) + == Some(kind) + }) + }) + .count(); + if n > 1 { + report( + e, + span, + if definition { + "validateStateDefinitionSubactionKind" + } else { + "validateStateUsageSubactionKind" + }, + "A state may have at most one subaction of each kind", + ); + } + } + if flag(b, e, "isParallel") + && g.members[e] + .iter() + .any(|&m| is(b, m, "TransitionUsage") || is(b, m, "Succession")) + { + report( + e, + span, + if definition { + "validateStateDefinitionParallelSubactions" + } else { + "validateStateUsageParallelSubactions" + }, + "A parallel state cannot own successions or transitions", + ); + } + } + if is(b, e, "ControlNode") + && !g.owner[e].is_some_and(|o| is(b, o, "ActionDefinition") || is(b, o, "ActionUsage")) + { + report( + e, + span, + "validateControlNodeOwningType", + "A control node must be owned by an action", + ); + } + if is(b, e, "Association") { + let ends: Vec<_> = g.members[e] + .iter() + .copied() + .filter(|&m| flag(b, m, "isEnd")) + .collect(); + if ends.len() == 1 && g.supers[e].is_empty() { + report( + e, + span, + "validateAssociationRelatedTypes", + "An association must have at least two related types", + ); + } + for end in ends { + let types = g.typed(b, end); + let minimal = types + .iter() + .filter(|&&t| !types.iter().any(|&u| u != t && g.closure(u).contains(&t))) + .count(); + if minimal > 1 { + report( + end, + g.span(b, end), + "validateAssociationEndTypes", + "An association end must have exactly one non-redundant type", + ); + } + } + } + if b.elements[e] + .owning_relationship + .is_some_and(|r| b.elements[r].ty == "RequirementVerificationMembership") + { + let valid = g.owner[e].is_some_and(|o| { + b.elements[o] + .owning_relationship + .is_some_and(|r| b.elements[r].ty == "ObjectiveMembership") + && g.owner[o].is_some_and(|c| { + is(b, c, "VerificationCaseDefinition") || is(b, c, "VerificationCaseUsage") + }) + }); + if !valid { + report( + e, + span, + "validateRequirementVerificationMembershipOwningType", + "A requirement verification must be in the objective of a verification case", + ); + } + } + if is(b, e, "MetadataFeature") { + let types = g.typed(b, e); + if !types.is_empty() && types.iter().all(|&t| flag(b, t, "isAbstract")) { + report( + e, + span, + "validateMetadataFeatureMetadataNotAbstract", + "Metadata must have a concrete type", + ); + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/typing.rs b/crates/sysmlv2-model/src/check/typing.rs new file mode 100644 index 0000000..c898f9b --- /dev/null +++ b/crates/sysmlv2-model/src/check/typing.rs @@ -0,0 +1,203 @@ +//! Explicit typing restrictions from the abstract-syntax property types. +//! +//! Metaclass inheritance comes from the pinned XMI, so e.g. a requirement +//! definition is also a predicate, and an interface definition is also an +//! association structure. This is separate from user-model specialization. + +use crate::{ + json::{ElementRef, ResolvedModel}, + metaclass, + model::Model, +}; +use std::collections::BTreeMap; +use sysmlv2_syntax::{Span, diag::Diagnostic}; + +/// (allowed metaclass, at most one non-redundant explicit type). +fn restriction(usage: &str) -> Option<(&'static str, bool)> { + Some(match usage { + "AttributeUsage" => ("DataType", false), + "EnumerationUsage" => ("EnumerationDefinition", true), + "OccurrenceUsage" | "ItemUsage" | "PartUsage" | "EventOccurrenceUsage" => ("Class", false), + "PortUsage" => ("PortDefinition", false), + "ConnectionUsage" => ("AssociationStructure", false), + "InterfaceUsage" => ("InterfaceDefinition", false), + "AllocationUsage" => ("AllocationDefinition", false), + "FlowUsage" | "SuccessionFlowUsage" => ("Interaction", false), + "ActionUsage" | "PerformActionUsage" => ("Behavior", false), + "StateUsage" | "ExhibitStateUsage" => ("StateDefinition", false), + "CalculationUsage" => ("Function", true), + "ConstraintUsage" | "AssertConstraintUsage" => ("Predicate", true), + "RequirementUsage" | "SatisfyRequirementUsage" | "ConcernUsage" => { + ("RequirementDefinition", true) + } + "CaseUsage" => ("CaseDefinition", true), + "AnalysisCaseUsage" => ("AnalysisCaseDefinition", true), + "VerificationCaseUsage" => ("VerificationCaseDefinition", true), + "UseCaseUsage" | "IncludeUseCaseUsage" => ("UseCaseDefinition", true), + "RenderingUsage" => ("RenderingDefinition", true), + "ViewUsage" => ("ViewDefinition", true), + "ViewpointUsage" => ("ViewpointDefinition", true), + "ReferenceUsage" => ("Classifier", false), + // Metadata has a dedicated rule and diagnostic in check.rs. + _ => return None, + }) +} + +/// A usage typed by a definition its own kind cannot take — the pair the +/// typing check reports, exposed so a repair can rewrite the usage +/// keyword to the kind the definition belongs to. +#[derive(Clone, Debug)] +pub struct IncompatibleTyping { + pub usage: ElementRef, + pub target: ElementRef, + /// Index into [`crate::model::Model::units`] of the usage. + pub unit: usize, + /// Span of the type name as written. + pub span: Span, + /// The metaclass family the usage's kind admits. + pub allowed: &'static str, +} + +/// One usage's declared typings with the restriction its kind places on +/// them. +struct TypingGroup { + owner: usize, + allowed: &'static str, + /// The kind requires exactly one non-redundant type. + single: bool, + targets: Vec<(usize, Span)>, +} + +/// The user usages with declared typings, grouped, each with its kind's +/// restriction. `model` filters library units by unit; without it the +/// element boundary does. +fn typing_groups(r: &ResolvedModel, model: Option<&Model>) -> Vec { + let mut groups: BTreeMap> = BTreeMap::new(); + for (i, (owner, kind, _, name)) in r.b.spec_targets.iter().enumerate() { + if *kind != "FeatureTyping" { + continue; + } + let library = match model { + Some(model) => model.is_library_unit(r.b.unit_of_elem(*owner)), + None => *owner < r.b.lib_boundary, + }; + if library { + continue; + } + if let Some(target) = r.b.spec_resolved.get(i).copied().flatten() { + groups.entry(*owner).or_default().push((target, name.span)); + } + } + let mut out = Vec::new(); + for (owner, targets) in groups { + let ty = r.b.elements[owner].ty; + let Some((mut allowed, mut single)) = restriction(ty) else { + continue; + }; + // Directed data/structural usages are parameters. They may carry + // data or occurrence values, while kind-specific parameters such as + // ports retain their narrower typing restrictions. + if r.b.elements[owner] + .props + .get("direction") + .is_some_and(|v| v.is_string()) + && matches!( + ty, + "AttributeUsage" | "PartUsage" | "ItemUsage" | "OccurrenceUsage" + ) + { + allowed = "Classifier"; + } + if ty == "AttributeUsage" + && targets + .iter() + .any(|(t, _)| metaclass::conforms(r.b.elements[*t].ty, "EnumerationDefinition")) + { + single = true; + } + out.push(TypingGroup { + owner, + allowed, + single, + targets, + }); + } + out +} + +/// Every user usage typed by a definition its kind cannot take, as +/// [`validate`] reports them. +pub(super) fn incompatible_typings(r: &ResolvedModel) -> Vec { + let mut out = Vec::new(); + for g in typing_groups(r, None) { + let unit = r.b.unit_of_elem(g.owner); + for (target, span) in &g.targets { + if !metaclass::conforms(r.b.elements[*target].ty, g.allowed) { + out.push(IncompatibleTyping { + usage: ElementRef(g.owner), + target: ElementRef(*target), + unit, + span: *span, + allowed: g.allowed, + }); + } + } + } + out +} + +pub(super) fn validate(r: &mut ResolvedModel, model: &Model) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + for g in typing_groups(r, Some(model)) { + let ty = r.b.elements[g.owner].ty; + let allowed = g.allowed; + let unit = r.b.unit_of_elem(g.owner); + let mut compatible = true; + for (target, span) in &g.targets { + let target_ty = r.b.elements[*target].ty; + if !metaclass::conforms(target_ty, allowed) { + compatible = false; + out.push(( + unit, + Diagnostic::error( + *span, + format!( + "{ty} must be typed by {allowed}; the declared type is a {target_ty}" + ), + ), + )); + } + } + if !g.single || !compatible { + continue; + } + // Repeating a type is handled by the duplicate-specialization rule. + // A general explicitly restated beside its specialization is also + // redundant, not a second independent type. + let mut distinct: Vec = g.targets.iter().map(|(t, _)| *t).collect(); + distinct.sort_unstable(); + distinct.dedup(); + let minimal: Vec = distinct + .iter() + .copied() + .filter(|&t| { + !distinct + .iter() + .any(|&other| other != t && r.b.conforms_upward(other, t)) + }) + .collect(); + if minimal.len() > 1 { + out.push(( + unit, + Diagnostic::error( + g.targets[1].1, + format!( + "{ty} must have exactly one non-redundant type; found {}", + minimal.len() + ), + ), + )); + } + } + out +} diff --git a/crates/sysmlv2-model/src/check/values.rs b/crates/sysmlv2-model/src/check/values.rs new file mode 100644 index 0000000..027fa1d --- /dev/null +++ b/crates/sysmlv2-model/src/check/values.rs @@ -0,0 +1,172 @@ +//! Valuation and metadata contracts. Missing types remain undecided. +use super::facts::{Facts, is}; +use crate::{ + json::{ElementRef, ResolvedModel}, + model::Model, +}; +use sysmlv2_syntax::diag::Diagnostic; + +pub(super) fn validate( + r: &mut ResolvedModel, + model: &Model, + g: &Facts, +) -> Vec<(usize, Diagnostic)> { + let mut out = Vec::new(); + // End features that a connector claims, indexed once for the walk. + let connected: std::collections::HashSet = + r.b.connector_ends.iter().map(|(_, end, _)| *end).collect(); + for e in 0..r.b.explicit_len() { + let unit = r.b.unit_of_elem(e); + if model.is_library_unit(unit) { + continue; + } + let span = g.span(&r.b, e); + if let Some((_, value)) = r.b.values.get(&e) { + if g.redefined(&r.b, e) + .iter() + .any(|t| r.b.values.contains_key(t) && !r.b.default_values.contains(t)) + { + out.push((unit, super::rule_error(value.span, "validateFeatureValueOverriding", + "Cannot override an inherited binding value; the redefined value must be default"))); + } + } + if is(&r.b, e, "EnumerationUsage") { + if let Some((_, expr)) = r.b.values.get(&e) { + if matches!(expr.kind, sysmlv2_syntax::ast::ExprKind::Body { .. }) { + out.push(( + unit, + super::rule_error( + expr.span, + "validateEnumerationUsageType", + "An expression body is not a value of the owning enumeration", + ), + )); + } + } + } + if super::facts::flag(&r.b, e, "isEnd") && !connected.contains(&e) { + if let Some((lo, hi)) = r.declared_multiplicity(ElementRef(e)) { + if lo != 1.0 || hi != 1.0 { + out.push(( + unit, + super::rule_warning( + span, + "validateFeatureEndFeatureMultiplicity", + "An end feature should have multiplicity 1..1", + ), + )); + } + } + } + if !is(&r.b, e, "MetadataFeature") || g.typed(&r.b, e).is_empty() { + continue; + } + let offered = g + .typed(&r.b, e) + .into_iter() + .flat_map(|t| g.effective_members(&r.b, t)) + .collect::>(); + let mut stack = vec![(e, offered)]; + while let Some((owner, offered)) = stack.pop() { + for &m in &g.members[owner] { + if !is(&r.b, m, "Feature") + || is(&r.b, m, "MetadataFeature") + || !r.b.elements[m] + .owning_relationship + .is_some_and(|rel| is(&r.b, rel, "FeatureMembership")) + { + continue; + } + let targets = g.relations(&r.b, m, "Redefinition", "redefinedFeature"); + let name = r.b.elements[m].props.get("declaredName"); + let implicit: Vec<_> = offered + .iter() + .copied() + .filter(|&t| { + name.is_some_and(|n| n.is_string()) + && name == r.b.elements[t].props.get("declaredName") + }) + .collect(); + let target = if targets.is_empty() { + (implicit.len() == 1).then(|| implicit[0]) + } else { + (targets.len() == 1 && offered.contains(&targets[0])).then(|| targets[0]) + }; + if let Some(t) = target { + stack.push((m, g.effective_members(&r.b, t))); + } else { + out.push((unit, super::rule_error(g.span(&r.b, m), "validateMetadataFeatureBody", + "A metadata body feature must redefine one feature of its metadata type"))); + } + if let Some((scope, expr)) = r.b.values.get(&m).cloned() { + if super::expressions::model_level(&mut r.b, g, scope, &expr, 0) == Some(false) + { + out.push(( + unit, + super::rule_error( + expr.span, + "validateMetadataFeatureBody", + "A metadata body value must be model-level evaluable", + ), + )); + } + } + } + } + } + for (e, scope, mult) in super::user_rows(&r.b, model, r.b.multiplicities.iter(), |row| row.0) { + let unit = r.b.unit_of_elem(e); + for expr in mult.lower.iter().chain(std::iter::once(&mult.upper)) { + let ts = super::expressions::types(&mut r.b, g, scope, expr, 0); + if !ts.is_empty() && ts.iter().all(|&t| !is(&r.b, t, "DataType")) { + out.push(( + unit, + super::rule_error( + expr.span, + "validateMultiplicityRangeResultTypes", + "A multiplicity bound must have a Natural result", + ), + )); + } + } + } + for (annotated, metas) in super::user_entries(&r.b, model, r.b.metadata_of.iter()) { + let unit = r.b.unit_of_elem(annotated); + for meta in metas { + let candidates: Vec<_> = g + .effective_members(&r.b, meta) + .into_iter() + .filter(|&member| { + g.closure(member) + .iter() + .any(|&f| g.named(&r.b, f, "Metaobjects::Metaobject::annotatedElement")) + }) + .collect(); + // Separate subsetting features specify alternative permitted + // metaclasses; a single feature's multiple types are conjunctive. + let specific: Vec<_> = candidates + .iter() + .copied() + .filter(|t| { + !candidates + .iter() + .any(|other| other != t && g.closure(*other).contains(t)) + }) + .collect(); + if let Some(reflection) = r.b.reflection_metaclass(r.b.elements[annotated].ty) { + let actual = g.context(reflection); + let allowed: Vec<_> = specific.iter().map(|&m| g.typed(&r.b, m)).collect(); + if !allowed.is_empty() + && allowed.iter().all(|ts| !ts.is_empty()) + && !allowed + .iter() + .any(|ts| ts.iter().all(|t| actual.contains(t))) + { + out.push((unit, super::rule_error(g.span(&r.b, meta), "validateMetadataFeatureAnnotatedElement", + "The annotated element's metaclass does not conform to annotatedElement's type"))); + } + } + } + } + out +} diff --git a/crates/sysmlv2-model/src/derived_names.rs b/crates/sysmlv2-model/src/derived_names.rs new file mode 100644 index 0000000..a2d18a0 --- /dev/null +++ b/crates/sysmlv2-model/src/derived_names.rs @@ -0,0 +1,473 @@ +//! Generated from `spec-refs/{KerML,SysML}.xmi` (normative metamodel +//! 20250201) by `tools/derived_census.py` — do not edit. +//! +//! The abstract syntax's derived property names, for the derived-property +//! read API: a property is derived on a concrete metaclass when the +//! schema catalog declares it, its name is in [`DERIVED_NAMES`], and the +//! metaclass is not listed under that name in [`OWNED_ON`] (a few names +//! are owned on one metaclass and derived on another). + +/// Every `isDerived` property name, sorted. +pub(crate) static DERIVED_NAMES: &[&str] = &[ + "action", + "actionDefinition", + "actorParameter", + "allocation", + "allocationDefinition", + "analysisCaseDefinition", + "annotatedElement", + "annotatingElement", + "annotation", + "argument", + "assertedConstraint", + "association", + "associationEnd", + "assumedConstraint", + "attributeDefinition", + "behavior", + "bodyAction", + "bound", + "calculation", + "calculationDefinition", + "caseDefinition", + "chainingFeature", + "concernDefinition", + "condition", + "conjugatedPortDefinition", + "connectionDefinition", + "connectionEnd", + "connectorEnd", + "constraintDefinition", + "crossFeature", + "crossingFeature", + "defaultFeaturingType", + "definition", + "differencingType", + "directedFeature", + "directedUsage", + "doAction", + "documentation", + "documentedElement", + "effectAction", + "elseAction", + "endFeature", + "endOwningType", + "entryAction", + "enumeratedValue", + "enumerationDefinition", + "eventOccurrence", + "exhibitedState", + "exitAction", + "exposedElement", + "expression", + "feature", + "featureChained", + "featureMembership", + "featureTarget", + "featureWithValue", + "featuringType", + "filterCondition", + "flowDefinition", + "flowEnd", + "framedConcern", + "function", + "guardExpression", + "ifArgument", + "importOwningNamespace", + "importedElement", + "importedMembership", + "includedUseCase", + "individualDefinition", + "inheritedFeature", + "inheritedMembership", + "input", + "instantiatedType", + "interaction", + "interfaceDefinition", + "interfaceEnd", + "intersectingType", + "isConjugated", + "isLibraryElement", + "isModelLevelEvaluable", + "isReference", + "itemDefinition", + "loopVariable", + "lowerBound", + "mayTimeVary", + "member", + "memberElementId", + "membership", + "membershipOwningNamespace", + "metaclass", + "metadataDefinition", + "multiplicity", + "name", + "nestedAction", + "nestedAllocation", + "nestedAnalysisCase", + "nestedAttribute", + "nestedCalculation", + "nestedCase", + "nestedConcern", + "nestedConnection", + "nestedConstraint", + "nestedEnumeration", + "nestedFlow", + "nestedInterface", + "nestedItem", + "nestedMetadata", + "nestedOccurrence", + "nestedPart", + "nestedPort", + "nestedReference", + "nestedRendering", + "nestedRequirement", + "nestedState", + "nestedTransition", + "nestedUsage", + "nestedUseCase", + "nestedVerificationCase", + "nestedView", + "nestedViewpoint", + "objectiveRequirement", + "occurrenceDefinition", + "originalPortDefinition", + "output", + "ownedAction", + "ownedActorParameter", + "ownedAllocation", + "ownedAnalysisCase", + "ownedAnnotatingElement", + "ownedAnnotatingRelationship", + "ownedAnnotation", + "ownedAttribute", + "ownedCalculation", + "ownedCase", + "ownedConcern", + "ownedConjugator", + "ownedConnection", + "ownedConstraint", + "ownedCrossSubsetting", + "ownedDifferencing", + "ownedDisjoining", + "ownedElement", + "ownedEndFeature", + "ownedEnumeration", + "ownedFeature", + "ownedFeatureChaining", + "ownedFeatureInverting", + "ownedFeatureMembership", + "ownedFlow", + "ownedImport", + "ownedInterface", + "ownedIntersecting", + "ownedItem", + "ownedMember", + "ownedMemberElement", + "ownedMemberElementId", + "ownedMemberFeature", + "ownedMemberName", + "ownedMemberParameter", + "ownedMemberShortName", + "ownedMembership", + "ownedMetadata", + "ownedObjectiveRequirement", + "ownedOccurrence", + "ownedPart", + "ownedPort", + "ownedPortConjugator", + "ownedRedefinition", + "ownedReference", + "ownedReferenceSubsetting", + "ownedRendering", + "ownedRequirement", + "ownedResultExpression", + "ownedSpecialization", + "ownedStakeholderParameter", + "ownedState", + "ownedSubclassification", + "ownedSubjectParameter", + "ownedSubsetting", + "ownedTransition", + "ownedTypeFeaturing", + "ownedTyping", + "ownedUnioning", + "ownedUsage", + "ownedUseCase", + "ownedVariantUsage", + "ownedVerificationCase", + "ownedView", + "ownedViewpoint", + "owner", + "owningAnnotatedElement", + "owningAnnotatingElement", + "owningAnnotatingRelationship", + "owningClassifier", + "owningDefinition", + "owningFeature", + "owningFeatureMembership", + "owningFeatureOfType", + "owningMembership", + "owningNamespace", + "owningType", + "owningUsage", + "parameter", + "partDefinition", + "payloadArgument", + "payloadFeature", + "payloadParameter", + "payloadType", + "performedAction", + "portDefinition", + "predicate", + "qualifiedName", + "receiverArgument", + "referencedConcern", + "referencedConstraint", + "referencedElement", + "referencedRendering", + "referencingFeature", + "referent", + "relatedElement", + "relatedFeature", + "relatedType", + "rendering", + "renderingDefinition", + "representedElement", + "requiredConstraint", + "requirementDefinition", + "result", + "resultExpression", + "satisfiedRequirement", + "satisfiedViewpoint", + "satisfyingFeature", + "senderArgument", + "seqArgument", + "shortName", + "source", + "sourceFeature", + "sourceOutputFeature", + "sourceType", + "stakeholderParameter", + "state", + "stateDefinition", + "step", + "subjectParameter", + "succession", + "target", + "targetArgument", + "targetFeature", + "targetInputFeature", + "targetType", + "terminatedOccurrenceArgument", + "text", + "textualRepresentation", + "thenAction", + "transitionFeature", + "triggerAction", + "type", + "typeDifferenced", + "typeIntersected", + "typeUnioned", + "unioningType", + "untilArgument", + "upperBound", + "usage", + "useCaseDefinition", + "useCaseIncluded", + "value", + "valueExpression", + "variant", + "variantMembership", + "verificationCaseDefinition", + "verifiedRequirement", + "view", + "viewCondition", + "viewDefinition", + "viewRendering", + "viewpointDefinition", + "viewpointStakeholder", + "whileArgument", +]; + +/// Names that are derived somewhere but *owned* on these metaclasses +/// (abstract ones included). +pub(crate) static OWNED_ON: &[(&str, &[&str])] = &[ + ("annotatedElement", &["Annotation"]), + ("chainingFeature", &["FeatureChaining"]), + ("conjugatedPortDefinition", &["ConjugatedPortTyping"]), + ("differencingType", &["Differencing"]), + ("featuringType", &["TypeFeaturing"]), + ( + "importedMembership", + &["MembershipExpose", "MembershipImport"], + ), + ("intersectingType", &["Intersecting"]), + ("originalPortDefinition", &["PortConjugation"]), + ( + "source", + &[ + "ActorMembership", + "AllocationDefinition", + "AllocationUsage", + "Annotation", + "Association", + "AssociationStructure", + "BindingConnector", + "BindingConnectorAsUsage", + "ConjugatedPortTyping", + "Conjugation", + "ConnectionDefinition", + "ConnectionUsage", + "Connector", + "ConnectorAsUsage", + "CrossSubsetting", + "Dependency", + "Differencing", + "Disjoining", + "ElementFilterMembership", + "EndFeatureMembership", + "Expose", + "FeatureChaining", + "FeatureInverting", + "FeatureMembership", + "FeatureTyping", + "FeatureValue", + "Flow", + "FlowDefinition", + "FlowUsage", + "FramedConcernMembership", + "Import", + "Interaction", + "InterfaceDefinition", + "InterfaceUsage", + "Intersecting", + "Membership", + "MembershipExpose", + "MembershipImport", + "NamespaceExpose", + "NamespaceImport", + "ObjectiveMembership", + "OwningMembership", + "ParameterMembership", + "PortConjugation", + "Redefinition", + "ReferenceSubsetting", + "Relationship", + "RequirementConstraintMembership", + "RequirementVerificationMembership", + "ResultExpressionMembership", + "ReturnParameterMembership", + "Specialization", + "StakeholderMembership", + "StateSubactionMembership", + "Subclassification", + "SubjectMembership", + "Subsetting", + "Succession", + "SuccessionAsUsage", + "SuccessionFlow", + "SuccessionFlowUsage", + "TransitionFeatureMembership", + "TypeFeaturing", + "Unioning", + "VariantMembership", + "ViewRenderingMembership", + ], + ), + ( + "target", + &[ + "ActorMembership", + "AllocationDefinition", + "AllocationUsage", + "Annotation", + "Association", + "AssociationStructure", + "BindingConnector", + "BindingConnectorAsUsage", + "ConjugatedPortTyping", + "Conjugation", + "ConnectionDefinition", + "ConnectionUsage", + "Connector", + "ConnectorAsUsage", + "CrossSubsetting", + "Dependency", + "Differencing", + "Disjoining", + "ElementFilterMembership", + "EndFeatureMembership", + "Expose", + "FeatureChaining", + "FeatureInverting", + "FeatureMembership", + "FeatureTyping", + "FeatureValue", + "Flow", + "FlowDefinition", + "FlowUsage", + "FramedConcernMembership", + "Import", + "Interaction", + "InterfaceDefinition", + "InterfaceUsage", + "Intersecting", + "Membership", + "MembershipExpose", + "MembershipImport", + "NamespaceExpose", + "NamespaceImport", + "ObjectiveMembership", + "OwningMembership", + "ParameterMembership", + "PortConjugation", + "Redefinition", + "ReferenceSubsetting", + "Relationship", + "RequirementConstraintMembership", + "RequirementVerificationMembership", + "ResultExpressionMembership", + "ReturnParameterMembership", + "Specialization", + "StakeholderMembership", + "StateSubactionMembership", + "Subclassification", + "SubjectMembership", + "Subsetting", + "Succession", + "SuccessionAsUsage", + "SuccessionFlow", + "SuccessionFlowUsage", + "TransitionFeatureMembership", + "TypeFeaturing", + "Unioning", + "VariantMembership", + "ViewRenderingMembership", + ], + ), + ("type", &["ConjugatedPortTyping", "FeatureTyping"]), + ("unioningType", &["Unioning"]), + ( + "value", + &[ + "LiteralBoolean", + "LiteralInteger", + "LiteralRational", + "LiteralString", + ], + ), +]; + +/// The abstract metaclasses of the abstract syntax, sorted: no element +/// has one, and the property catalog skips them. +pub(crate) static ABSTRACT_METACLASSES: &[&str] = &[ + "ConnectorAsUsage", + "ControlNode", + "Element", + "Expose", + "Import", + "InstantiationExpression", + "LoopActionUsage", + "Relationship", +]; diff --git a/crates/sysmlv2-model/src/eval.rs b/crates/sysmlv2-model/src/eval.rs index 26a2705..6a8fe78 100644 --- a/crates/sysmlv2-model/src/eval.rs +++ b/crates/sysmlv2-model/src/eval.rs @@ -71,12 +71,20 @@ use std::fmt; use sysmlv2_syntax::Span; use sysmlv2_syntax::ast::*; +pub use crate::rational::Rational; + /// An evaluated value. KerML's `null` is the empty sequence. #[derive(Clone, Debug, PartialEq)] pub enum Value { Boolean(bool), Integer(i128), - Rational(f64), + /// An exact rational that is not an integer in `i128` range — + /// integral values in range are always [`Value::Integer`]. + Rational(Rational), + /// An approximate binary double: the result of a transcendental + /// function, a non-exact power or root, or infinity. Any operation + /// with a `Real` operand is approximate; everything else is exact. + Real(f64), String(String), /// A model element used as a *closed* value: an enum literal, a /// query-mode reflection result, or a collected member standing for @@ -86,10 +94,16 @@ pub enum Value { /// member access, chains, and classification treat it like the /// element itself, but cardinality/emptiness questions refuse to /// fabricate answers (the declared multiplicity answers when it is - /// exact). Minted only for user-owned features outside library - /// evaluation frames — library calc bodies keep the closed - /// one-element convention their semantics rely on. + /// exact). Defaults read through a parameter or reference that still + /// stands for an argument are indeterminate. Minted only for features + /// outside library evaluation frames — library calc bodies keep the + /// closed one-element convention their semantics rely on. Unbound(ElementRef), + /// An unvalued member reached through an unknown receiver. Like + /// [`Value::Unbound`], but retains the receiver's uncertainty through + /// aliases, conditionals, sequences and calculation arguments. A + /// later chain step must not read the member type's defaults. + UnboundMember(ElementRef), /// The result of an operation over an unknown operand: arithmetic, /// comparison, or logic over an unbound feature is not a type error — /// the formula is parametric and its value simply is not determined. @@ -120,7 +134,7 @@ pub enum Value { /// to a reduced rational exponent (`den > 0`, `num != 0`, gcd 1). The /// name is the element's simple name, kept for display only — identity /// is the element. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, PartialEq, serde::Serialize, serde::Deserialize)] pub(crate) struct Dim { pub(crate) elem: usize, pub(crate) name: String, @@ -143,7 +157,7 @@ pub(crate) struct Dim { #[derive(Clone, Debug)] pub struct Unit { pub(crate) dims: Vec, - pub(crate) scale: f64, + pub(crate) scale: Rational, pub(crate) display: String, } @@ -155,16 +169,17 @@ impl Unit { let display = render_dims(&merged); Unit { dims: merged, - scale: 1.0, + scale: Rational::one(), display, } } /// Canonical identity key — units are equal iff their keys are. pub fn key(&self) -> String { + use std::fmt::Write as _; let mut out = self.dims_key(); - if self.scale != 1.0 { - out.push_str(&format!("x{};", self.scale)); + if !self.scale.is_one() { + let _ = write!(out, "x{};", self.scale); } out } @@ -182,9 +197,11 @@ impl Unit { } /// Multiplier taking this unit's magnitudes to the reference - /// magnitude (`min` → 60, base units → 1). - pub fn scale(&self) -> f64 { - self.scale + /// magnitude (`min` → 60, base units → 1). Exact: library + /// conversion factors are decimals, small fractions and integer + /// powers, and every composition of them stays a rational. + pub fn scale(&self) -> &Rational { + &self.scale } /// Display spelling: the source spelling for bracket-constructed @@ -307,11 +324,10 @@ pub fn parse_unit_spelling(name: &str) -> Option> { } f.neg = true; } - c if sup_digit(c).is_some() => { + c if let Some(d) = sup_digit(c) => { if f.base.is_empty() { return None; } - let d = sup_digit(c).unwrap(); f.mag = Some(f.mag.unwrap_or(0).checked_mul(10)?.checked_add(d)?); } c => { @@ -402,24 +418,36 @@ fn dims_pow(dims: &[Dim], exp: (i32, i32)) -> Vec { } /// A numeric value as a reduced small rational, for unit exponents: -/// integers directly, rationals only when a denominator up to 16 -/// represents them exactly (`^(1/2)` after rational division is 0.5). +/// integers directly, exact rationals with a denominator up to 16 and a +/// numerator up to 1024 in magnitude (`^(1/2)` after rational division +/// is 1/2). An approximate double counts as the small fraction whose +/// nearest double it is, so a computed `0.5` or `0.1` still names a +/// root; its exact dyadic expansion would never have a small +/// denominator. fn small_ratio(v: &Value) -> Option<(i32, i32)> { - match v { - Value::Integer(i) => i32::try_from(*i).ok().map(|n| (n, 1)), - Value::Rational(f) => (1..=16i32).find_map(|den| { + let small = |n: i32, d: i32| (d <= 16 && n.abs() <= 1024).then_some((n, d)); + match v.num()? { + Num::Exact(r) => { + let (n, d) = r.to_i32_parts()?; + small(n, d) + } + Num::Approx(f) => (1..=16i32).find_map(|den| { let n = f * den as f64; - (n.fract() == 0.0 && n.abs() <= 1024.0 && (n as i32 as f64 / den as f64) == *f).then( - || { + (n.fract() == 0.0 && n.abs() <= 1024.0 && (n as i32 as f64 / den as f64) == f) + .then(|| { let g = gcd(n as i64, den as i64); ((n as i64 / g) as i32, (den as i64 / g) as i32) - }, - ) + }) + .and_then(|(n, d)| small(n, d)) }), - _ => None, } } +/// `a / b` for unit scales, which are never zero. +fn scale_ratio(a: &Rational, b: &Rational) -> Rational { + a.div(b).unwrap_or_else(Rational::one) +} + /// An integer-literal unit exponent, allowing the negated spelling the /// library uses (`s^-1`). fn unit_exponent(e: &Expr) -> Option { @@ -484,12 +512,231 @@ impl Value { } fn as_f64(&self) -> Option { + self.num().map(|n| n.to_f64()) + } + + /// The scalar number this value is, if it is one. + pub(crate) fn num(&self) -> Option { match self { - Value::Integer(i) => Some(*i as f64), - Value::Rational(r) => Some(*r), + Value::Integer(i) => Some(Num::Exact(Rational::from_integer(*i))), + Value::Rational(r) => Some(Num::Exact(r.clone())), + Value::Real(f) => Some(Num::Approx(*f)), _ => None, } } + + /// The canonical value of a number: an exact integer in `i128` range + /// is [`Value::Integer`], any other exact value [`Value::Rational`], + /// an approximate one [`Value::Real`]. + pub(crate) fn from_num(n: Num) -> Value { + match n { + Num::Exact(r) => match r.to_i128() { + Some(i) => Value::Integer(i), + None => Value::Rational(r), + }, + Num::Approx(f) => Value::Real(f), + } + } +} + +/// A scalar number as the evaluator computes with it: exact, or an +/// explicitly approximate double. Exact operands give exact results; +/// one approximate operand makes the result approximate. Comparisons +/// are exact in every combination — a finite double compares as the +/// dyadic rational it denotes. +#[derive(Clone, Debug)] +pub(crate) enum Num { + Exact(Rational), + Approx(f64), +} + +impl Num { + fn to_f64(&self) -> f64 { + match self { + Num::Exact(r) => r.to_f64(), + Num::Approx(f) => *f, + } + } + + /// The exact value: itself, or the dyadic rational of a finite + /// double; `None` for infinities and NaN. + fn exact(&self) -> Option { + match self { + Num::Exact(r) => Some(r.clone()), + Num::Approx(f) => Rational::from_f64(*f), + } + } + + fn is_zero(&self) -> bool { + match self { + Num::Exact(r) => r.is_zero(), + Num::Approx(f) => *f == 0.0, + } + } + + fn is_one(&self) -> bool { + match self { + Num::Exact(r) => r.is_one(), + Num::Approx(f) => *f == 1.0, + } + } + + fn is_negative(&self) -> bool { + match self { + Num::Exact(r) => r.is_negative(), + Num::Approx(f) => *f < 0.0, + } + } + + fn add(&self, o: &Num) -> Num { + match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Num::Exact(a.add(b)), + _ => Num::Approx(self.to_f64() + o.to_f64()), + } + } + + fn sub(&self, o: &Num) -> Num { + match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Num::Exact(a.sub(b)), + _ => Num::Approx(self.to_f64() - o.to_f64()), + } + } + + fn mul(&self, o: &Num) -> Num { + match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Num::Exact(a.mul(b)), + _ => Num::Approx(self.to_f64() * o.to_f64()), + } + } + + fn div(&self, o: &Num) -> Result { + if o.is_zero() { + return Err(EvalError::DivisionByZero); + } + Ok(match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Num::Exact(a.div(b).expect("non-zero divisor")), + _ => Num::Approx(self.to_f64() / o.to_f64()), + }) + } + + /// Truncated remainder. + fn rem(&self, o: &Num) -> Result { + if o.is_zero() { + return Err(EvalError::DivisionByZero); + } + Ok(match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Num::Exact(a.rem(b).expect("non-zero divisor")), + _ => Num::Approx(self.to_f64() % o.to_f64()), + }) + } + + /// `self ** e`: exact for an integer exponent and for a rational + /// exponent whose root exists, otherwise a double power. + fn pow(&self, e: &Num) -> Num { + if let (Num::Exact(a), Num::Exact(b)) = (self, e) { + let exact = match b.to_i128().and_then(|k| i32::try_from(k).ok()) { + Some(k) => a.pow(k), + None => a.pow_rational(b), + }; + if let Some(r) = exact { + return Num::Exact(r); + } + } + Num::Approx(self.to_f64().powf(e.to_f64())) + } + + /// The `n`-th root: exact when it exists, otherwise a double root. + fn root(&self, n: u32) -> Num { + if let Num::Exact(a) = self { + if let Some(r) = a.root(n) { + return Num::Exact(r); + } + } + let f = self.to_f64(); + Num::Approx(if n == 2 { + f.sqrt() + } else { + f.powf(1.0 / n as f64) + }) + } + + fn neg(&self) -> Num { + match self { + Num::Exact(r) => Num::Exact(r.neg()), + Num::Approx(f) => Num::Approx(-f), + } + } + + fn abs(&self) -> Num { + match self { + Num::Exact(r) => Num::Exact(r.abs()), + Num::Approx(f) => Num::Approx(f.abs()), + } + } + + /// Multiply by an exact factor (a unit scale). + fn scale(&self, s: &Rational) -> Num { + self.mul(&Num::Exact(s.clone())) + } + + /// The greatest integer not above the value; `None` for a non-finite + /// double. + fn floor(&self) -> Option { + self.exact().map(|r| Num::Exact(r.floor())) + } + + /// The nearest integer, halves away from zero; `None` for a + /// non-finite double. + fn round(&self) -> Option { + self.exact().map(|r| Num::Exact(r.round())) + } + + /// Exact ordering; `None` only when a NaN is involved. + fn cmp(&self, o: &Num) -> Option { + match (self, o) { + (Num::Exact(a), Num::Exact(b)) => Some(a.cmp(b)), + _ => match (self.exact(), o.exact()) { + (Some(a), Some(b)) => Some(a.cmp(&b)), + _ => self.to_f64().partial_cmp(&o.to_f64()), + }, + } + } + + fn eq(&self, o: &Num) -> bool { + self.cmp(o) == Some(std::cmp::Ordering::Equal) + } +} + +impl Value { + /// `Display`, except that a rational without a terminating decimal + /// expansion shows as an approximate decimal (`≈0.3333333333333333`) + /// instead of a fraction. For glanceable surfaces such as editor + /// hints; `Display` stays exact and re-parseable. + pub fn to_approx_string(&self) -> String { + match self { + Value::Rational(r) => r.to_approx_string(), + Value::Quantity(n, u) => format!("{} [{}]", n.to_approx_string(), u.display), + Value::Instance { + ty_name, fields, .. + } => { + let fields = fields + .iter() + .map(|(name, v)| format!("{name} = {}", v.to_approx_string())) + .collect::>() + .join(", "); + format!("{ty_name}({fields})") + } + Value::Sequence(s) if !s.is_empty() => { + let items = s + .iter() + .map(Value::to_approx_string) + .collect::>() + .join(", "); + format!("({items})") + } + v => v.to_string(), + } + } } impl fmt::Display for Value { @@ -498,9 +745,10 @@ impl fmt::Display for Value { Value::Boolean(b) => write!(f, "{b}"), Value::Integer(i) => write!(f, "{i}"), Value::Rational(r) => write!(f, "{r}"), + Value::Real(r) => write!(f, "{r}"), Value::String(s) => write!(f, "{s:?}"), Value::Element(_) => write!(f, ""), - Value::Unbound(_) => write!(f, ""), + Value::Unbound(_) | Value::UnboundMember(_) => write!(f, ""), Value::Indeterminate => write!(f, ""), Value::Quantity(n, u) => write!(f, "{n} [{}]", u.display), Value::Instance { @@ -541,8 +789,14 @@ pub enum EvalError { /// A feature's value (transitively) references itself. Cycle(String), DivisionByZero, + /// The evaluation budget ([`MAX_STEPS`], [`MAX_SEQUENCE`], + /// [`MAX_STRING`], [`MAX_ALLOCATION`], [`MAX_CALL_DEPTH`]) was + /// exceeded. + Budget(String), } +impl std::error::Error for EvalError {} + impl fmt::Display for EvalError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { @@ -551,6 +805,7 @@ impl fmt::Display for EvalError { EvalError::Type(m) => write!(f, "type error: {m}"), EvalError::Cycle(n) => write!(f, "cyclic feature value involving `{n}`"), EvalError::DivisionByZero => write!(f, "division by zero"), + EvalError::Budget(w) => write!(f, "evaluation budget exceeded: {w}"), } } } @@ -572,8 +827,11 @@ pub(crate) fn evaluate_expr_in(b: &mut Builder, scope: usize, e: &Expr) -> Resul env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, } .expr(scope, e) @@ -595,8 +853,11 @@ pub(crate) fn evaluate_expr_with( env: Vec::new(), in_progress: HashSet::new(), overrides, + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, } .expr(scope, e) @@ -613,8 +874,11 @@ pub(crate) fn unit_of_expr_in(b: &mut Builder, scope: usize, e: &Expr) -> Result env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, } .unit_of(scope, e) @@ -633,8 +897,11 @@ pub(crate) fn evaluate_query_in(b: &mut Builder, scope: usize, e: &Expr) -> Resu env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: true, } .expr(scope, e) @@ -654,8 +921,11 @@ pub(crate) fn evaluate_query_with_env( env, in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: true, } .expr(scope, e) @@ -668,8 +938,11 @@ pub(crate) fn evaluate_feature(model: &mut ResolvedModel, e: ElementRef) -> Resu env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, } .feature_value(e.0) @@ -689,8 +962,11 @@ pub(crate) fn evaluate_chain_of( env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, }; let mut v = ev.feature_value(root.0)?; @@ -716,14 +992,18 @@ pub(crate) fn evaluate_member_of( env: Vec::new(), in_progress: HashSet::new(), overrides: HashMap::new(), + unbound_receiver: None, lib_frames: 0, call_depth: 0, + steps: 0, + allocated: 0, query: false, }; let target = match ev.feature_value(receiver.0) { Ok( v @ (Value::Element(_) | Value::Unbound(_) + | Value::UnboundMember(_) | Value::Sequence(_) | Value::Instance { .. }), ) => v, @@ -735,6 +1015,31 @@ pub(crate) fn evaluate_member_of( } } +/// Evaluation budget: an expression that would run or allocate without +/// bound (`1..1000000000`, a calculation doubling a string on every +/// recursion, nested collects over large ranges, a product folding into +/// a million-digit integer) fails with [`EvalError::Budget`] instead of +/// hanging or exhausting memory. Steps count expression nodes; the +/// allocation budget counts the bytes of every sequence or string an +/// operator materializes, so many individually admissible values cannot +/// add up without bound; exact numbers are refused past +/// [`crate::rational::MAX_BITS`]. The limits are far above anything a +/// model's feature values or a document's query tags legitimately need. +pub const MAX_STEPS: usize = 10_000_000; +/// The most elements a range (`a..b`) materializes. +pub const MAX_SEQUENCE: usize = 1_000_000; +/// The longest string (in bytes) an operation produces. +pub const MAX_STRING: usize = 1 << 24; +/// The most bytes of sequences and strings one evaluation materializes +/// through operators, cumulatively. +pub const MAX_ALLOCATION: usize = 256 << 20; +/// The most nested user-calculation calls one evaluation may have open. +/// Recursion is allowed; a recursion that does not terminate exhausts +/// this instead of the stack. Far above any legitimate call chain — a +/// recursive calculation that needs more frames than this is a runaway, +/// not a deep model. +pub const MAX_CALL_DEPTH: usize = 64; + struct Evaluator<'m> { b: &'m mut Builder, /// Lambda- and calculation-parameter bindings, innermost last. @@ -752,8 +1057,16 @@ struct Evaluator<'m> { /// convention (library functions legitimately count and compare /// placeholders); at user level they mint [`Value::Unbound`]. lib_frames: usize, + /// Receiver whose members are currently evaluated without a bound + /// instance. Cleared for unrelated references and concrete receivers. + unbound_receiver: Option, /// User-defined calculation call depth (recursion is allowed, bounded). call_depth: usize, + /// Expression nodes evaluated so far (the step budget, [`MAX_STEPS`]). + steps: usize, + /// Bytes of sequences and strings materialized by operators so far + /// (the allocation budget, [`MAX_ALLOCATION`]). + allocated: usize, /// Ad-hoc query mode ([`evaluate_query_in`]): closed-world element /// classification and the reflection intrinsics. Never set for model /// feature values — corpus evaluation semantics must not drift. @@ -783,7 +1096,7 @@ impl Evaluator<'_> { /// anything inside a library evaluation frame keep the closed /// [`Value::Element`] convention. Non-feature elements (packages, /// definitions referenced as values) are closed element values. - fn placeholder(&self, e: usize) -> Value { + fn placeholder(&mut self, e: usize) -> Value { let ty = self.b.elements[e].ty; let feature_like = ty.ends_with("Usage") || matches!( @@ -803,15 +1116,32 @@ impl Evaluator<'_> { // *starts* outside a library frame (standalone evaluation of a // parametric library formula) — inside an invocation frame // (`lib_frames > 0`) the closed one-element convention that - // library sequence semantics rely on still applies. - if feature_like && !variant && self.lib_frames == 0 { - Value::Unbound(ElementRef(e)) + // library sequence semantics rely on still applies, except when + // navigating a receiver already known to be unbound. + let unknown_member = self.receiver_member(e).is_some(); + if feature_like && !variant && (self.lib_frames == 0 || unknown_member) { + if unknown_member { + Value::UnboundMember(ElementRef(e)) + } else { + Value::Unbound(ElementRef(e)) + } } else { Value::Element(ElementRef(e)) } } fn feature_value_in(&mut self, e: usize, ctx: Option) -> Result_ { + // Reading a local/output directly must not bypass the refusal at + // invocation: its initializer need not be its value after execution. + let mut owner = self.b.owner_elem(e); + while let Some(o) = owner { + if self.b.calculation_requires_execution(o) { + return Err(EvalError::Unsupported( + "calculation body requires statement execution".into(), + )); + } + owner = self.b.owner_elem(o); + } if let Some(v) = self.overrides.get(&e) { return Ok(v.clone()); } @@ -831,6 +1161,9 @@ impl Evaluator<'_> { _ => return Ok(self.placeholder(e)), }, }; + if (inherited || self.b.default_values.contains(&e)) && self.receiver_member(e).is_some() { + return Ok(Value::Indeterminate); + } let scope = ctx.unwrap_or(scope); if !self.in_progress.insert((e, scope)) { if inherited { @@ -894,11 +1227,7 @@ impl Evaluator<'_> { else { return Some((1.0, 1.0)); }; - let as_num = |v: Value| match v { - Value::Integer(i) => Some(i as f64), - Value::Rational(f) => Some(f), - _ => None, - }; + let as_num = |v: Value| v.as_f64(); let hi = as_num(self.expr(scope, &m.upper).ok()?)?; let lo = match &m.lower { Some(l) => as_num(self.expr(scope, l).ok()?)?, @@ -908,7 +1237,37 @@ impl Evaluator<'_> { Some((lo, hi)) } + /// The single exit for a freshly materialized value: it charges a + /// sequence or string against the allocation budget and hands it + /// back. Every operator that *builds* one passes it through here — + /// arithmetic and ranges, the control functions, the intrinsics, a + /// lambda or function reference applied per item, and sequence + /// construction — so many individually admissible values cannot add + /// up without bound. Values that merely flow through references + /// (a feature read, an index, a parameter binding) are not charged + /// again. + fn charged(&mut self, value: Value) -> Result_ { + let bytes = match &value { + Value::Sequence(items) => items.len().saturating_mul(std::mem::size_of::()), + Value::String(s) => s.len(), + _ => return Ok(value), + }; + self.allocated = self.allocated.saturating_add(bytes); + if self.allocated > MAX_ALLOCATION { + return Err(EvalError::Budget(format!( + "evaluation materialized more than {MAX_ALLOCATION} bytes of sequences and strings" + ))); + } + Ok(value) + } + fn expr(&mut self, scope: usize, e: &Expr) -> Result_ { + self.steps += 1; + if self.steps > MAX_STEPS { + return Err(EvalError::Budget(format!( + "evaluation exceeded {MAX_STEPS} steps" + ))); + } match &e.kind { ExprKind::Literal(l) => self.literal(l), ExprKind::Null => Ok(Value::null()), @@ -925,26 +1284,24 @@ impl Evaluator<'_> { ExprKind::Binary { op, lhs, rhs } => self.binary(scope, *op, lhs, rhs), ExprKind::Unary { op, operand } => { let v = self.expr(scope, operand)?; - if matches!(v, Value::Unbound(_) | Value::Indeterminate) - && !matches!(op, UnaryOp::Tilde) + if matches!( + v, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) && !matches!(op, UnaryOp::Tilde) { return Ok(Value::Indeterminate); } match op { UnaryOp::Plus => Ok(v), UnaryOp::Minus => match v { - Value::Integer(i) => Ok(Value::Integer(-i)), - Value::Rational(r) => Ok(Value::Rational(-r)), - Value::Quantity(n, u) => match *n { - Value::Integer(i) => { - Ok(Value::Quantity(Box::new(Value::Integer(-i)), u)) - } - Value::Rational(r) => { - Ok(Value::Quantity(Box::new(Value::Rational(-r)), u)) - } - _ => Err(EvalError::Type("unary `-` needs a number".into())), + Value::Quantity(n, u) => match n.num() { + Some(x) => Ok(Value::Quantity(Box::new(Value::from_num(x.neg())), u)), + None => Err(EvalError::Type("unary `-` needs a number".into())), + }, + v => match v.num() { + Some(x) => Ok(Value::from_num(x.neg())), + None => Err(EvalError::Type("unary `-` needs a number".into())), }, - _ => Err(EvalError::Type("unary `-` needs a number".into())), }, UnaryOp::Not => match v { Value::Boolean(b) => Ok(Value::Boolean(!b)), @@ -958,7 +1315,7 @@ impl Evaluator<'_> { let tval = self.expr(scope, target)?; let i = match self.expr(scope, index)? { Value::Integer(i) => i, - Value::Unbound(_) | Value::Indeterminate => { + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { return Ok(Value::Indeterminate); } _ => return Err(EvalError::Type("index must be an integer".into())), @@ -973,7 +1330,7 @@ impl Evaluator<'_> { // sequence. match &tval { Value::Indeterminate => return Ok(Value::Indeterminate), - Value::Unbound(ElementRef(e)) => { + Value::Unbound(ElementRef(e)) | Value::UnboundMember(ElementRef(e)) => { let bounds = self.unbound_cardinality(*e); let admitted = i >= 1 && bounds.is_none_or(|(_, hi)| hi.is_infinite() || i as f64 <= hi); @@ -998,7 +1355,10 @@ impl Evaluator<'_> { } ExprKind::Bracket { target, arg } => { let num = self.expr(scope, target)?; - if matches!(num, Value::Unbound(_) | Value::Indeterminate) { + if matches!( + num, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) { return Ok(Value::Indeterminate); } let unit = self.unit_of(scope, arg)?; @@ -1013,7 +1373,7 @@ impl Evaluator<'_> { let num = match num { Value::Quantity(n, u) => { if same_dims(&u, &unit) && u.scale != unit.scale { - scale_magnitude(*n, u.scale / unit.scale)? + scale_magnitude(*n, &scale_ratio(&u.scale, &unit.scale))? } else { *n } @@ -1024,17 +1384,17 @@ impl Evaluator<'_> { // A bracket expression that cancels completely // (`[m/m]`, `[mm/m]`) is dimensionless — any // residual scale folds into the number. - return if unit.scale == 1.0 { + return if unit.scale.is_one() { Ok(num) } else { - match num.as_f64() { - Some(f) => Ok(Value::Rational(f * unit.scale)), + match num.num() { + Some(n) => Ok(Value::from_num(n.scale(&unit.scale))), None => Ok(num), } }; } match num { - Value::Integer(_) | Value::Rational(_) => { + Value::Integer(_) | Value::Rational(_) | Value::Real(_) => { Ok(Value::Quantity(Box::new(num), unit)) } // A sequence magnitude is a vector quantity — @@ -1047,8 +1407,13 @@ impl Evaluator<'_> { Value::Sequence(items) => { for it in &items { match it { - Value::Integer(_) | Value::Rational(_) | Value::Quantity(..) => {} - Value::Unbound(_) | Value::Indeterminate => { + Value::Integer(_) + | Value::Rational(_) + | Value::Real(_) + | Value::Quantity(..) => {} + Value::Unbound(_) + | Value::UnboundMember(_) + | Value::Indeterminate => { return Ok(Value::Indeterminate); } other => { @@ -1078,7 +1443,7 @@ impl Evaluator<'_> { // first (positional only), user-defined calculations after. if values.iter().all(|(n, _)| n.is_none()) { let positional: Vec = values.iter().map(|(_, v)| v.clone()).collect(); - match self.intrinsic(ty, positional) { + match self.intrinsic(ty, &positional) { Err(EvalError::Unsupported(_)) => {} out => return out, } @@ -1093,7 +1458,7 @@ impl Evaluator<'_> { for i in items { out.extend(self.expr(scope, i)?.items()); } - Ok(Value::Sequence(out)) + self.charged(Value::Sequence(out)) } ExprKind::Classification { op, operand, ty } => { self.classification(scope, *op, operand.as_deref(), ty) @@ -1107,12 +1472,20 @@ impl Evaluator<'_> { Ok(match l { Literal::Bool(b) => Value::Boolean(*b), Literal::String(s) => Value::String(s.clone()), - Literal::Integer(raw) => raw - .parse::() - .map(Value::Integer) - .unwrap_or(Value::Rational(raw.parse().unwrap_or(f64::INFINITY))), - Literal::Real(raw) => Value::Rational(raw.parse().unwrap_or(f64::NAN)), - Literal::Infinity => Value::Rational(f64::INFINITY), + // Numbers are exact: an integer beyond `i128` and every + // decimal spelling become rationals with no intermediate + // double. Only an exponent too large to materialize degrades + // to the double parser (infinity). + Literal::Integer(raw) => match raw.parse::() { + Ok(i) => Value::Integer(i), + Err(_) => Rational::parse_decimal(raw) + .map(|r| Value::from_num(Num::Exact(r))) + .unwrap_or_else(|| Value::Real(raw.parse().unwrap_or(f64::INFINITY))), + }, + Literal::Real(raw) => Rational::parse_decimal(raw) + .map(|r| Value::from_num(Num::Exact(r))) + .unwrap_or_else(|| Value::Real(raw.parse().unwrap_or(f64::INFINITY))), + Literal::Infinity => Value::Real(f64::INFINITY), }) } @@ -1121,6 +1494,9 @@ impl Evaluator<'_> { /// owner (the receiver, under a featuring context); a type's body /// reads `that` as the type's own instance. fn featuring_instance(&mut self, elem: usize) -> Value { + if let Some(receiver) = self.unbound_receiver { + return Value::UnboundMember(ElementRef(receiver)); + } let ty = self.b.elements[elem].ty; let feature_like = ty.ends_with("Usage") || matches!( @@ -1150,7 +1526,7 @@ impl Evaluator<'_> { return Ok(v.clone()); } } - let Some(elem) = self.b.resolve(scope, qn, 0) else { + let Some(mut elem) = self.b.resolve(scope, qn, 0) else { // KerML `that` lives on the implied root feature `things`, // an implied specialization the resolver does not // materialize — a resolved declaration always wins, and only @@ -1169,11 +1545,84 @@ impl Evaluator<'_> { // redefinitions of the instance it was reached through. A // qualified path names an element elsewhere; its value uses its // own scope. - if qn.segments.len() == 1 && !qn.is_global { - self.feature_value_in(elem, Some(scope)) + let previous = self.unbound_receiver; + let mut member_scope = scope; + if let Some(receiver) = previous { + let hit = if qn.segments.len() == 1 && !qn.is_global { + self.receiver_member(elem) + } else { + None + }; + if let Some(hit) = hit { + // A method body resolves lexical names from its declaring + // type. Re-enter the receiver's redefinition context before + // reading them, just as a direct member chain does. + elem = hit; + member_scope = self.b.elem_scope.get(&receiver).copied().unwrap_or(scope); + } else if !self.receiver_context_contains(elem) { + self.unbound_receiver = None; + } + } + let value = if qn.segments.len() == 1 && !qn.is_global { + self.feature_value_in(elem, Some(member_scope)) } else { self.feature_value(elem) + }; + self.unbound_receiver = previous; + value + } + + /// The receiver's version of a lexical member, including a member + /// reached through an inherited method and redefined by the receiver. Call-local defaults and unrelated lexical declarations + /// do not become unknown just because their caller has no instance. + fn receiver_member(&mut self, elem: usize) -> Option { + let receiver = self.unbound_receiver?; + let value = self.b.id_name(elem)?; + let name = Name { + value, + span: Span::default(), + }; + let sub = self.b.elem_scope.get(&receiver).copied(); + let hit = self.b.resolve_rest(receiver, sub, &[name], 0)?; + let hit_owner = self.b.owner_elem(hit)?; + if !self.b.indexed_conforms(receiver, hit_owner) { + return None; + } + if self.b.indexed_conforms(hit, elem) { + return Some(hit); } + // SysML also permits redefinition by name in a specializing + // type, without an explicit :>> edge (the resolver's same-name + // shadowing rule). Unrelated locals with the same name do not + // satisfy this owner relationship. + if self.b.elements[hit].ty.ends_with("Usage") { + let owner = self.b.owner_elem(hit)?; + let base_owner = self.b.owner_elem(elem)?; + if owner != base_owner + && self.b.indexed_conforms(owner, base_owner) + && !self.b.indexed_conforms(base_owner, owner) + { + return Some(hit); + } + } + None + } + + /// A method-local expression may still read the receiver's fields. + /// Preserve its lexical context without treating the local itself as + /// a receiver member; imported declarations have unrelated owners. + fn receiver_context_contains(&mut self, elem: usize) -> bool { + let Some(receiver) = self.unbound_receiver else { + return false; + }; + let mut owner = self.b.owner_elem(elem); + while let Some(o) = owner { + if self.b.indexed_conforms(receiver, o) { + return true; + } + owner = self.b.owner_elem(o); + } + false } /// `new T(args)` — instantiate `T`, binding arguments to its owned @@ -1240,12 +1689,18 @@ impl Evaluator<'_> { .iter() .filter(|(_, e)| !self.b.values.contains_key(e)); let mut fields = Vec::with_capacity(values.len()); + let mut bound = HashSet::new(); for (name, v) in values { match name { Some(n) => { if !declared.iter().any(|(f, _)| *f == n) { return Err(EvalError::Unresolved(format!("field `{n}` of `{ty_name}`"))); } + if !bound.insert(n.clone()) { + return Err(EvalError::Type(format!( + "constructor field `{n}` is bound more than once" + ))); + } fields.push((n, v)); } None => { @@ -1254,6 +1709,11 @@ impl Evaluator<'_> { "too many constructor arguments for `{ty_name}`" ))); }; + if !bound.insert(f.clone()) { + return Err(EvalError::Type(format!( + "constructor field `{f}` is bound more than once" + ))); + } fields.push((f.clone(), v)); } } @@ -1284,7 +1744,16 @@ impl Evaluator<'_> { /// possibly-equal values need `collect`, and why /// `engines.specificImpulseVacuum` over five identical engines is /// one number, not five. + /// Uncertainty follows the evaluated receiver, including a receiver + /// returned by an alias, conditional or calculation. fn chain_into(&mut self, target: Value, member: &QualifiedName) -> Result_ { + // An unknown target has nothing to resolve a member against, and + // the step is as parametric as the target was: strictly + // propagating (see [`Value::Indeterminate`]) rather than a type + // error, so `subject.part.attribute` stays one undecided verdict. + if matches!(target, Value::Indeterminate) { + return Ok(Value::Indeterminate); + } if let Value::Sequence(items) = target { let mut out: Vec = Vec::new(); for item in items { @@ -1312,7 +1781,15 @@ impl Evaluator<'_> { EvalError::Type(format!("field `{name}` of `{ty_name}` is not bound")) }); } - let (Value::Element(ElementRef(elem)) | Value::Unbound(ElementRef(elem))) = target else { + let unbound = match &target { + Value::UnboundMember(_) => true, + Value::Unbound(e) => self.b.is_reference_feature(e.0), + _ => false, + }; + let (Value::Element(ElementRef(elem)) + | Value::Unbound(ElementRef(elem)) + | Value::UnboundMember(ElementRef(elem))) = target + else { return Err(EvalError::Type( "chain target must be a model element".into(), )); @@ -1333,7 +1810,7 @@ impl Evaluator<'_> { // (SysML 8.4.2 Table 32), which the model deliberately does not // materialize as relationships. `p.performedActions` collects // p's perform usages, each standing for its referenced action. - if !self.b.values.contains_key(&hit) { + if !unbound && !self.b.values.contains_key(&hit) { // A named slot answers with its owned parts before the general // collection rule, which would otherwise collect the slot // itself (it specializes the member it redefines). @@ -1350,7 +1827,14 @@ impl Evaluator<'_> { return Ok(v); } } - self.feature_value_in(hit, sub) + // Evaluate fixed formulas in the unknown receiver's context too: + // `eligible = willing` fixes the formula, not a default on willing. + // A concrete receiver establishes a fresh, known context. + let previous = self.unbound_receiver; + self.unbound_receiver = unbound.then_some(elem); + let value = self.feature_value_in(hit, sub); + self.unbound_receiver = previous; + value } /// A named slot's value: when the receiver owns a part that only @@ -1661,10 +2145,8 @@ impl Evaluator<'_> { let id = self.b.elements[r] .props .get("referencedFeature") - .and_then(|v| v.get("@id")) - .and_then(|v| v.as_str()) - .map(str::to_string); - if let Some(t) = id.and_then(|id| self.b.element_index_of_id(&id)) { + .and_then(|v| v.as_reference()); + if let Some(t) = id.and_then(|id| self.b.element_index_of_uuid(id)) { return Some(t); } } @@ -1687,7 +2169,11 @@ impl Evaluator<'_> { }) } - fn unit_dims(&mut self, scope: usize, e: &Expr) -> Result<(Vec, f64, String), EvalError> { + fn unit_dims( + &mut self, + scope: usize, + e: &Expr, + ) -> Result<(Vec, Rational, String), EvalError> { match &e.kind { ExprKind::Ref(qn) => { let elem = self @@ -1709,7 +2195,7 @@ impl Evaluator<'_> { let (rd, rs, rdisp) = self.unit_dims(scope, rhs)?; Ok(( dims_combine(&ld, &rd, 1), - ls * rs, + ls.mul(&rs), format!("{ldisp}*{rdisp}"), )) } @@ -1717,12 +2203,16 @@ impl Evaluator<'_> { let (rd, rs, rdisp) = self.unit_dims(scope, rhs)?; Ok(( dims_combine(&ld, &rd, -1), - ls / rs, + scale_ratio(&ls, &rs), format!("{ldisp}/{rdisp}"), )) } BinaryOp::Pow | BinaryOp::Caret => match unit_exponent(rhs) { - Some(k) => Ok((dims_pow(&ld, (k, 1)), ls.powi(k), format!("{ldisp}**{k}"))), + Some(k) => Ok(( + dims_pow(&ld, (k, 1)), + ls.pow_or_approx(k), + format!("{ldisp}**{k}"), + )), None => Err(EvalError::Unsupported( "a unit exponent that is not an integer literal".into(), )), @@ -1758,7 +2248,49 @@ impl Evaluator<'_> { elem: usize, name: String, depth: u32, - ) -> (Vec, f64) { + ) -> (Vec, Rational) { + // Recursive/bound evaluations can have context-dependent cutoffs. + // Cache only complete unbound top-level reductions, and include the + // spelling switch and fallback scope in the key. + let cacheable = self.b.semantic_ready + && depth == 0 + && self.env.is_empty() + && self.overrides.is_empty() + && self.in_progress.is_empty() + && !self.query + && self.call_depth == 0; + if !cacheable { + return self.expanded_unit_uncached(scope, elem, name, depth); + } + let key = ( + self.b.owner_scope_of(elem).unwrap_or(scope), + elem, + name.clone(), + unit_spelling_expansion(), + ); + if let Some(hit) = self.b.semantic_memo.units.get(&key).cloned() { + self.b.used_imports.extend(hit.imports); + return hit.value; + } + let imports = std::mem::take(&mut self.b.used_imports); + let value = self.expanded_unit_uncached(scope, elem, name, depth); + self.b.semantic_memo.units.insert( + key, + crate::semantic_memo::Proven { + value: value.clone(), + imports: self.b.used_imports.iter().copied().collect(), + }, + ); + self.b.used_imports.extend(imports); + value + } + fn expanded_unit_uncached( + &mut self, + scope: usize, + elem: usize, + name: String, + depth: u32, + ) -> (Vec, Rational) { if depth < 8 { if let Some(out) = self.conversion_dims(elem, depth) { return out; @@ -1787,7 +2319,7 @@ impl Evaluator<'_> { num: 1, den: 1, }], - 1.0, + Rational::one(), ) } @@ -1804,11 +2336,11 @@ impl Evaluator<'_> { elem: usize, name: &str, depth: u32, - ) -> Option<(Vec, f64)> { + ) -> Option<(Vec, Rational)> { let factors = parse_unit_spelling(name)?; let scope = self.b.owner_scope_of(elem).unwrap_or(scope); let mut dims: Vec = Vec::new(); - let mut scale = 1.0f64; + let mut scale = Rational::one(); for (sym, exp) in factors { let qn = QualifiedName { is_global: false, @@ -1824,7 +2356,7 @@ impl Evaluator<'_> { } let (cd, cs) = self.expanded_unit(scope, c, sym, depth + 1); dims = dims_combine(&dims, &dims_pow(&cd, (exp, 1)), 1); - scale *= cs.powi(exp); + scale = scale.mul(&cs.pow_or_approx(exp)); } Some((dims, scale)) } @@ -1834,7 +2366,7 @@ impl Evaluator<'_> { /// `referenceUnit` to a unit element and `conversionFactor` to a /// finite positive number (the abstract inherited members on every /// `MeasurementUnit` are valueless and fall out here). - fn conversion_dims(&mut self, elem: usize, depth: u32) -> Option<(Vec, f64)> { + fn conversion_dims(&mut self, elem: usize, depth: u32) -> Option<(Vec, Rational)> { let seg = |s: &str| { vec![Name { value: s.to_string(), @@ -1850,34 +2382,43 @@ impl Evaluator<'_> { let member = |b: &mut Self, owner: usize, scope: Option, name: &str| { let hit = b.b.resolve_rest(owner, scope, &seg(name), 0)?; match b.feature_value_in(hit, scope) { - Ok(Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))) if e == hit => { - None - } + Ok( + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)), + ) if e == hit => None, Ok(v) => Some(v), Err(_) => None, } }; let ref_unit = match member(self, conv, conv_scope, "referenceUnit")? { - Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) => e, + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) => e, _ => return None, }; // `ConversionByConvention` binds `conversionFactor` directly; // `ConversionByPrefix` derives it as `prefix.conversionFactor` // (MeasurementReferences.sysml) — follow that derivation // explicitly when the direct member is unbound. - let factor = - match member(self, conv, conv_scope, "conversionFactor").and_then(|v| v.as_f64()) { - Some(f) => f, - None => { - let prefix = match member(self, conv, conv_scope, "prefix")? { - Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) => e, - _ => return None, - }; - let p_scope = self.b.elem_scope.get(&prefix).copied(); - member(self, prefix, p_scope, "conversionFactor")?.as_f64()? - } - }; - if !factor.is_finite() || factor <= 0.0 { + let factor = match member(self, conv, conv_scope, "conversionFactor").and_then(|v| v.num()) + { + Some(f) => f, + None => { + let prefix = match member(self, conv, conv_scope, "prefix")? { + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) => e, + _ => return None, + }; + let p_scope = self.b.elem_scope.get(&prefix).copied(); + member(self, prefix, p_scope, "conversionFactor")?.num()? + } + }; + // An approximate factor (an irrational user conversion) enters + // the scale as the exact value of its double. + let factor = factor.exact()?; + if !factor.is_positive() { return None; } let ref_name = self.b.elements[ref_unit] @@ -1892,7 +2433,7 @@ impl Evaluator<'_> { // fallback. let ref_scope = conv_scope.unwrap_or(0); let (dims, ref_scale) = self.expanded_unit(ref_scope, ref_unit, ref_name, depth + 1); - Some((dims, factor * ref_scale)) + Some((dims, factor.mul(&ref_scale))) } /// `unit_dims`, but for a candidate derived-unit *definition*: any @@ -1903,7 +2444,7 @@ impl Evaluator<'_> { scope: usize, e: &Expr, depth: u32, - ) -> Option<(Vec, f64)> { + ) -> Option<(Vec, Rational)> { match &e.kind { ExprKind::Ref(qn) => { let elem = self.b.resolve(scope, qn, 0)?; @@ -1915,15 +2456,15 @@ impl Evaluator<'_> { match op { BinaryOp::Mul => { let (rd, rs) = self.power_product_dims(scope, rhs, depth)?; - Some((dims_combine(&ld, &rd, 1), ls * rs)) + Some((dims_combine(&ld, &rd, 1), ls.mul(&rs))) } BinaryOp::Div => { let (rd, rs) = self.power_product_dims(scope, rhs, depth)?; - Some((dims_combine(&ld, &rd, -1), ls / rs)) + Some((dims_combine(&ld, &rd, -1), scale_ratio(&ls, &rs))) } BinaryOp::Pow | BinaryOp::Caret => { let k = unit_exponent(rhs)?; - Some((dims_pow(&ld, (k, 1)), ls.powi(k))) + Some((dims_pow(&ld, (k, 1)), ls.pow_or_approx(k))) } _ => None, } @@ -2003,7 +2544,10 @@ impl Evaluator<'_> { // discipline). ClassificationOp::AtType => { for v in &items { - let (Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))) = v else { + let (Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e))) = v + else { return Err(EvalError::Type( "the metadata test `@` applies to model elements".into(), )); @@ -2032,7 +2576,9 @@ impl Evaluator<'_> { for v in items { match v { Value::Instance { .. } => metas.push(v), - Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) => { + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) => { if matches!(self.b.elements[e].ty, "MetadataUsage" | "MetadataFeature") { // An annotation already *is* a metaobject. @@ -2075,7 +2621,9 @@ impl Evaluator<'_> { if target.segments.len() == 1 && !target.is_global { let name = &target.segments[0].value; if let Some((_, v)) = self.env.iter().rev().find(|(n, _)| n == name) { - let (Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))) = v.clone() + let (Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e))) = v.clone() else { return Err(EvalError::Type( "`.metadata` applies to model elements".into(), @@ -2123,7 +2671,7 @@ impl Evaluator<'_> { not loaded)" )) })?; - let props = self.b.elements[elem].props.clone(); + let props = self.b.elements[elem].props.to_json(); let mut fields = Vec::new(); for (k, v) in props { let value = match v { @@ -2131,7 +2679,12 @@ impl Evaluator<'_> { serde_json::Value::Bool(b) => Value::Boolean(b), serde_json::Value::Number(n) => match n.as_i64() { Some(i) => Value::Integer(i as i128), - None => Value::Rational(n.as_f64().unwrap_or(f64::NAN)), + // A JSON number's decimal spelling is the value + // meant; read it exactly rather than through a double. + None => match Rational::parse_decimal(&n.to_string()) { + Some(r) => Value::from_num(Num::Exact(r)), + None => Value::Real(n.as_f64().unwrap_or(f64::NAN)), + }, }, _ => continue, }; @@ -2155,7 +2708,9 @@ impl Evaluator<'_> { fn metaobject_conforms(&mut self, v: &Value, target: usize) -> Result { let classifier = match v { Value::Instance { ty, .. } => ty.0, - Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) => *e, + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) => *e, _ => { return Err(EvalError::Type( "metadata classification applies to metaobjects".into(), @@ -2215,10 +2770,21 @@ impl Evaluator<'_> { "Number", "ScalarValue", ]), + Value::Rational(r) if r.is_integer() => scalar(&[ + "Integer", + "Rational", + "Real", + "Complex", + "Number", + "ScalarValue", + ]), Value::Rational(_) => scalar(&["Rational", "Real", "Complex", "Number", "ScalarValue"]), + Value::Real(_) => scalar(&["Real", "Complex", "Number", "ScalarValue"]), Value::Boolean(_) => scalar(&["Boolean", "ScalarValue"]), Value::String(_) => scalar(&["String", "ScalarValue"]), - Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) => { + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) => { if !direct && self.conforms_upward(*e, target) { return Ok(Some(true)); } @@ -2337,8 +2903,10 @@ impl Evaluator<'_> { .map(|(_, v)| v.clone()); if let Some(value) = bound { return match value { - Value::Element(ElementRef(elem)) | Value::Unbound(ElementRef(elem)) => { - self.user_calc_elem(display, elem, args) + Value::Element(ElementRef(elem)) + | Value::Unbound(ElementRef(elem)) + | Value::UnboundMember(ElementRef(elem)) => { + self.user_calc_elem(&display, elem, args) } Value::Indeterminate => Ok(Value::Indeterminate), other => Err(EvalError::Type(format!( @@ -2369,7 +2937,7 @@ impl Evaluator<'_> { (display, elem) } }; - self.user_calc_elem(display, elem, args) + self.user_calc_elem(&display, elem, args) } /// Invoke an already-resolved calculation element. Kept separate from @@ -2377,10 +2945,34 @@ impl Evaluator<'_> { /// concrete element bound in the current calculation frame. fn user_calc_elem( &mut self, - display: String, + display: &str, elem: usize, args: Vec<(Option, Value)>, ) -> Result_ { + let previous = self.unbound_receiver; + let elem = match self.receiver_member(elem) { + Some(hit) => hit, + None => { + self.unbound_receiver = None; + elem + } + }; + let value = self.user_calc_body(display, elem, args); + self.unbound_receiver = previous; + value + } + + fn user_calc_body( + &mut self, + display: &str, + elem: usize, + args: Vec<(Option, Value)>, + ) -> Result_ { + if self.b.calculation_requires_execution(elem) { + return Err(EvalError::Unsupported( + "calculation body requires statement execution".into(), + )); + } let has_body = self.b.result_exprs.iter().any(|(o, _, _)| *o == elem) || self .b @@ -2395,44 +2987,99 @@ impl Evaluator<'_> { // Validate and bind arguments before the abstract/bodiless fallback: // an unknown result does not make an invalid invocation well-formed. let params = self.callee_params(elem); - let depth = self.env.len(); + // Parameters belong to this invocation. A missing argument/default + // must never capture a same-named parameter from the calling frame. + let caller_env = self.env.clone(); + self.env.retain(|(name, _)| !params.contains(name)); let mut positional = 0usize; + let mut bound = HashSet::new(); for (name, v) in args { match name { Some(n) => { if !params.contains(&n) { - self.env.truncate(depth); + self.env = caller_env; return Err(EvalError::Unresolved(format!( "parameter `{n}` of `{display}`" ))); } + if !bound.insert(n.clone()) { + self.env = caller_env; + return Err(EvalError::Type(format!( + "parameter `{n}` of `{display}` is bound more than once" + ))); + } self.env.push((n, v)); } None => { let Some(p) = params.get(positional) else { - self.env.truncate(depth); + self.env = caller_env; return Err(EvalError::Type(format!( "too many arguments to `{display}`" ))); }; + if !bound.insert(p.clone()) { + self.env = caller_env; + return Err(EvalError::Type(format!( + "parameter `{p}` of `{display}` is bound more than once" + ))); + } self.env.push((p.clone(), v)); positional += 1; } } } + if has_body { + for name in ¶ms { + if bound.contains(name) { + continue; + } + let mut stack = vec![elem]; + let mut seen = HashSet::new(); + let mut parameter = None; + while let Some(owner) = stack.pop() { + if !seen.insert(owner) { + continue; + } + if let Some((_, field)) = self + .b + .ctor_fields + .get(&owner) + .and_then(|fields| fields.iter().find(|(n, _)| n == name)) + { + parameter = Some(*field); + break; + } + stack.extend(self.b.explicit_supertype_elems(owner)); + } + let Some(parameter) = parameter.filter(|p| self.b.values.contains_key(p)) else { + self.env = caller_env; + return Err(EvalError::Unresolved(format!( + "unbound parameter `{name}` of `{display}`" + ))); + }; + let value = match self.feature_value(parameter) { + Ok(value) => value, + Err(error) => { + self.env = caller_env; + return Err(error); + } + }; + self.env.push((name.clone(), value)); + } + } // A calculation's result is its trailing result expression, or — // the `return x = expr;` spelling — its return parameter's value. enum CalcBody { Result(usize, Expr), Return(usize), } - let body = match self + let result = self .b .result_exprs .iter() .find(|(o, _, _)| *o == elem) - .map(|(_, s, e)| (*s, e.clone())) - { + .map(|(_, s, e)| (*s, e.clone())); + let body = match result { Some((s, e)) => CalcBody::Result(s, e), None => match self.b.return_params.get(&elem) { Some(&ret) if self.b.values.contains_key(&ret) => CalcBody::Return(ret), @@ -2444,19 +3091,24 @@ impl Evaluator<'_> { // Non-callable targets keep the error (degrading // those would mask a genuine model defect). if self.callee_is_calculation(elem) { - self.env.truncate(depth); + self.env = caller_env; return Ok(Value::Indeterminate); } - self.env.truncate(depth); + self.env = caller_env; return Err(EvalError::Unsupported(format!( "function `{display}` (no result expression)" ))); } }, }; - if self.call_depth >= 64 { - self.env.truncate(depth); - return Err(EvalError::Cycle(display)); + // Call depth is a budget, not a cycle: a recursion that does not + // terminate reaches it, and so does a legitimately deep chain of + // distinct calculations. + if self.call_depth >= MAX_CALL_DEPTH { + self.env = caller_env; + return Err(EvalError::Budget(format!( + "evaluation nested more than {MAX_CALL_DEPTH} calculation calls, at `{display}`" + ))); } self.call_depth += 1; // A library-owned callee evaluates in a library frame: its body @@ -2474,7 +3126,7 @@ impl Evaluator<'_> { self.lib_frames -= 1; } self.call_depth -= 1; - self.env.truncate(depth); + self.env = caller_env; out } @@ -2493,7 +3145,8 @@ impl Evaluator<'_> { .unwrap_or(false) }; match (a, b) { - (Value::Unbound(_), _) | (_, Value::Unbound(_)) => { + (Value::Unbound(_) | Value::UnboundMember(_), _) + | (_, Value::Unbound(_) | Value::UnboundMember(_)) => { Err(EvalError::Type("comparison with an unbound feature".into())) } (Value::Element(x), Value::Element(y)) => { @@ -2510,8 +3163,8 @@ impl Evaluator<'_> { if u == v { Ok(value_eq(x, y)) } else if same_dims(u, v) { - match (x.as_f64(), y.as_f64()) { - (Some(a), Some(b)) => Ok(a * u.scale == b * v.scale), + match (x.num(), y.num()) { + (Some(a), Some(b)) => Ok(a.scale(&u.scale).eq(&b.scale(&v.scale))), _ => Err(EvalError::Type("numeric operands required".into())), } } else { @@ -2538,7 +3191,7 @@ impl Evaluator<'_> { fn tri_boolean(&mut self, scope: usize, e: &Expr) -> Result, EvalError> { match self.expr(scope, e)? { Value::Boolean(b) => Ok(Some(b)), - Value::Unbound(_) | Value::Indeterminate => Ok(None), + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => Ok(None), other => Err(EvalError::Type(format!("expected a boolean, got {other}"))), } } @@ -2605,12 +3258,16 @@ impl Evaluator<'_> { // error — a parametric formula over an unbound feature degrades // to an indeterminate value. Closed `Element` values still // type-error below (an enum literal is not a number). - if matches!(l, Value::Unbound(_) | Value::Indeterminate) - || matches!(r, Value::Unbound(_) | Value::Indeterminate) - { + if matches!( + l, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) || matches!( + r, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) { return Ok(Value::Indeterminate); } - match op { + let value = match op { AndAmp | Xor | OrBar => match (l, r) { (Value::Boolean(a), Value::Boolean(b)) => Ok(Value::Boolean(match op { AndAmp => a && b, @@ -2632,13 +3289,27 @@ impl Evaluator<'_> { } Range => match (l, r) { (Value::Integer(a), Value::Integer(b)) => { - Ok(Value::Sequence((a..=b).map(Value::Integer).collect())) + // Checked: the bounds may span the whole `i128` range. + let count = if b < a { + Some(0) + } else { + b.checked_sub(a).and_then(|n| n.checked_add(1)) + }; + match count { + Some(n) if n <= MAX_SEQUENCE as i128 => { + Ok(Value::Sequence((a..=b).map(Value::Integer).collect())) + } + _ => Err(EvalError::Budget(format!( + "range `{a}..{b}` has more than {MAX_SEQUENCE} elements" + ))), + } } _ => Err(EvalError::Type("`..` needs integer bounds".into())), }, Add | Sub | Mul | Div | Rem | Pow | Caret => arith(op, l, r), _ => unreachable!("short-circuit ops handled above"), - } + }?; + self.charged(value) } /// `target->Fn (args)` / `->Fn {body}` — invocation with the target as @@ -2661,7 +3332,7 @@ impl Evaluator<'_> { } if values.iter().all(|(n, _)| n.is_none()) { let positional: Vec = values.iter().map(|(_, v)| v.clone()).collect(); - match self.intrinsic(ty, positional) { + match self.intrinsic(ty, &positional) { Err(EvalError::Unsupported(_)) => {} out => return out, } @@ -2687,12 +3358,16 @@ impl Evaluator<'_> { /// Control functions with a lambda body over a sequence. /// Apply a control function's per-item computation: a `{ … }` lambda - /// body, or a referenced function (`->reduce '+'`). + /// body, or a referenced function (`->reduce '+'`). A per-item result + /// is a materialized value like any other — a fold over a thousand + /// items builds a thousand of them — so it leaves through + /// [`Self::charged`]. fn apply(&mut self, scope: usize, applier: &Applier<'_>, args: &[Value]) -> Result_ { - match applier { - Applier::Lambda(body) => self.apply_lambda(scope, body, args), - Applier::FnRef(qn) => self.apply_fn_ref(scope, qn, args.to_vec()), - } + let value = match applier { + Applier::Lambda(body) => self.apply_lambda(scope, body, args)?, + Applier::FnRef(qn) => self.apply_fn_ref(scope, qn, args.to_vec())?, + }; + self.charged(value) } /// Apply a *referenced* function to arguments: operator spellings @@ -2716,7 +3391,7 @@ impl Evaluator<'_> { return arith(op, l.clone(), r.clone()); } } - match self.intrinsic(&TargetRef::Name(qn.clone()), args.clone()) { + match self.intrinsic(&TargetRef::Name(qn.clone()), &args) { Err(EvalError::Unsupported(_)) => {} out => return out, } @@ -2724,12 +3399,25 @@ impl Evaluator<'_> { self.user_calc(scope, &TargetRef::Name(qn.clone()), named) } + /// A control function's own result — the collected, selected or + /// folded value — through the allocation budget. fn control( &mut self, scope: usize, name: &str, target: Value, applier: &Applier<'_>, + ) -> Result_ { + let value = self.control_uncharged(scope, name, target, applier)?; + self.charged(value) + } + + fn control_uncharged( + &mut self, + scope: usize, + name: &str, + target: Value, + applier: &Applier<'_>, ) -> Result_ { let items = target.items(); match name { @@ -2751,7 +3439,9 @@ impl Evaluator<'_> { out.push(item.clone()); } } - Value::Unbound(_) | Value::Indeterminate => unknown = true, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { + unknown = true + } _ => { return Err(EvalError::Type(format!( "{name} body must yield a boolean" @@ -2759,7 +3449,9 @@ impl Evaluator<'_> { } }, "forAll" => match v { - Value::Unbound(_) | Value::Indeterminate => unknown = true, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { + unknown = true + } v if v != Value::Boolean(true) => { return Ok(Value::Boolean(false)); } @@ -2767,7 +3459,9 @@ impl Evaluator<'_> { }, "exists" => match v { Value::Boolean(true) => return Ok(Value::Boolean(true)), - Value::Unbound(_) | Value::Indeterminate => unknown = true, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { + unknown = true + } _ => {} }, _ => unreachable!(), @@ -2788,7 +3482,7 @@ impl Evaluator<'_> { Value::Boolean(false) => {} // An unknown predicate makes *which* item is // selected unknown. - Value::Unbound(_) | Value::Indeterminate => { + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { return Ok(Value::Indeterminate); } _ => { @@ -2835,11 +3529,17 @@ impl Evaluator<'_> { // A non-body lambda argument evaluates as a plain expression. return self.expr(scope, body); }; + Self::check_expression_body(members)?; let mut params = Vec::new(); let mut result = None; for m in members { match &m.kind { - MemberKind::Usage(u) if u.prefix.direction.is_some() => { + MemberKind::Usage(u) + if matches!( + u.prefix.direction, + Some(FeatureDirection::In | FeatureDirection::InOut) + ) => + { if let Some(n) = &u.declaration.id.name { params.push(n.value.clone()); } @@ -2850,6 +3550,13 @@ impl Evaluator<'_> { } let result = result.ok_or_else(|| EvalError::Unsupported("lambda body without a result".into()))?; + if params.len() != args.len() { + return Err(EvalError::Type(format!( + "lambda expects {} argument(s), got {}", + params.len(), + args.len() + ))); + } let depth = self.env.len(); for (p, v) in params.iter().zip(args) { self.env.push((p.clone(), v.clone())); @@ -2861,6 +3568,7 @@ impl Evaluator<'_> { /// Evaluate a `{ …; result-expr }` body expression directly. fn body_result(&mut self, scope: usize, members: &[Member]) -> Result_ { + Self::check_expression_body(members)?; for m in members { if let MemberKind::Result(e) = &m.kind { return self.expr(scope, e); @@ -2871,6 +3579,23 @@ impl Evaluator<'_> { )) } + fn check_expression_body(members: &[Member]) -> Result<(), EvalError> { + if members.iter().any(crate::json::member_requires_execution) { + return Err(EvalError::Unsupported( + "calculation body requires statement execution".into(), + )); + } + if members + .iter() + .any(|m| matches!(&m.kind, MemberKind::Usage(u) if u.prefix.direction.is_none())) + { + return Err(EvalError::Unsupported( + "expression-body local declarations require scoped evaluation".into(), + )); + } + Ok(()) + } + /// The elements owned by `e` through its owned memberships, as /// [`Value::Element`]s — see [`Builder::owned_member_elems`]. fn owned_members(&self, e: usize, features_only: bool) -> Vec { @@ -2883,7 +3608,7 @@ impl Evaluator<'_> { /// One reflection answer over element `e` (empty sequence when the /// element has no such name). - fn reflect_element(&mut self, what: &str, e: usize) -> Value { + fn reflect_element(&self, what: &str, e: usize) -> Value { let props = &self.b.elements[e].props; let name = |k: &str| props.get(k).and_then(|v| v.as_str()).map(str::to_string); let some = |s: Option| { @@ -2935,35 +3660,55 @@ impl Evaluator<'_> { } /// Kernel Function Library intrinsics, matched by the invoked name's - /// last segment. - fn intrinsic(&mut self, ty: &TargetRef, args: Vec) -> Result_ { + /// last segment. An intrinsic that builds a sequence or a string + /// (`reverse`, `including`, `ToString`, `Substring`, …) returns it + /// through the allocation budget; an + /// [`EvalError::Unsupported`] answer is the "not an intrinsic" + /// sentinel invocation dispatch falls through on, and stays exactly + /// that. + fn intrinsic(&mut self, ty: &TargetRef, args: &[Value]) -> Result_ { + let value = self.intrinsic_uncharged(ty, args)?; + self.charged(value) + } + + fn intrinsic_uncharged(&mut self, ty: &TargetRef, args: &[Value]) -> Result_ { let TargetRef::Name(qn) = ty else { return Err(EvalError::Unsupported("chained function reference".into())); }; let name = qn.segments.last().unwrap().value.as_str(); let items = |v: &Value| v.clone().items(); - match (name, args.as_slice()) { + match (name, args) { // Reflection over the model structure (query mode only — // `sysmlv2 query` / `ResolvedModel::query` — so these names // can never shadow a user calculation in a model file): the // KerML derived properties `Namespace::ownedMember` / // `Type::ownedFeature` as functions over a model element. - ("ownedMember", [Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))]) - if self.query => - { - Ok(Value::Sequence(self.owned_members(*e, false))) - } - ("ownedFeature", [Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))]) - if self.query => - { - Ok(Value::Sequence(self.owned_members(*e, true))) - } + ( + "ownedMember", + [ + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)), + ], + ) if self.query => Ok(Value::Sequence(self.owned_members(*e, false))), + ( + "ownedFeature", + [ + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)), + ], + ) if self.query => Ok(Value::Sequence(self.owned_members(*e, true))), // Element reflection (query mode): names, metaclass and // documentation of a model element, as the rendering backend's // translated template expressions ask for them. ( "declaredName" | "shortName" | "qualifiedName" | "metaclass" | "docs", - [Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e))], + [ + Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)), + ], ) if self.query => Ok(self.reflect_element(name, *e)), ( "declaredName" | "shortName" | "qualifiedName" | "metaclass" | "docs", @@ -2971,7 +3716,10 @@ impl Evaluator<'_> { ) if self.query => { let mut out = Vec::new(); for item in items { - if let Value::Element(ElementRef(e)) | Value::Unbound(ElementRef(e)) = item { + if let Value::Element(ElementRef(e)) + | Value::Unbound(ElementRef(e)) + | Value::UnboundMember(ElementRef(e)) = item + { out.extend(self.reflect_element(name, *e).items()); } } @@ -2993,7 +3741,7 @@ impl Evaluator<'_> { // emptiness; anything else is honestly undecided. Sequences // *containing* placeholders keep their literal arity, and // library frames never mint Unbound in the first place. - ("size", [Value::Unbound(ElementRef(e))]) => { + ("size", [Value::Unbound(ElementRef(e)) | Value::UnboundMember(ElementRef(e))]) => { match self.unbound_cardinality(*e) { Some((lo, hi)) if lo == hi && lo.is_finite() => Ok(Value::Integer(lo as i128)), // Indeterminate, not an error — the cardinality is @@ -3004,16 +3752,20 @@ impl Evaluator<'_> { _ => Ok(Value::Indeterminate), } } - ("isEmpty", [Value::Unbound(ElementRef(e))]) => match self.unbound_cardinality(*e) { - Some((_, 0.0)) => Ok(Value::Boolean(true)), - Some((lo, _)) if lo >= 1.0 => Ok(Value::Boolean(false)), - _ => Ok(Value::Indeterminate), - }, - ("notEmpty", [Value::Unbound(ElementRef(e))]) => match self.unbound_cardinality(*e) { - Some((_, 0.0)) => Ok(Value::Boolean(false)), - Some((lo, _)) if lo >= 1.0 => Ok(Value::Boolean(true)), - _ => Ok(Value::Indeterminate), - }, + ("isEmpty", [Value::Unbound(ElementRef(e)) | Value::UnboundMember(ElementRef(e))]) => { + match self.unbound_cardinality(*e) { + Some((_, 0.0)) => Ok(Value::Boolean(true)), + Some((lo, _)) if lo >= 1.0 => Ok(Value::Boolean(false)), + _ => Ok(Value::Indeterminate), + } + } + ("notEmpty", [Value::Unbound(ElementRef(e)) | Value::UnboundMember(ElementRef(e))]) => { + match self.unbound_cardinality(*e) { + Some((_, 0.0)) => Ok(Value::Boolean(false)), + Some((lo, _)) if lo >= 1.0 => Ok(Value::Boolean(true)), + _ => Ok(Value::Indeterminate), + } + } // Cardinality/emptiness of an indeterminate value is itself // indeterminate. ("size" | "isEmpty" | "notEmpty", [Value::Indeterminate]) => Ok(Value::Indeterminate), @@ -3040,8 +3792,8 @@ impl Evaluator<'_> { Value::Boolean(name == "excludes") }) } - ("head", [s]) => Ok(items(s).first().cloned().unwrap_or(Value::null())), - ("last", [s]) => Ok(items(s).last().cloned().unwrap_or(Value::null())), + ("head", [s]) => Ok(items(s).first().cloned().unwrap_or_else(Value::null)), + ("last", [s]) => Ok(items(s).last().cloned().unwrap_or_else(Value::null)), ("tail", [s]) => { let mut i = items(s); if !i.is_empty() { @@ -3068,29 +3820,35 @@ impl Evaluator<'_> { ("max", [a, b]) => extremum(vec![a.clone(), b.clone()], true), ("min", [a, b]) => extremum(vec![a.clone(), b.clone()], false), ("abs", [v]) => match v { - Value::Integer(i) => Ok(Value::Integer(i.abs())), - Value::Rational(r) => Ok(Value::Rational(r.abs())), - Value::Quantity(n, u) => match **n { - Value::Integer(i) => Ok(Value::Quantity( - Box::new(Value::Integer(i.abs())), + Value::Quantity(n, u) => match n.num() { + Some(x) => Ok(Value::Quantity( + Box::new(Value::from_num(x.abs())), u.clone(), )), - Value::Rational(r) => Ok(Value::Quantity( - Box::new(Value::Rational(r.abs())), - u.clone(), - )), - _ => Err(EvalError::Type("abs needs a number".into())), + None => Err(EvalError::Type("abs needs a number".into())), + }, + v => match v.num() { + Some(x) => Ok(Value::from_num(x.abs())), + None => Err(EvalError::Type("abs needs a number".into())), }, - _ => Err(EvalError::Type("abs needs a number".into())), }, // sqrt is `^(1/2)` — on a quantity it also halves the unit - // exponents. - ("sqrt", [v @ Value::Quantity(..)]) => { - arith(BinaryOp::Pow, v.clone(), Value::Rational(0.5)) - } - ("sqrt", [v]) => num1(v, f64::sqrt), + // exponents. Exact when the root exists (`sqrt(0.25)` is + // `0.5`), otherwise a double. + ("sqrt", [v @ Value::Quantity(..)]) => arith( + BinaryOp::Pow, + v.clone(), + Value::Rational(Rational::new(1, 2).expect("non-zero denominator")), + ), + ("sqrt", [v]) => match v.num() { + Some(n) if n.is_negative() => { + Err(EvalError::Type("sqrt of a negative number".into())) + } + Some(n) => Ok(Value::from_num(n.root(2))), + None => Err(EvalError::Type("sqrt needs a number".into())), + }, ("ln", [v]) => match v.as_f64() { - Some(f) if f > 0.0 => Ok(Value::Rational(f.ln())), + Some(f) if f > 0.0 => Ok(Value::Real(f.ln())), Some(_) => Err(EvalError::Type("ln of a non-positive number".into())), None => Err(EvalError::Type("ln needs a number".into())), }, @@ -3099,9 +3857,12 @@ impl Evaluator<'_> { ("sin", [v]) => num1(v, f64::sin), ("cos", [v]) => num1(v, f64::cos), ("tan", [v]) => num1(v, f64::tan), - // RationalFunctions::rat — true division (our Rational is a - // numeric value, not a numerator/denominator pair). + // RationalFunctions::rat/numer/denom — exact division and the + // reduced fraction's parts (a double counts through its exact + // dyadic value). ("rat", [a, b]) => arith(BinaryOp::Div, a.clone(), b.clone()), + ("numer", [v]) => rational_part(v, true), + ("denom", [v]) => rational_part(v, false), // ComplexFunctions::re/im on real values. ("re", [v]) => match v.as_f64() { Some(_) => Ok(v.clone()), @@ -3112,26 +3873,26 @@ impl Evaluator<'_> { None => Err(EvalError::Type("im needs a number".into())), }, // NumericalFunctions::isZero/isUnit. - ("isZero", [v]) => match v.as_f64() { - Some(f) => Ok(Value::Boolean(f == 0.0)), + ("isZero", [v]) => match v.num() { + Some(n) => Ok(Value::Boolean(n.is_zero())), None => Err(EvalError::Type("isZero needs a number".into())), }, - ("isUnit", [v]) => match v.as_f64() { - Some(f) => Ok(Value::Boolean(f == 1.0)), + ("isUnit", [v]) => match v.num() { + Some(n) => Ok(Value::Boolean(n.is_one())), None => Err(EvalError::Type("isUnit needs a number".into())), }, ("log", [v]) => match v.as_f64() { - Some(f) if f > 0.0 => Ok(Value::Rational(f.log10())), + Some(f) if f > 0.0 => Ok(Value::Real(f.log10())), Some(_) => Err(EvalError::Type("log of a non-positive number".into())), None => Err(EvalError::Type("log needs a number".into())), }, - ("floor", [v]) => match v.as_f64() { - Some(f) => Ok(Value::Integer(f.floor() as i128)), - None => Err(EvalError::Type("floor needs a number".into())), + ("floor", [v]) => match v.num().and_then(|n| n.floor()) { + Some(n) => Ok(Value::from_num(n)), + None => Err(EvalError::Type("floor needs a finite number".into())), }, - ("round", [v]) => match v.as_f64() { - Some(f) => Ok(Value::Integer(f.round() as i128)), - None => Err(EvalError::Type("round needs a number".into())), + ("round", [v]) => match v.num().and_then(|n| n.round()) { + Some(n) => Ok(Value::from_num(n)), + None => Err(EvalError::Type("round needs a finite number".into())), }, ("ToString", [v]) => Ok(Value::String(match v { Value::String(s) => s.clone(), @@ -3142,11 +3903,13 @@ impl Evaluator<'_> { .parse::() .map(Value::Integer) .map_err(|_| EvalError::Type(format!("cannot parse `{s}` as Integer"))), - ("ToReal", [Value::String(s)]) => s - .trim() - .parse::() - .map(Value::Rational) - .map_err(|_| EvalError::Type(format!("cannot parse `{s}` as Real"))), + // A decimal or fraction spelling converts exactly, so + // `ToString` output reads back; anything else the double + // parser accepts (`inf`) is approximate. + ("ToReal", [Value::String(s)]) => Rational::parse(s) + .map(|r| Value::from_num(Num::Exact(r))) + .or_else(|| s.trim().parse::().ok().map(Value::Real)) + .ok_or_else(|| EvalError::Type(format!("cannot parse `{s}` as Real"))), ("Length", [Value::String(s)]) => Ok(Value::Integer(s.chars().count() as i128)), ("Substring", [Value::String(s), Value::Integer(lo), Value::Integer(hi)]) => { // KerML string indexing is 1-based and inclusive. @@ -3169,10 +3932,12 @@ impl Evaluator<'_> { /// Scale a scalar or vector quantity magnitude during same-dimension unit /// conversion. Components that already carry their own unit are coordinates /// with an explicit measurement reference and remain verbatim. -fn scale_magnitude(v: Value, factor: f64) -> Result { +fn scale_magnitude(v: Value, factor: &Rational) -> Result { match v { - Value::Integer(i) => Ok(Value::Rational(i as f64 * factor)), - Value::Rational(r) => Ok(Value::Rational(r * factor)), + Value::Integer(_) | Value::Rational(_) | Value::Real(_) => { + let n = v.num().expect("numeric arm"); + Ok(Value::from_num(n.scale(factor))) + } Value::Sequence(items) => items .into_iter() .map(|v| match v { @@ -3181,7 +3946,9 @@ fn scale_magnitude(v: Value, factor: f64) -> Result { }) .collect::, _>>() .map(Value::Sequence), - Value::Unbound(_) | Value::Indeterminate => Ok(Value::Indeterminate), + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => { + Ok(Value::Indeterminate) + } other => Err(EvalError::Type(format!( "a quantity needs a numeric magnitude, got {other}" ))), @@ -3189,14 +3956,28 @@ fn scale_magnitude(v: Value, factor: f64) -> Result { } fn is_zero(v: &Value) -> bool { - matches!(v, Value::Integer(0)) || matches!(v, Value::Rational(r) if *r == 0.0) + v.num().is_some_and(|n| n.is_zero()) +} + +/// `numer`/`denom` of a number's reduced fraction. +fn rational_part(v: &Value, numer: bool) -> Result { + let name = if numer { "numer" } else { "denom" }; + let Some(n) = v.num() else { + return Err(EvalError::Type(format!("{name} needs a number"))); + }; + let Some(r) = n.exact() else { + return Err(EvalError::Type(format!("{name} needs a finite number"))); + }; + let (num, den) = r.to_string_parts(); + let part = Rational::parse_decimal(if numer { &num } else { &den }).expect("decimal digits"); + Ok(Value::from_num(Num::Exact(part))) } /// Whether equality involving this value is undecidable because some part is /// an unbound or indeterminate value. fn value_is_unknown(v: &Value) -> bool { match v { - Value::Unbound(_) | Value::Indeterminate => true, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate => true, Value::Quantity(n, _) => value_is_unknown(n), Value::Instance { fields, .. } => fields.iter().any(|(_, v)| value_is_unknown(v)), Value::Sequence(items) => items.iter().any(value_is_unknown), @@ -3206,15 +3987,19 @@ fn value_is_unknown(v: &Value) -> bool { fn value_eq(a: &Value, b: &Value) -> bool { match (a, b) { - (Value::Integer(i), Value::Rational(r)) | (Value::Rational(r), Value::Integer(i)) => { - *i as f64 == *r - } + ( + Value::Integer(_) | Value::Rational(_) | Value::Real(_), + Value::Integer(_) | Value::Rational(_) | Value::Real(_), + ) => match (a.num(), b.num()) { + (Some(x), Some(y)) => x.eq(&y), + _ => false, + }, (Value::Quantity(x, u), Value::Quantity(y, v)) => { if u == v { value_eq(x, y) } else if same_dims(u, v) { - match (x.as_f64(), y.as_f64()) { - (Some(a), Some(b)) => a * u.scale == b * v.scale, + match (x.num(), y.num()) { + (Some(a), Some(b)) => a.scale(&u.scale).eq(&b.scale(&v.scale)), _ => false, } } else { @@ -3248,9 +4033,10 @@ fn compare(a: &Value, b: &Value) -> Result { compare(x, y) } else if same_dims(u, v) { // Convertible: compare reference magnitudes. - match (x.as_f64(), y.as_f64()) { - (Some(a), Some(b)) => (a * u.scale) - .partial_cmp(&(b * v.scale)) + match (x.num(), y.num()) { + (Some(a), Some(b)) => a + .scale(&u.scale) + .cmp(&b.scale(&v.scale)) .ok_or_else(|| EvalError::Type("NaN comparison".into())), _ => Err(EvalError::Type("numeric operands required".into())), } @@ -3264,9 +4050,9 @@ fn compare(a: &Value, b: &Value) -> Result { (Value::Quantity(..), _) | (_, Value::Quantity(..)) => Err(EvalError::Type( "cannot compare a quantity with a plain value".into(), )), - _ => match (a.as_f64(), b.as_f64()) { + _ => match (a.num(), b.num()) { (Some(x), Some(y)) => x - .partial_cmp(&y) + .cmp(&y) .ok_or_else(|| EvalError::Type("NaN comparison".into())), _ => Err(EvalError::Type(format!("cannot compare {a} and {b}"))), }, @@ -3284,12 +4070,22 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { let (l, r) = (unwrap(l), unwrap(r)); // An unknown operand makes the result unknown (see `binary` — folds // like `sum`/`product` reach arithmetic through here directly). - if matches!(l, Value::Unbound(_) | Value::Indeterminate) - || matches!(r, Value::Unbound(_) | Value::Indeterminate) - { + if matches!( + l, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) || matches!( + r, + Value::Unbound(_) | Value::UnboundMember(_) | Value::Indeterminate + ) { return Ok(Value::Indeterminate); } if let (Add, Value::String(a), Value::String(b)) = (op, &l, &r) { + if a.len() + b.len() > MAX_STRING { + return Err(EvalError::Budget(format!( + "string of {} bytes exceeds the {MAX_STRING}-byte limit", + a.len() + b.len() + ))); + } return Ok(Value::String(format!("{a}{b}"))); } // Quantities: same-dimension additive ops (converting across scales @@ -3298,13 +4094,13 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { // scales into the number and take the reference spelling, so the // printed magnitude is always true to the printed unit; dimensions // that cancel completely leave a plain number. - let quantity_or_plain = |n: Value, dims: Vec, scale: f64| { + let quantity_or_plain = |n: Value, dims: Vec, scale: Rational| { let unit = Unit::from_dims(dims); - let n = if scale == 1.0 { + let n = if scale.is_one() { n } else { - match n.as_f64() { - Some(f) => Value::Rational(f * scale), + match n.num() { + Some(f) => Value::from_num(f.scale(&scale)), None => return Err(EvalError::Type("numeric operands required".into())), } }; @@ -3321,12 +4117,16 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { Ok(Value::Quantity(Box::new(n), u.clone())) } else if same_dims(u, v) { // Convert the right operand into the left's unit. - let (Some(a), Some(b)) = (a.as_f64(), b.as_f64()) else { + let (Some(a), Some(b)) = (a.num(), b.num()) else { return Err(EvalError::Type("numeric operands required".into())); }; - let b = b * (v.scale / u.scale); - let n = if matches!(op, Add) { a + b } else { a - b }; - Ok(Value::Quantity(Box::new(Value::Rational(n)), u.clone())) + let b = b.scale(&scale_ratio(&v.scale, &u.scale)); + let n = if matches!(op, Add) { + a.add(&b) + } else { + a.sub(&b) + }; + Ok(Value::Quantity(Box::new(bounded(n)?), u.clone())) } else { Err(EvalError::Type(format!( "cannot combine quantities in `{}` and `{}`", @@ -3336,32 +4136,44 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { } (Mul, Value::Quantity(a, u), Value::Quantity(b, v)) => { let n = arith(Mul, (**a).clone(), (**b).clone())?; - return quantity_or_plain(n, dims_combine(&u.dims, &v.dims, 1), u.scale * v.scale); + return quantity_or_plain(n, dims_combine(&u.dims, &v.dims, 1), u.scale.mul(&v.scale)); } (Div, Value::Quantity(a, u), Value::Quantity(b, v)) => { let n = arith(Div, (**a).clone(), (**b).clone())?; - return quantity_or_plain(n, dims_combine(&u.dims, &v.dims, -1), u.scale / v.scale); + return quantity_or_plain( + n, + dims_combine(&u.dims, &v.dims, -1), + scale_ratio(&u.scale, &v.scale), + ); } (Mul, Value::Quantity(a, u), s) | (Mul, s, Value::Quantity(a, u)) - if matches!(s, Value::Integer(_) | Value::Rational(_)) => + if matches!(s, Value::Integer(_) | Value::Rational(_) | Value::Real(_)) => { let n = arith(Mul, (**a).clone(), s.clone())?; return Ok(Value::Quantity(Box::new(n), u.clone())); } - (Div, Value::Quantity(a, u), s) if matches!(s, Value::Integer(_) | Value::Rational(_)) => { + (Div, Value::Quantity(a, u), s) + if matches!(s, Value::Integer(_) | Value::Rational(_) | Value::Real(_)) => + { let n = arith(Div, (**a).clone(), s.clone())?; return Ok(Value::Quantity(Box::new(n), u.clone())); } // A scalar over a quantity is a reciprocal-unit quantity // (`2/r_leo`, failure rates in `1/h`). - (Div, s, Value::Quantity(a, u)) if matches!(s, Value::Integer(_) | Value::Rational(_)) => { + (Div, s, Value::Quantity(a, u)) + if matches!(s, Value::Integer(_) | Value::Rational(_) | Value::Real(_)) => + { let n = arith(Div, s.clone(), (**a).clone())?; - return quantity_or_plain(n, dims_pow(&u.dims, (-1, 1)), 1.0 / u.scale); + return quantity_or_plain( + n, + dims_pow(&u.dims, (-1, 1)), + scale_ratio(&Rational::one(), &u.scale), + ); } // A quantity raised to a numeric power scales its exponents // (`x^2`, and after rational division `x^(1/2)` is a root). (Pow | Caret, Value::Quantity(a, u), s) - if matches!(s, Value::Integer(_) | Value::Rational(_)) => + if matches!(s, Value::Integer(_) | Value::Rational(_) | Value::Real(_)) => { let Some(exp) = small_ratio(s) else { return Err(EvalError::Unsupported( @@ -3369,7 +4181,7 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { )); }; let n = arith(op, (**a).clone(), s.clone())?; - let scale = u.scale.powf(exp.0 as f64 / exp.1 as f64); + let scale = u.scale.pow_ratio_or_approx(exp); return quantity_or_plain(n, dims_pow(&u.dims, exp), scale); } // A plain *zero* is the additive identity of every dimension @@ -3389,56 +4201,40 @@ fn arith(op: BinaryOp, l: Value, r: Value) -> Result { } _ => {} } - match (&l, &r) { - (Value::Integer(a), Value::Integer(b)) => { - let (a, b) = (*a, *b); - Ok(match op { - Add => Value::Integer(a.wrapping_add(b)), - Sub => Value::Integer(a.wrapping_sub(b)), - Mul => Value::Integer(a.wrapping_mul(b)), - Div => { - if b == 0 { - return Err(EvalError::DivisionByZero); - } - // KFL `IntegerFunctions::'/'` returns Rational — true - // division, not truncation (`7/2 = 3.5`, `x^(1/2)` is a - // square root). - Value::Rational(a as f64 / b as f64) - } - Rem => { - if b == 0 { - return Err(EvalError::DivisionByZero); - } - Value::Integer(a % b) - } - Pow | Caret => match u32::try_from(b) { - Ok(e) => Value::Integer(a.wrapping_pow(e)), - Err(_) => Value::Rational((a as f64).powf(b as f64)), - }, - _ => unreachable!(), - }) - } - _ => { - let (a, b) = match (l.as_f64(), r.as_f64()) { - (Some(a), Some(b)) => (a, b), - _ => return Err(EvalError::Type("numeric operands required".into())), - }; - Ok(Value::Rational(match op { - Add => a + b, - Sub => a - b, - Mul => a * b, - Div => { - if b == 0.0 { - return Err(EvalError::DivisionByZero); - } - a / b - } - Rem => a % b, - Pow | Caret => a.powf(b), - _ => unreachable!(), - })) + // Plain numbers: exact unless an operand is an approximate double. + // KFL `IntegerFunctions::'/'` returns Rational — true division, not + // truncation (`7/2` is `3.5`, `x^(1/2)` is a square root); integer + // results that outgrow `i128` promote to exact big rationals instead + // of wrapping. + let (Some(a), Some(b)) = (l.num(), r.num()) else { + return Err(EvalError::Type("numeric operands required".into())); + }; + bounded(match op { + Add => a.add(&b), + Sub => a.sub(&b), + Mul => a.mul(&b), + Div => a.div(&b)?, + Rem => a.rem(&b)?, + Pow | Caret => a.pow(&b), + _ => unreachable!(), + }) +} + +/// An arithmetic result as a value, refused past +/// [`crate::rational::MAX_BITS`]: exact integers no longer wrap, so a fold +/// such as `product(1..1000000)` would otherwise grow without bound one +/// multiplication at a time, each a single step. +fn bounded(n: Num) -> Result { + if let Num::Exact(r) = &n { + let bits = r.bits(); + if bits > crate::rational::MAX_BITS { + return Err(EvalError::Budget(format!( + "a number of {bits} bits exceeds the {}-bit limit", + crate::rational::MAX_BITS + ))); } } + Ok(Value::from_num(n)) } fn extremum(items: Vec, want_max: bool) -> Result { @@ -3456,11 +4252,94 @@ fn extremum(items: Vec, want_max: bool) -> Result { } }); } - Ok(best.unwrap_or(Value::null())) + Ok(best.unwrap_or_else(Value::null)) } +/// A transcendental function: always an approximate double. fn num1(v: &Value, f: fn(f64) -> f64) -> Result { v.as_f64() - .map(|x| Value::Rational(f(x))) + .map(|x| Value::Real(f(x))) .ok_or_else(|| EvalError::Type("numeric argument required".into())) } + +pub(crate) fn prepare_unit(b: &mut Builder, elem: usize) { + let scope = b.owner_scope_of(elem).unwrap_or(0); + let names: Vec<_> = ["declaredName", "declaredShortName"] + .into_iter() + .filter_map(|key| b.elements[elem].props.get(key)?.as_str().map(str::to_owned)) + .collect(); + let mut evaluator = Evaluator { + b, + env: Vec::new(), + in_progress: HashSet::new(), + overrides: HashMap::new(), + unbound_receiver: None, + lib_frames: 0, + call_depth: 0, + steps: 0, + allocated: 0, + query: false, + }; + for name in names { + evaluator.expanded_unit(scope, elem, name, 0); + } +} + +#[cfg(test)] +mod memo_tests { + use super::*; + #[test] + fn unit_memo_replays_imports_and_bypasses_bound_or_recursive_contexts() { + let mut model = crate::model::Model::new(); + model.add_source("units.sysml", "package B { attribute m; attribute s; } package U { private import B::*; attribute <'m/s'> speed; }"); + let mut r = ResolvedModel::build(&model); + let elem = r.resolve_qualified("U::speed").unwrap().0; + let scope = r.b.owner_scope_of(elem).unwrap(); + let mut ev = Evaluator { + b: &mut r.b, + env: Vec::new(), + in_progress: HashSet::new(), + overrides: HashMap::new(), + unbound_receiver: None, + lib_frames: 0, + call_depth: 0, + steps: 0, + allocated: 0, + query: false, + }; + ev.b.used_imports.clear(); + // A recursion cutoff must never poison a later complete reduction. + let shallow = ev.expanded_unit(scope, elem, "m/s".into(), 8); + assert_eq!(ev.b.semantic_memo.units.iter().count(), 0); + let full = ev.expanded_unit(scope, elem, "m/s".into(), 0); + assert_ne!(shallow, full); + let imports = ev.b.used_imports.clone(); + assert!( + !imports.is_empty(), + "spelled components use the wildcard import" + ); + // Recompute while the imports are already marked, then replay into an + // empty evidence set: recording only a set difference would lose them. + ev.b.semantic_memo.units = Default::default(); + assert_eq!(ev.expanded_unit(scope, elem, "m/s".into(), 0), full); + ev.b.used_imports.clear(); + assert_eq!(ev.expanded_unit(scope, elem, "m/s".into(), 0), full); + assert_eq!(ev.b.used_imports, imports); + ev.b.semantic_memo.units = Default::default(); + ev.overrides.insert(elem, Value::Integer(3)); + ev.expanded_unit(scope, elem, "m/s".into(), 0); + ev.overrides.clear(); + ev.in_progress.insert((scope, elem)); + ev.expanded_unit(scope, elem, "m/s".into(), 0); + ev.in_progress.clear(); + ev.query = true; + ev.expanded_unit(scope, elem, "m/s".into(), 0); + ev.query = false; + ev.call_depth = 1; + ev.expanded_unit(scope, elem, "m/s".into(), 0); + ev.call_depth = 0; + ev.env.push(("x".into(), Value::Integer(1))); + ev.expanded_unit(scope, elem, "m/s".into(), 0); + assert_eq!(ev.b.semantic_memo.units.iter().count(), 0); + } +} diff --git a/crates/sysmlv2-model/src/flat.rs b/crates/sysmlv2-model/src/flat.rs new file mode 100644 index 0000000..609949d --- /dev/null +++ b/crates/sysmlv2-model/src/flat.rs @@ -0,0 +1,208 @@ +//! Immutable rows over shared contiguous storage, with row-local copy-on-write. +//! Snapshot tables decode their values in bulk; no pointer fixups or unsafe +//! ownership tricks are needed, and changing one row cannot affect a neighbour. +mod rows; +pub(crate) use rows::Rows; + +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{ops::Deref, sync::Arc}; + +#[derive(Clone, Debug)] +pub(crate) enum Row { + Owned(Vec), + Shared { + values: Arc>, + start: usize, + end: usize, + }, +} +impl Default for Row { + fn default() -> Self { + Self::Owned(Vec::new()) + } +} +impl From> for Row { + fn from(v: Vec) -> Self { + Self::Owned(v) + } +} +impl Deref for Row { + type Target = [T]; + fn deref(&self) -> &[T] { + match self { + Self::Owned(v) => v, + Self::Shared { values, start, end } => &values[*start..*end], + } + } +} +impl Row { + pub fn make_mut(&mut self) -> &mut Vec { + if matches!(self, Self::Shared { .. }) { + *self = Self::Owned(self.to_vec()); + } + match self { + Self::Owned(v) => v, + _ => unreachable!(), + } + } + pub fn push(&mut self, v: T) { + self.make_mut().push(v); + } +} +impl<'a, T> IntoIterator for &'a Row { + type Item = &'a T; + type IntoIter = std::slice::Iter<'a, T>; + fn into_iter(self) -> Self::IntoIter { + self.iter() + } +} +impl IntoIterator for Row { + type Item = T; + type IntoIter = std::vec::IntoIter; + fn into_iter(self) -> Self::IntoIter { + match self { + Self::Owned(v) => v, + other => other.to_vec(), + } + .into_iter() + } +} +impl FromIterator for Row { + fn from_iter>(iter: I) -> Self { + Self::Owned(iter.into_iter().collect()) + } +} +impl PartialEq for Row { + fn eq(&self, rhs: &Self) -> bool { + **self == **rhs + } +} +impl Serialize for Row { + fn serialize(&self, s: S) -> Result { + self.deref().serialize(s) + } +} +impl<'de, T: Deserialize<'de>> Deserialize<'de> for Row { + fn deserialize>(d: D) -> Result { + Vec::deserialize(d).map(Self::Owned) + } +} + +/// Two contiguous vectors: row lengths and values. Checked prefix sums form +/// offsets with exact coverage of the values vector before rows are exposed. +pub(crate) mod table { + use super::*; + #[cfg(test)] + pub fn serialize( + rows: &[Row], + s: S, + ) -> Result { + Slices(rows.iter().map(|r| &**r).collect()).serialize(s) + } + pub fn deserialize<'de, T: Deserialize<'de>, D: Deserializer<'de>>( + d: D, + ) -> Result>, D::Error> { + let (lengths, values): (Vec, Vec) = Deserialize::deserialize(d)?; + let mut offsets = Vec::with_capacity(lengths.len() + 1); + offsets.push(0usize); + for length in lengths { + let end = offsets + .last() + .unwrap() + .checked_add(length) + .ok_or_else(|| serde::de::Error::custom("flat row length overflow"))?; + if end > values.len() { + return Err(serde::de::Error::custom("flat row outside values")); + } + offsets.push(end); + } + if offsets.first() != Some(&0) + || offsets.last() != Some(&values.len()) + || offsets.windows(2).any(|r| r[0] > r[1]) + { + return Err(serde::de::Error::custom("invalid flat row offsets")); + } + let values = Arc::new(values); + Ok(offsets + .windows(2) + .map(|r| { + if r[0] == r[1] { + Row::default() + } else { + Row::Shared { + values: values.clone(), + start: r[0], + end: r[1], + } + } + }) + .collect()) + } +} + +/// A serialization-only view; values are borrowed without cloning the graph. +pub(crate) struct Slices<'a, T>(pub Vec<&'a [T]>); +impl Serialize for Slices<'_, T> { + fn serialize(&self, s: S) -> Result { + use serde::ser::{SerializeSeq, SerializeTuple}; + let lengths: Vec<_> = self.0.iter().map(|r| r.len()).collect(); + let count = lengths + .iter() + .try_fold(0usize, |n, &length| n.checked_add(length)) + .ok_or_else(|| serde::ser::Error::custom("flat table length overflow"))?; + struct Values<'a, T>(&'a [&'a [T]], usize); + impl Serialize for Values<'_, T> { + fn serialize(&self, s: S) -> Result { + let mut seq = s.serialize_seq(Some(self.1))?; + for value in self.0.iter().flat_map(|r| r.iter()) { + seq.serialize_element(value)?; + } + seq.end() + } + } + let mut tuple = s.serialize_tuple(2)?; + tuple.serialize_element(&lengths)?; + tuple.serialize_element(&Values(&self.0, count))?; + tuple.end() + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::cache_codec; + #[derive(Serialize, Deserialize)] + struct Table(#[serde(with = "table")] Vec>); + #[test] + fn decoded_rows_share_storage_and_mutations_are_isolated() { + let original = Table(vec![vec![1, 2].into(), vec![3].into(), Row::default()]); + let bytes = cache_codec::encode(&original).unwrap(); + let mut decoded: Table = cache_codec::decode(&bytes).unwrap(); + let (Row::Shared { values: a, .. }, Row::Shared { values: b, .. }) = + (&decoded.0[0], &decoded.0[1]) + else { + panic!("rows must decode in bulk") + }; + assert!(Arc::ptr_eq(a, b)); + let retained = decoded.0[0].clone(); + decoded.0[0].make_mut()[0] = 9; + decoded.0[1].push(4); + assert_eq!(&*retained, &[1, 2]); + assert_eq!(&*decoded.0[0], &[9, 2]); + assert_eq!(&*decoded.0[1], &[3, 4]); + assert!(decoded.0[2].is_empty()); + for cut in 0..bytes.len() { + assert!(cache_codec::decode::
(&bytes[..cut]).is_err()); + } + } + #[test] + fn invalid_offsets_cannot_create_out_of_bounds_rows() { + for offsets in [vec![], vec![1], vec![3], vec![1, 2], vec![usize::MAX, 2]] { + let bytes = cache_codec::encode(&((offsets, vec![1u32, 2]),)).unwrap(); + assert!(cache_codec::decode::
(&bytes).is_err()); + } + let empty = Table(Vec::new()); + let restored: Table = cache_codec::decode(&cache_codec::encode(&empty).unwrap()).unwrap(); + assert!(restored.0.is_empty()); + } +} diff --git a/crates/sysmlv2-model/src/flat/rows.rs b/crates/sysmlv2-model/src/flat/rows.rs new file mode 100644 index 0000000..e012560 --- /dev/null +++ b/crates/sysmlv2-model/src/flat/rows.rs @@ -0,0 +1,205 @@ +//! Checked adjacency rows over one shared offsets/value table. Only private +//! edits allocate rows; replay does not reconstruct a handle for every row. +use super::Slices; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{ops::Index, sync::Arc}; + +#[derive(Clone)] +pub(crate) struct Rows { + base: Arc>, + // Box the few edited row headers to keep the dense directory one pointer + // per library row, rather than three words per row for an inline Vec. + #[allow(clippy::box_collection)] + edits: Vec>>>, + tail: Vec>, +} +struct Table { + offsets: Vec, + values: Vec, +} +impl Default for Rows { + fn default() -> Self { + Self { + base: Arc::new(Table { + offsets: vec![0], + values: Vec::new(), + }), + edits: Vec::new(), + tail: Vec::new(), + } + } +} +impl Rows { + fn base_len(&self) -> usize { + self.base.offsets.len() - 1 + } + pub fn len(&self) -> usize { + self.base_len() + self.tail.len() + } + pub fn iter(&self) -> impl Iterator { + self.base + .offsets + .windows(2) + .enumerate() + .map(|(i, range)| { + self.edits + .get(i) + .and_then(Option::as_deref) + .map(Vec::as_slice) + .unwrap_or_else(|| &self.base.values[range[0]..range[1]]) + }) + .chain(self.tail.iter().map(Vec::as_slice)) + } + pub fn push(&mut self, row: Vec) { + self.tail.push(row); + } + pub fn resize(&mut self, len: usize) { + assert!(len >= self.len(), "adjacency rows only grow"); + self.tail.resize_with(len - self.base_len(), Vec::new); + } + pub fn set(&mut self, i: usize, row: Vec) { + if i < self.base_len() { + if self.edits.is_empty() { + self.edits.resize_with(self.base_len(), || None); + } + self.edits[i] = Some(Box::new(row)); + } else { + let j = i - self.base_len(); + self.tail[j] = row; + } + } +} +impl Rows { + pub fn row_mut(&mut self, i: usize) -> &mut Vec { + if i < self.base_len() { + if self.edits.is_empty() { + self.edits.resize_with(self.base_len(), || None); + } + self.edits[i].get_or_insert_with(|| { + Box::new(self.base.values[self.base.offsets[i]..self.base.offsets[i + 1]].to_vec()) + }) + } else { + let j = i - self.base_len(); + &mut self.tail[j] + } + } + pub fn freeze(&mut self) { + if self.edits.is_empty() && self.tail.is_empty() { + return; + } + let mut offsets = Vec::with_capacity(self.len() + 1); + let mut values = Vec::new(); + offsets.push(0); + for row in self.iter() { + values.extend_from_slice(row); + offsets.push(values.len()); + } + self.base = Arc::new(Table { offsets, values }); + self.edits = Vec::new(); + self.tail = Vec::new(); + } +} +impl Index for Rows { + type Output = [T]; + fn index(&self, i: usize) -> &[T] { + if i >= self.base_len() { + return &self.tail[i - self.base_len()]; + } + if let Some(row) = self.edits.get(i).and_then(Option::as_deref) { + return row; + } + &self.base.values[self.base.offsets[i]..self.base.offsets[i + 1]] + } +} +impl Serialize for Rows { + fn serialize(&self, s: S) -> Result { + Slices(self.iter().collect()).serialize(s) + } +} +impl<'de, T: Deserialize<'de>> Deserialize<'de> for Rows { + fn deserialize>(d: D) -> Result { + let (lengths, values): (Vec, Vec) = Deserialize::deserialize(d)?; + let mut offsets = Vec::with_capacity(lengths.len() + 1); + offsets.push(0usize); + for length in lengths { + let end = offsets + .last() + .unwrap() + .checked_add(length) + .ok_or_else(|| serde::de::Error::custom("adjacency row length overflow"))?; + if end > values.len() { + return Err(serde::de::Error::custom("adjacency row outside values")); + } + offsets.push(end); + } + if offsets.last() != Some(&values.len()) { + return Err(serde::de::Error::custom("unused adjacency values")); + } + Ok(Self { + base: Arc::new(Table { offsets, values }), + edits: Vec::new(), + tail: Vec::new(), + }) + } +} +#[cfg(test)] +mod tests { + use super::*; + use crate::cache_codec; + #[test] + fn replay_edits_and_refreeze_preserve_order_and_isolation() { + let mut rows = Rows::default(); + rows.push(vec![1u32, 2]); + rows.push(vec![]); + rows.push(vec![3]); + let bytes = cache_codec::encode(&rows).unwrap(); + let mut replay: Rows = cache_codec::decode(&bytes).unwrap(); + assert!(replay.tail.is_empty()); + assert!(replay.edits.is_empty()); + let retained = replay.clone(); + assert!(Arc::ptr_eq(&replay.base, &retained.base)); + replay.row_mut(0).push(4); + replay.set(1, vec![5]); + replay.resize(5); + replay.row_mut(3).push(6); + replay.set(4, vec![7]); + let expected = vec![vec![1, 2, 4], vec![5], vec![3], vec![6], vec![7]]; + assert_eq!( + replay.iter().map(<[_]>::to_vec).collect::>(), + expected + ); + assert_eq!(&retained[0], &[1, 2]); + assert!(retained[1].is_empty()); + let edited: Rows = + cache_codec::decode(&cache_codec::encode(&replay).unwrap()).unwrap(); + replay.freeze(); + assert_eq!( + replay.iter().collect::>(), + edited.iter().collect::>() + ); + assert!(replay.tail.is_empty()); + assert!(replay.edits.is_empty()); + let base = replay.base.clone(); + replay.freeze(); + assert!(Arc::ptr_eq(&base, &replay.base)); + for cut in 0..bytes.len() { + assert!(cache_codec::decode::>(&bytes[..cut]).is_err()); + } + } + #[test] + fn malformed_lengths_reject_overflow_gaps_and_out_of_bounds() { + for lengths in [vec![], vec![1], vec![3], vec![1, 2], vec![1, usize::MAX]] { + let bytes = cache_codec::encode(&(lengths, vec![1u32, 2])).unwrap(); + assert!(cache_codec::decode::>(&bytes).is_err()); + } + let rows: Rows = cache_codec::decode( + &cache_codec::encode(&(vec![0usize; 3], Vec::::new())).unwrap(), + ) + .unwrap(); + assert_eq!(rows.len(), 3); + assert!(rows.iter().all(<[_]>::is_empty)); + let empty: Rows = + cache_codec::decode(&cache_codec::encode(&Rows::::default()).unwrap()).unwrap(); + assert_eq!(empty.len(), 0); + } +} diff --git a/crates/sysmlv2-model/src/full.rs b/crates/sysmlv2-model/src/full.rs index 4392f24..71de1ee 100644 --- a/crates/sysmlv2-model/src/full.rs +++ b/crates/sysmlv2-model/src/full.rs @@ -13,10 +13,10 @@ //! "passthrough" conformance level of the Systems Modeling API — and are //! called out in the README. -use crate::json::{ - implicit_def_bases, implicit_usage_bases, model_to_compact_json, to_compact_json, -}; -use crate::lift::{def_kind_of, usage_kind_of}; +use crate::json::model_to_compact_json; +use crate::json::{CLOSURE_NAMES, ClosurePolicy}; +use crate::lift::usage_kind_of; +use crate::metaclass::conforms; use crate::model::Model; use crate::schema_props::METACLASS_PROPS; use serde_json::{Map, Value, json}; @@ -27,10 +27,11 @@ use uuid::Uuid; /// How full-form interchange handles compact `{"@ref": ...}` values. The /// published full schema permits only `@id` references, so preserving a /// partial model requires schema-valid textual recovery annotations. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] pub enum UnresolvedReferencePolicy { /// Emit deterministic recovery annotations. This is the default and is /// lossless when lifted by this toolkit. + #[default] Preserve, /// Refuse full-form emission when any unresolved reference remains. Reject, @@ -57,8 +58,61 @@ impl std::fmt::Display for UnresolvedReferenceError { impl std::error::Error for UnresolvedReferenceError {} +/// How a full-form emission answers the inheritance-aware properties and +/// the unresolved references. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub struct EmissionPolicy { + pub unresolved: UnresolvedReferencePolicy, + /// [`ClosurePolicy::Passthrough`] (the default) writes the owned side + /// of the inheritance-aware properties and the type-correct empty + /// value for the four closure names — the payload stays proportional + /// to the model; [`ClosurePolicy::Closure`] writes the specification's + /// values, the closures materialized per element. + pub closures: ClosurePolicy, +} + +/// Why a full-form emission was refused. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum EmissionError { + /// The [`UnresolvedReferencePolicy::Reject`] policy met unresolved + /// references. + UnresolvedReferences(UnresolvedReferenceError), + /// Under [`ClosurePolicy::Closure`], the inheritance or import walk of + /// these elements (by interchange id) hit the resolver's depth budget: + /// their closures would be incomplete, and a cut enumeration is not + /// written as the closure. + TruncatedClosures { elements: Vec }, +} + +impl std::fmt::Display for EmissionError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnresolvedReferences(e) => e.fmt(f), + Self::TruncatedClosures { elements } => write!( + f, + "the inheritance walk of {} element(s) exceeded the depth budget, so their closures cannot be written: {}", + elements.len(), + elements.join(", ") + ), + } + } +} + +impl std::error::Error for EmissionError {} + +impl From for EmissionError { + fn from(e: UnresolvedReferenceError) -> Self { + Self::UnresolvedReferences(e) + } +} + /// Serialize a model to the full interchange form. Library units provide /// the implied-relationship targets (normative IDs) and are not emitted. +/// +/// # Panics +/// +/// Never in practice: this spelling preserves unresolved references, the +/// one policy that cannot reject a model. pub fn model_to_full_json(model: &Model) -> Value { model_to_full_json_with_policy(model, UnresolvedReferencePolicy::Preserve) .expect("the preserve policy cannot reject") @@ -72,6 +126,11 @@ pub fn model_to_full_json(model: &Model) -> Value { /// spelling) owned by its document's root namespace. Foreign tools see /// ordinary annotations; this toolkit's lift restores the references, so /// *partial models round-trip losslessly through the full form*. +/// +/// # Panics +/// +/// Never in practice: both spellings of `recover_refs` select a policy +/// that cannot reject a model. pub fn model_to_full_json_with(model: &Model, recover_refs: bool) -> Value { model_to_full_json_with_policy( model, @@ -88,6 +147,52 @@ pub fn model_to_full_json_with_policy( model: &Model, policy: UnresolvedReferencePolicy, ) -> Result { + let mut resolved = crate::json::ResolvedModel::build(model); + resolved_to_full_json_with_policy(&mut resolved, model, policy) +} + +/// [`model_to_full_json_with_policy`] over an already resolved model: +/// the derived properties the derivation layer computes +/// ([`crate::json::computed_names`]) are projected from it, the rest +/// from the compact element array. The ids of `resolved` must agree +/// with `model`'s compact emission (a resolved model carrying an +/// explicit-id overlay does not): elements the projection cannot find +/// by id keep the array-level derivations. +pub fn resolved_to_full_json_with_policy( + resolved: &mut crate::json::ResolvedModel, + model: &Model, + policy: UnresolvedReferencePolicy, +) -> Result { + match resolved_to_full_json( + resolved, + model, + EmissionPolicy { + unresolved: policy, + closures: ClosurePolicy::Passthrough, + }, + ) { + Ok(v) => Ok(v), + Err(EmissionError::UnresolvedReferences(e)) => Err(e), + Err(EmissionError::TruncatedClosures { .. }) => { + unreachable!("no closure is written at the passthrough level") + } + } +} + +/// [`resolved_to_full_json_with_policy`] with a full [`EmissionPolicy`]: +/// under [`ClosurePolicy::Closure`] the inheritance-aware properties carry +/// their specification values over the inherited and imported memberships +/// and the four closure names (`inheritedMembership`, `inheritedFeature`, +/// `importedMembership`, `featuringType`) are written; an element whose +/// walk hit the depth budget refuses the emission +/// ([`EmissionError::TruncatedClosures`]). The resolved model's closure +/// policy is set for the emission and restored after it. Both forms are +/// schema-valid and this toolkit reads either (INTEROP.md). +pub fn resolved_to_full_json( + resolved: &mut crate::json::ResolvedModel, + model: &Model, + policy: EmissionPolicy, +) -> Result { let compact = model_to_compact_json(model); // Elements only: membership ids share their member's qualified name and // must not win the name→id inversion (implied bases target elements). @@ -96,12 +201,36 @@ pub fn model_to_full_json_with_policy( for (id, segments) in &lib_names { by_name.insert(segments.join("::"), id.clone()); } - full_from_compact_policy(compact, &by_name, policy) + let previous = resolved.closure_policy(); + resolved.set_closure_policy(policy.closures); + let mut truncated: Vec = Vec::new(); + let result = full_from_compact_policy( + compact, + &by_name, + policy.unresolved, + Some(resolved), + policy.closures, + &mut truncated, + ); + resolved.set_closure_policy(previous); + let value = result?; + if truncated.is_empty() { + Ok(value) + } else { + Err(EmissionError::TruncatedClosures { + elements: truncated, + }) + } } /// Serialize a single unit to the full form. Without a library, implied /// relationships cannot be resolved and are omitted (`isImpliedIncluded` /// stays `false`); derived properties are still completed. +/// +/// # Panics +/// +/// Never in practice: this spelling preserves unresolved references, the +/// one policy that cannot reject a unit. pub fn to_full_json(unit: &SourceUnit) -> Value { to_full_json_with_policy(unit, UnresolvedReferencePolicy::Preserve) .expect("the preserve policy cannot reject") @@ -109,6 +238,11 @@ pub fn to_full_json(unit: &SourceUnit) -> Value { /// [`to_full_json`] with unresolved-reference recovery annotations — see /// [`model_to_full_json_with`]. +/// +/// # Panics +/// +/// Never in practice: both spellings of `recover_refs` select a policy +/// that cannot reject a unit. pub fn to_full_json_with(unit: &SourceUnit, recover_refs: bool) -> Value { to_full_json_with_policy( unit, @@ -125,7 +259,12 @@ pub fn to_full_json_with_policy( unit: &SourceUnit, policy: UnresolvedReferencePolicy, ) -> Result { - full_from_compact_policy(to_compact_json(unit), &HashMap::new(), policy) + // The unit's compact form completed in place: the ids are the ones + // the compact route derives (a one-unit *model* would seed its root + // from a unit name and shift every id), and the document is loaded + // through the model with those ids kept, so the derivation layer + // answers the full form as it does for any payload. + from_compact_value_with_policy(crate::json::to_compact_json(unit), &HashMap::new(), policy) } /// Language tag of the recovery annotations emitted by the @@ -146,7 +285,16 @@ pub fn from_compact_value( lib_by_name: &HashMap, recover_refs: bool, ) -> Value { - full_from_compact_with(compact, lib_by_name, recover_refs) + from_compact_value_with_policy( + compact, + lib_by_name, + if recover_refs { + UnresolvedReferencePolicy::Preserve + } else { + UnresolvedReferencePolicy::LegacyDanglingId + }, + ) + .expect("the boolean compatibility policies cannot reject") } pub fn from_compact_value_with_policy( @@ -154,9 +302,80 @@ pub fn from_compact_value_with_policy( lib_by_name: &HashMap, policy: UnresolvedReferencePolicy, ) -> Result { - full_from_compact_policy(compact, lib_by_name, policy) + if policy == UnresolvedReferencePolicy::Reject { + let mut references = Vec::new(); + unresolved_ref_spellings(&compact, &mut references); + references.sort(); + references.dedup(); + if !references.is_empty() { + return Err(UnresolvedReferenceError { references }); + } + } + // The payload path goes through the model: the document is loaded + // (ids kept as explicit ids) and the full form emitted from it, so + // there is one derivation implementation. The library is known by + // name only, as before: implied relationships target the named ids, + // and library references stay the ids the document spelled. + let names: HashMap> = lib_by_name + .iter() + .map(|(qn, id)| (id.clone(), qn.split("::").map(str::to_string).collect())) + .collect(); + // Keep the payload's owned graph intact. The loaded model supplies + // derived properties for the elements it represents; it is never the + // source of the emitted owned elements. In particular, an unsupported + // or over-budget subtree must not disappear during full-form export. + let loaded = crate::loader::load_document(&compact, &names); + let mut projection = loaded.ok().and_then(|(_, mut resolved, _, warnings)| { + // A normalized or incomplete model can carry relationships absent + // from the original payload. Do not project those phantom ids; + // derive directly from the original array when the loader warns. + warnings.is_empty().then(|| { + resolved.set_library_names(&names); + resolved + }) + }); + full_from_compact_policy( + compact, + lib_by_name, + policy, + projection.as_mut(), + ClosurePolicy::Passthrough, + &mut Vec::new(), + ) +} + +/// A derived value of the layer as the full form spells it. +fn derived_to_json(resolved: &crate::json::ResolvedModel, v: &crate::json::DerivedValue) -> Value { + use crate::json::DerivedValue as V; + let id = |e| id_ref(&resolved.element_id(e).to_string()); + match v { + V::Null => Value::Null, + V::Bool(b) => Value::Bool(*b), + V::Str(s) => Value::String(s.clone()), + V::Element(e) => id(*e), + V::Elements(es) => Value::Array(es.iter().map(|&e| id(e)).collect()), + V::Reference(r) => reference_to_json(resolved, r), + V::References(rs) => { + Value::Array(rs.iter().map(|r| reference_to_json(resolved, r)).collect()) + } + V::Strings(ss) => Value::Array(ss.iter().map(|s| Value::String(s.clone())).collect()), + } +} + +/// A reference of the layer as the full form spells it: an external id +/// as it is, an unresolved spelling as the same deterministic dangling +/// id `patch_refs` derives (the schema forbids `@ref`). +fn reference_to_json(resolved: &crate::json::ResolvedModel, r: &crate::json::Reference) -> Value { + use crate::json::Reference as R; + match r { + R::Element(e) => id_ref(&resolved.element_id(*e).to_string()), + R::External(id) => id_ref(&id.to_string()), + R::Unresolved(spelling) => id_ref(&dangling_id(spelling)), + } } +use crate::json::dangling_id; + fn id_ref(id: &str) -> Value { json!({ "@id": id }) } @@ -165,17 +384,47 @@ fn ty(el: &Map) -> &str { el.get("@type").and_then(|v| v.as_str()).unwrap_or("") } -fn eid(el: &Map) -> String { - el.get("@id") - .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string() +fn eid(el: &Map) -> &str { + el.get("@id").and_then(|v| v.as_str()).unwrap_or("") +} + +/// The schema's property list for a concrete metaclass. Both the +/// metaclass table and each property list are sorted by name (asserted in +/// this module's tests), so both lookups are searches over the static +/// tables — no per-export map, no per-element set. +fn metaclass_props(metaclass: &str) -> Option<&'static [(&'static str, u8)]> { + METACLASS_PROPS + .binary_search_by_key(&metaclass, |(name, _)| name) + .ok() + .map(|i| METACLASS_PROPS[i].1) } fn ref_of(v: &Value) -> Option { v.get("@id").and_then(|x| x.as_str()).map(|s| s.to_string()) } +/// The AnnotatingElement an Annotation owns (`ownedAnnotatingElement`): +/// spelled by the payload, or the first owned related element of that +/// kind. Present only in the prefix-annotation shape, where the Annotation +/// is owned by the element it annotates. +fn owned_annotating_element( + elements: &[Map], + related_elems: &[Vec], + index: &HashMap, + r: usize, +) -> Option { + elements[r] + .get("ownedAnnotatingElement") + .and_then(ref_of) + .and_then(|id| index.get(&id).copied()) + .or_else(|| { + related_elems[r] + .iter() + .copied() + .find(|&k| conforms(ty(&elements[k]), "AnnotatingElement")) + }) +} + fn is_membership(t: &str) -> bool { // FeatureValue and ElementFilterMembership are OwningMembership // subtypes in the metamodel. @@ -193,7 +442,11 @@ fn unresolved_ref_spellings(value: &Value, out: &mut Vec) { match value { Value::Object(object) => { if let Some(spelling) = object.get("@ref").and_then(Value::as_str) { - out.push(spelling.to_string()); + // An id-shaped spelling is a reference by id (kept as such + // on the wire), not an unresolved name. + if Uuid::parse_str(spelling.trim_matches('\'')).is_err() { + out.push(spelling.to_string()); + } } for value in object.values() { unresolved_ref_spellings(value, out); @@ -212,6 +465,9 @@ fn full_from_compact_policy( compact: Value, lib_by_name: &HashMap, policy: UnresolvedReferencePolicy, + projection: Option<&mut crate::json::ResolvedModel>, + closures: ClosurePolicy, + truncated: &mut Vec, ) -> Result { if policy == UnresolvedReferencePolicy::Reject { let mut references = Vec::new(); @@ -226,6 +482,9 @@ fn full_from_compact_policy( compact, lib_by_name, policy == UnresolvedReferencePolicy::Preserve, + projection, + closures, + truncated, )) } @@ -233,6 +492,9 @@ pub(crate) fn full_from_compact_with( compact: Value, lib_by_name: &HashMap, recover_refs: bool, + mut projection: Option<&mut crate::json::ResolvedModel>, + closures: ClosurePolicy, + truncated: &mut Vec, ) -> Value { let Value::Array(items) = compact else { return compact; @@ -258,16 +520,22 @@ pub(crate) fn full_from_compact_with( } // ---- implied relationships ---- - if !lib_by_name.is_empty() { - add_implied_relationships(&mut elements, lib_by_name); + // The layer synthesizes them (`json/implied.rs`) when the library + // bases are known (a loaded library or a name table — the layer + // synthesizes none otherwise, so `isImpliedIncluded` stays false + // exactly where no implied relationship is listed); the full form + // lists them under their owner's `ownedRelationship` and as elements + // of the array. Without a model to project from, none can be offered. + if let Some(resolved) = projection.as_deref_mut() { + add_implied_relationships(&mut elements, resolved); } - let implied_included = !lib_by_name.is_empty(); + let implied_included = projection.is_some() && !lib_by_name.is_empty(); // ---- graph indexes ---- let index: HashMap = elements .iter() .enumerate() - .map(|(i, el)| (eid(el), i)) + .map(|(i, el)| (eid(el).to_string(), i)) .collect(); // Element → owning relationship index; relationship → owner element idx. let owner_rel: Vec> = elements @@ -350,50 +618,280 @@ pub(crate) fn full_from_compact_with( ); } - let catalog: HashMap<&str, &[(&str, u8)]> = METACLASS_PROPS.iter().copied().collect(); + // Element::isLibraryElement (KerML deriveElementIsLibraryElement): + // true when `libraryNamespace()` is non-null, i.e. the element is a + // LibraryPackage or sits anywhere in the ownership tree of one. + // Ownership steps through the owning relationship (an element's + // `owningRelationship`, then that relationship's owner); a + // relationship's own owner is its `owningRelatedElement`. + // Library membership by ownership walk, for elements the layer does + // not project (implied relationships). + let library_element: Vec = { + let parent = |i: usize| -> Option { + rel_owner[i].or_else(|| owner_rel[i].and_then(|r| rel_owner[r])) + }; + let mut memo: Vec> = vec![None; elements.len()]; + for start in 0..elements.len() { + if memo[start].is_some() { + continue; + } + let mut path = Vec::new(); + let mut at = Some(start); + let mut found = false; + while let Some(i) = at { + if let Some(v) = memo[i] { + found = v; + break; + } + if path.contains(&i) { + break; // malformed ownership cycle: not a library tree + } + path.push(i); + if ty(&elements[i]) == "LibraryPackage" { + found = true; + break; + } + at = parent(i); + } + for i in path { + memo[i] = Some(found); + } + } + memo.into_iter().map(|v| v.unwrap_or(false)).collect() + }; // ---- derived properties ---- for i in 0..elements.len() { let t = ty(&elements[i]).to_string(); + let this_id = eid(&elements[i]).to_string(); let mut derived: Map = Map::new(); + // Projection: every name the derivation layer computes comes from + // the resolved model; the array-level code below only fills the + // families not ported yet. + // Elements with no model counterpart — the implied relationships + // this pass synthesizes — keep the array-level derivations until + // the layer synthesizes them itself. + let mut projected = false; + if let Some(resolved) = projection.as_deref_mut() { + // Same id *and* same metaclass: a model holding two elements + // under one id (a unit-name collision) must not lend one + // element's lists to the other. + if let Some(e) = resolved + .element_by_id(&this_id) + .filter(|&e| resolved.element_type(e) == t) + { + projected = true; + // Under the closure policy a walk that hit the depth + // budget refuses the emission rather than writing a cut + // closure. + if closures != ClosurePolicy::Passthrough && resolved.closure_truncated(e) { + truncated.push(this_id.clone()); + } + // The names the layer computes on this metaclass, decided + // once per metaclass rather than once per element. + let names = resolved.computable_names(resolved.element_type(e)); + for name in names.iter() { + // The four closure names are written under the closure + // policy only; the catalog's empty value stands for + // them at the passthrough level. + if closures == ClosurePolicy::Passthrough && CLOSURE_NAMES.contains(name) { + continue; + } + if let crate::json::Derived::Value(v) = resolved.derived_computable(e, name) { + derived.insert((*name).to_string(), derived_to_json(resolved, &v)); + } + } + // Relationships this pass added to the array and the model + // does not hold — the unresolved-reference recovery + // annotations' memberships — still belong to their owner's + // lists, so the full form stays self-consistent. + let extra: Vec = owned_rels[i] + .iter() + .copied() + .filter(|&r| resolved.element_by_id(eid(&elements[r])).is_none()) + .collect(); + for &r in &extra { + let rel = id_ref(eid(&elements[r])); + let kids: Vec = related_elems[r] + .iter() + .map(|&k| id_ref(eid(&elements[k]))) + .collect(); + let push = |derived: &mut Map, name: &str, vals: &[Value]| { + if let Some(Value::Array(a)) = derived.get_mut(name) { + a.extend(vals.iter().cloned()); + } + }; + push(&mut derived, "ownedElement", &kids); + // Recovery annotations are TextualRepresentations. + for &k in &related_elems[r] { + if ty(&elements[k]) == "TextualRepresentation" { + let kid = id_ref(eid(&elements[k])); + push(&mut derived, "textualRepresentation", &[kid]); + } + } + if is_membership(ty(&elements[r])) { + push(&mut derived, "ownedMembership", std::slice::from_ref(&rel)); + push(&mut derived, "membership", std::slice::from_ref(&rel)); + push(&mut derived, "ownedMember", &kids); + push(&mut derived, "member", &kids); + } + } + } + } + // Owned Annotation relationships and whether one annotates this + // very element (the prefix-annotation shape) — shared by the + // annotation-family derivations below. + let owned_annotations: Vec = owned_rels[i] + .iter() + .copied() + .filter(|&r| ty(&elements[r]) == "Annotation") + .collect(); + let annotates_self = |r: usize| match elements[r].get("annotatedElement").and_then(ref_of) { + Some(annotated) => annotated == this_id, + // Unspelled: completed from the owner below, in the shape where + // the Annotation owns its annotating element. + None => owned_annotating_element(&elements, &related_elems, &index, r).is_some(), + }; // Derivations that must win over a compact-spelled value (the // pilot computes these at the model level regardless of the // textual spelling): applied with insert, not or_insert. let mut overrides: Map = Map::new(); - // Ownership. + // Ownership (owner, owningMembership, owningNamespace and + // isLibraryElement are projected from the layer; an unprojected + // element gets the array-level derivation). let owner_idx = owner_rel[i].and_then(|r| rel_owner[r]); - derived.insert( - "owner".into(), - owner_idx - .map(|o| id_ref(&eid(&elements[o]))) - .unwrap_or(Value::Null), - ); - let owning_membership = owner_rel[i].filter(|&r| is_membership(ty(&elements[r]))); - derived.insert( - "owningMembership".into(), - owning_membership - .map(|r| id_ref(&eid(&elements[r]))) - .unwrap_or(Value::Null), - ); - derived.insert( - "owningNamespace".into(), - owning_membership - .and(owner_idx) - .map(|o| id_ref(&eid(&elements[o]))) - .unwrap_or(Value::Null), - ); - // Feature::endOwningType — the owner through an EndFeatureMembership - // (the catalog filter drops this for metaclasses without it) — and - // such end features are constant (KerML 2025 metamodel). - if owner_rel[i].is_some_and(|r| ty(&elements[r]) == "EndFeatureMembership") { - if let Some(o) = owner_idx { - derived.insert("endOwningType".into(), id_ref(&eid(&elements[o]))); - } - if t != "FlowEnd" { + if !projected { + derived.insert( + "owner".into(), + owner_idx + .map(|o| id_ref(eid(&elements[o]))) + .unwrap_or(Value::Null), + ); + let owning_membership = owner_rel[i].filter(|&r| is_membership(ty(&elements[r]))); + derived.insert( + "owningMembership".into(), + owning_membership + .map(|r| id_ref(eid(&elements[r]))) + .unwrap_or(Value::Null), + ); + derived.insert( + "owningNamespace".into(), + owning_membership + .and(owner_idx) + .map(|o| id_ref(eid(&elements[o]))) + .unwrap_or(Value::Null), + ); + derived.insert("isLibraryElement".into(), Value::Bool(library_element[i])); + } + // Feature::owningType — the owner through a FeatureMembership + // kind — with its membership, the SysML Definition/Usage + // narrowings, and `endOwningType` when the membership is an + // EndFeatureMembership (the catalog filter drops undeclared + // entries). + let owning_fm = + owner_rel[i].filter(|&r| crate::json::is_feature_membership(ty(&elements[r]))); + if let Some(r) = owning_fm { + let is_end = ty(&elements[r]) == "EndFeatureMembership"; + // The owning-type family is projected from the layer; an + // unprojected element gets the array-level derivation. + if !projected { + derived.insert("owningFeatureMembership".into(), id_ref(eid(&elements[r]))); + if let Some(o) = owner_idx.filter(|&o| conforms(ty(&elements[o]), "Type")) { + let oty = ty(&elements[o]); + let oref = id_ref(eid(&elements[o])); + if conforms(oty, "Definition") { + derived.insert("owningDefinition".into(), oref.clone()); + } + if conforms(oty, "Usage") { + derived.insert("owningUsage".into(), oref.clone()); + } + if is_end { + derived.insert("endOwningType".into(), oref.clone()); + } + derived.insert("owningType".into(), oref); + } + } + // End features are constant (KerML 2025 metamodel); the pilot's + // FlowEnds are not. + if is_end && t != "FlowEnd" { derived.insert("isConstant".into(), Value::Bool(true)); } } + if !projected { + // Type::multiplicity — the owned member that is a Multiplicity: the + // MultiplicityRange a `[n..m]` part declares, or a KerML + // `multiplicity` member. A Type owns at most one. (KerML's derive + // rule adds a fallback to the general Type's multiplicity through an + // owned Specialization; that contradicts the property's `subsets + // ownedMember`, and the property definition wins here.) + if let Some(m) = owned_rels[i] + .iter() + .filter(|&&r| is_membership(ty(&elements[r]))) + .find_map(|&r| { + related_elems[r] + .iter() + .copied() + .find(|&k| conforms(ty(&elements[k]), "Multiplicity")) + }) + { + derived.insert("multiplicity".into(), id_ref(eid(&elements[m]))); + } + } + // Annotation ends. This toolkit lowers every Annotation as owned by + // its annotating element (the `about` shape), so `annotatingElement` + // is the owner. A payload that instead owns the annotating element + // under the Annotation (KerML's `ownedAnnotatingElement`, the + // prefix-annotation shape) makes the owner the annotated element; + // the `owning*` narrowings and the endpoint fill below follow the + // same test. `annotatedElement` is an *owned* property here, so the + // layer never projects it and this completion runs for every + // Annotation; the projected names it also writes agree with the + // layer's. + // The Annotation-side family is projected; this is the fallback. + if !projected && t == "Annotation" { + let owned_annotating = owned_annotating_element(&elements, &related_elems, &index, i); + match (owned_annotating, rel_owner[i]) { + (Some(k), owner) => { + let kref = id_ref(eid(&elements[k])); + derived.insert("ownedAnnotatingElement".into(), kref.clone()); + derived.insert("annotatingElement".into(), kref); + // The owner is the annotated element when the spelled + // annotatedElement agrees; when it is absent, the required + // end is completed from the owner rather than left to the + // self-reference placeholder. + if let Some(o) = owner { + let oref = id_ref(eid(&elements[o])); + match elements[i].get("annotatedElement").and_then(ref_of) { + None => { + derived.insert("annotatedElement".into(), oref.clone()); + derived.insert("owningAnnotatedElement".into(), oref); + } + Some(a) if a == eid(&elements[o]) => { + derived.insert("owningAnnotatedElement".into(), oref); + } + Some(_) => {} + } + } + } + (None, Some(o)) if conforms(ty(&elements[o]), "AnnotatingElement") => { + let oref = id_ref(eid(&elements[o])); + derived.insert("annotatingElement".into(), oref.clone()); + derived.insert("owningAnnotatingElement".into(), oref); + } + _ => {} + } + } + // AnnotatingElement::owningAnnotatingRelationship — the owning + // relationship when it is an Annotation (prefix-annotation shape). + if !projected { + if let Some(r) = owner_rel[i].filter(|&r| ty(&elements[r]) == "Annotation") { + derived.insert( + "owningAnnotatingRelationship".into(), + id_ref(eid(&elements[r])), + ); + } + } // End *usages* are constant, variable, and time-varying regardless // of how they are owned (interface-body ends ride a plain // FeatureMembership) — but the pilot's FlowEnds are none of these. @@ -415,38 +913,33 @@ pub(crate) fn full_from_compact_with( overrides.insert("isComposite".into(), Value::Bool(true)); } - // Owned elements: through each owned relationship. - let mut owned_elements = Vec::new(); - for &r in &owned_rels[i] { - for &k in &related_elems[r] { - owned_elements.push(id_ref(&eid(&elements[k]))); + // Names: the layer projects `name`, `shortName` and + // `qualifiedName` (the graph-effective naming rule, KerML + // 8.2.3.5); the array-level rule is the fallback. + if !projected { + let declared_name = elements[i] + .get("declaredName") + .filter(|v| !v.is_null()) + .cloned() + .or_else(|| eff_names[i].clone().map(Value::String)) + .unwrap_or(Value::Null); + let declared_short = elements[i] + .get("declaredShortName") + .cloned() + .unwrap_or(Value::Null); + derived.insert("name".into(), declared_name); + derived.insert("shortName".into(), declared_short); + derived.insert( + "qualifiedName".into(), + qnames[i].clone().map(Value::String).unwrap_or(Value::Null), + ); + // Usage::isReference is derived as the negation of isComposite + // (pilot `Usage_isReference_SettingDelegate`); the catalog + // filter drops this for metaclasses without the property. + if let Some(c) = elements[i].get("isComposite").and_then(|v| v.as_bool()) { + derived.insert("isReference".into(), Value::Bool(!c)); } } - derived.insert("ownedElement".into(), Value::Array(owned_elements)); - - // Names. - let declared_name = elements[i] - .get("declaredName") - .filter(|v| !v.is_null()) - .cloned() - .or_else(|| eff_names[i].clone().map(Value::String)) - .unwrap_or(Value::Null); - let declared_short = elements[i] - .get("declaredShortName") - .cloned() - .unwrap_or(Value::Null); - derived.insert("name".into(), declared_name); - // Usage::isReference is derived as the negation of isComposite - // (pilot `Usage_isReference_SettingDelegate`); the catalog filter - // drops this for metaclasses without the property. - if let Some(c) = elements[i].get("isComposite").and_then(|v| v.as_bool()) { - derived.insert("isReference".into(), Value::Bool(!c)); - } - derived.insert("shortName".into(), declared_short); - derived.insert( - "qualifiedName".into(), - qnames[i].clone().map(Value::String).unwrap_or(Value::Null), - ); // Annotating members. let owned_kids: Vec = owned_rels[i] @@ -457,13 +950,15 @@ pub(crate) fn full_from_compact_with( owned_kids .iter() .filter(|&&k| ty(&elements[k]) == name) - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect() }; - derived.insert( - "documentation".into(), - Value::Array(kids_of_type("Documentation")), - ); + if !projected { + derived.insert( + "documentation".into(), + Value::Array(kids_of_type("Documentation")), + ); + } // Requirement/concern `text` is the owned documentation bodies // (pilot `RequirementDefinition_text_SettingDelegate`); the catalog // filter drops it for metaclasses without the property. @@ -472,98 +967,96 @@ pub(crate) fn full_from_compact_with( .filter(|&&k| ty(&elements[k]) == "Documentation") .filter_map(|&k| elements[k].get("body").filter(|v| !v.is_null()).cloned()) .collect(); - derived.insert("text".into(), Value::Array(texts)); - derived.insert( - "textualRepresentation".into(), - Value::Array(kids_of_type("TextualRepresentation")), - ); - derived.insert( - "ownedAnnotation".into(), - Value::Array( - owned_rels[i] - .iter() - .filter(|&&r| ty(&elements[r]) == "Annotation") - .map(|&r| id_ref(&eid(&elements[r]))) - .collect(), - ), - ); - - // Namespace-level memberships and imports. - let memberships: Vec = owned_rels[i] - .iter() - .filter(|&&r| is_membership(ty(&elements[r]))) - .map(|&r| id_ref(&eid(&elements[r]))) - .collect(); - derived.insert("ownedMembership".into(), Value::Array(memberships.clone())); - derived.insert("membership".into(), Value::Array(memberships)); - let owned_members: Vec = owned_rels[i] - .iter() - .filter(|&&r| is_membership(ty(&elements[r]))) - .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(&eid(&elements[k])))) - .collect(); - derived.insert("ownedMember".into(), Value::Array(owned_members.clone())); - derived.insert("member".into(), Value::Array(owned_members)); - derived.insert( - "ownedImport".into(), - Value::Array( - owned_rels[i] - .iter() - .filter(|&&r| is_import(ty(&elements[r]))) - .map(|&r| id_ref(&eid(&elements[r]))) - .collect(), - ), - ); + if !projected { + derived.insert("text".into(), Value::Array(texts)); + } + if !projected { + derived.insert( + "textualRepresentation".into(), + Value::Array(kids_of_type("TextualRepresentation")), + ); + } + // Element::ownedAnnotation — the owned Annotations that annotate + // this element (the prefix-annotation shape). An `about` clause's + // Annotation is owned by the annotating element and annotates + // another, so it is that element's `ownedAnnotatingRelationship`, + // not its `ownedAnnotation`. + if !projected { + derived.insert( + "ownedAnnotation".into(), + Value::Array( + owned_annotations + .iter() + .filter(|&&r| annotates_self(r)) + .map(|&r| id_ref(eid(&elements[r]))) + .collect(), + ), + ); + } - // Type-level features. + // The namespace membership family and the type-level feature + // family (ownedElement, ownedMembership, membership, ownedMember, + // member, ownedImport, ownedFeatureMembership, featureMembership, + // ownedFeature, feature) are projected from the layer; an + // unprojected element gets the array-level derivation. The owned + // features feed the direction-filtered families below either way. let feature_memberships: Vec = owned_rels[i] .iter() .copied() - .filter(|&r| { - matches!( - ty(&elements[r]), - "FeatureMembership" - | "EndFeatureMembership" - | "ParameterMembership" - | "ReturnParameterMembership" - | "ResultExpressionMembership" - | "VariantMembership" - | "SubjectMembership" - | "ActorMembership" - | "StakeholderMembership" - | "ObjectiveMembership" - | "RequirementConstraintMembership" - | "FramedConcernMembership" - | "RequirementVerificationMembership" - | "StateSubactionMembership" - | "TransitionFeatureMembership" - | "ViewRenderingMembership" - | "ElementFilterMembership" - ) - }) + .filter(|&r| crate::json::is_feature_membership(ty(&elements[r]))) .collect(); - derived.insert( - "ownedFeatureMembership".into(), - Value::Array( - feature_memberships - .iter() - .map(|&r| id_ref(&eid(&elements[r]))) - .collect(), - ), - ); - derived.insert( - "featureMembership".into(), - derived["ownedFeatureMembership"].clone(), - ); let features: Vec = feature_memberships .iter() .flat_map(|&r| related_elems[r].iter().copied()) .collect(); - let feature_refs: Vec = features - .iter() - .map(|&k| id_ref(&eid(&elements[k]))) - .collect(); - derived.insert("ownedFeature".into(), Value::Array(feature_refs.clone())); - derived.insert("feature".into(), Value::Array(feature_refs)); + if !projected { + let mut owned_elements = Vec::new(); + for &r in &owned_rels[i] { + for &k in &related_elems[r] { + owned_elements.push(id_ref(eid(&elements[k]))); + } + } + derived.insert("ownedElement".into(), Value::Array(owned_elements)); + let memberships: Vec = owned_rels[i] + .iter() + .filter(|&&r| is_membership(ty(&elements[r]))) + .map(|&r| id_ref(eid(&elements[r]))) + .collect(); + derived.insert("ownedMembership".into(), Value::Array(memberships.clone())); + derived.insert("membership".into(), Value::Array(memberships)); + let owned_members: Vec = owned_rels[i] + .iter() + .filter(|&&r| is_membership(ty(&elements[r]))) + .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(eid(&elements[k])))) + .collect(); + derived.insert("ownedMember".into(), Value::Array(owned_members.clone())); + derived.insert("member".into(), Value::Array(owned_members)); + derived.insert( + "ownedImport".into(), + Value::Array( + owned_rels[i] + .iter() + .filter(|&&r| is_import(ty(&elements[r]))) + .map(|&r| id_ref(eid(&elements[r]))) + .collect(), + ), + ); + let fm_refs: Vec = feature_memberships + .iter() + .map(|&r| id_ref(eid(&elements[r]))) + .collect(); + derived.insert( + "ownedFeatureMembership".into(), + Value::Array(fm_refs.clone()), + ); + derived.insert("featureMembership".into(), Value::Array(fm_refs)); + let feature_refs: Vec = features + .iter() + .map(|&k| id_ref(eid(&elements[k]))) + .collect(); + derived.insert("ownedFeature".into(), Value::Array(feature_refs.clone())); + derived.insert("feature".into(), Value::Array(feature_refs)); + } let ends: Vec = features .iter() .filter(|&&k| { @@ -572,10 +1065,12 @@ pub(crate) fn full_from_compact_with( .and_then(|v| v.as_bool()) .unwrap_or(false) }) - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(); - derived.insert("ownedEndFeature".into(), Value::Array(ends.clone())); - derived.insert("endFeature".into(), Value::Array(ends)); + if !projected { + derived.insert("ownedEndFeature".into(), Value::Array(ends.clone())); + derived.insert("endFeature".into(), Value::Array(ends)); + } let by_direction = |dir: &str| -> Vec { features .iter() @@ -585,15 +1080,17 @@ pub(crate) fn full_from_compact_with( && elements[k].get("direction").and_then(|v| v.as_str()) == Some("inout")) }) - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect() }; let mut input = by_direction("in"); input.extend(by_direction("inout")); let mut output = by_direction("out"); output.extend(by_direction("inout")); - derived.insert("input".into(), Value::Array(input)); - derived.insert("output".into(), Value::Array(output)); + if !projected { + derived.insert("input".into(), Value::Array(input)); + derived.insert("output".into(), Value::Array(output)); + } let directed: Vec = features .iter() .filter(|&&k| { @@ -602,73 +1099,83 @@ pub(crate) fn full_from_compact_with( .map(|v| v.is_string()) .unwrap_or(false) }) - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(); - derived.insert("directedFeature".into(), Value::Array(directed.clone())); - derived.insert("directedUsage".into(), Value::Array(directed)); + if !projected { + derived.insert("directedFeature".into(), Value::Array(directed.clone())); + derived.insert("directedUsage".into(), Value::Array(directed)); + } - // Specializations owned by this element. + // Specializations owned by this element (projected from the + // layer, implied ones included; the fallback below selects by + // exact metaclass name). let rels_of = |names: &[&str]| -> Vec { owned_rels[i] .iter() .filter(|&&r| names.contains(&ty(&elements[r]))) - .map(|&r| id_ref(&eid(&elements[r]))) + .map(|&r| id_ref(eid(&elements[r]))) .collect() }; - derived.insert( - "ownedSpecialization".into(), - Value::Array(rels_of(&[ - "Specialization", - "Subclassification", - "FeatureTyping", - "Subsetting", - "Redefinition", - "ReferenceSubsetting", - "CrossSubsetting", - ])), - ); - derived.insert( - "ownedSubclassification".into(), - Value::Array(rels_of(&["Subclassification"])), - ); - derived.insert( - "ownedTyping".into(), - Value::Array(rels_of(&["FeatureTyping", "ConjugatedPortTyping"])), - ); - derived.insert( - "ownedSubsetting".into(), - Value::Array(rels_of(&[ - "Subsetting", - "Redefinition", - "ReferenceSubsetting", - "CrossSubsetting", - ])), - ); - derived.insert( - "ownedRedefinition".into(), - Value::Array(rels_of(&["Redefinition"])), - ); - derived.insert( - "ownedReferenceSubsetting".into(), - rels_of(&["ReferenceSubsetting"]) - .into_iter() - .next() - .unwrap_or(Value::Null), - ); - derived.insert( - "ownedCrossSubsetting".into(), - rels_of(&["CrossSubsetting"]) - .into_iter() - .next() - .unwrap_or(Value::Null), - ); - derived.insert( - "ownedConjugator".into(), - rels_of(&["Conjugation", "PortConjugation"]) - .into_iter() - .next() - .unwrap_or(Value::Null), - ); + if !projected { + derived.insert( + "ownedSpecialization".into(), + Value::Array(rels_of(&[ + "Specialization", + "Subclassification", + "FeatureTyping", + "Subsetting", + "Redefinition", + "ReferenceSubsetting", + "CrossSubsetting", + ])), + ); + derived.insert( + "ownedSubclassification".into(), + Value::Array(rels_of(&["Subclassification"])), + ); + derived.insert( + "ownedTyping".into(), + Value::Array(rels_of(&["FeatureTyping", "ConjugatedPortTyping"])), + ); + derived.insert( + "ownedSubsetting".into(), + Value::Array(rels_of(&[ + "Subsetting", + "Redefinition", + "ReferenceSubsetting", + "CrossSubsetting", + ])), + ); + derived.insert( + "ownedRedefinition".into(), + Value::Array(rels_of(&["Redefinition"])), + ); + derived.insert( + "ownedReferenceSubsetting".into(), + rels_of(&["ReferenceSubsetting"]) + .into_iter() + .next() + .unwrap_or(Value::Null), + ); + } + if !projected { + derived.insert( + "ownedCrossSubsetting".into(), + rels_of(&["CrossSubsetting"]) + .into_iter() + .next() + .unwrap_or(Value::Null), + ); + } + if !projected { + derived.insert( + "ownedConjugator".into(), + rels_of(&["Conjugation", "PortConjugation"]) + .into_iter() + .next() + .unwrap_or(Value::Null), + ); + } derived.insert( "ownedDisjoining".into(), Value::Array(rels_of(&["Disjoining"])), @@ -680,9 +1187,11 @@ pub(crate) fn full_from_compact_with( .filter(|&&r| matches!(ty(&elements[r]), "FeatureTyping" | "ConjugatedPortTyping")) .filter_map(|&r| elements[r].get("type").cloned()) .collect(); - derived.insert("type".into(), Value::Array(typing_targets.clone())); - if t.ends_with("Usage") || usage_kind_of(&t, Dialect::Sysml).is_some() { - derived.insert("definition".into(), Value::Array(typing_targets)); + if !projected { + derived.insert("type".into(), Value::Array(typing_targets.clone())); + if t.ends_with("Usage") || usage_kind_of(&t, Dialect::Sysml).is_some() { + derived.insert("definition".into(), Value::Array(typing_targets)); + } } // Usage kind-filtered lists (ownedPart / nestedPart / …). @@ -693,38 +1202,88 @@ pub(crate) fn full_from_compact_with( .collect(); let usage_kid_refs: Vec = usage_kids .iter() - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(); - derived.insert("ownedUsage".into(), Value::Array(usage_kid_refs.clone())); - derived.insert("nestedUsage".into(), Value::Array(usage_kid_refs.clone())); - derived.insert("usage".into(), Value::Array(usage_kid_refs)); - let variant_rels: Vec = rels_of(&["VariantMembership"]); - derived.insert("variantMembership".into(), Value::Array(variant_rels)); - derived.insert( - "variant".into(), - Value::Array( - owned_rels[i] - .iter() - .filter(|&&r| ty(&elements[r]) == "VariantMembership") - .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(&eid(&elements[k])))) - .collect(), - ), + if !projected { + derived.insert("ownedUsage".into(), Value::Array(usage_kid_refs.clone())); + derived.insert("nestedUsage".into(), Value::Array(usage_kid_refs.clone())); + derived.insert("usage".into(), Value::Array(usage_kid_refs)); + let variant_rels: Vec = rels_of(&["VariantMembership"]); + derived.insert("variantMembership".into(), Value::Array(variant_rels)); + derived.insert( + "variant".into(), + Value::Array( + owned_rels[i] + .iter() + .filter(|&&r| ty(&elements[r]) == "VariantMembership") + .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(eid(&elements[k])))) + .collect(), + ), + ); + } + + // Relationship endpoints (`source`/`target` are owned on the + // wire; `relatedElement` is projected). + fill_relationship_endpoints( + &mut derived, + &elements, + i, + &rel_owner, + &related_elems, + projected, ); - // Relationship endpoints. - fill_relationship_endpoints(&mut derived, &elements, i, &rel_owner, &related_elems); + // Relationship-side owners (owningType, owningClassifier, + // owningFeature, owningFeatureOfType) are projected from the layer; + // an implied specialization, which has no model counterpart, is + // owned by its specific side and says so. + if !projected { + if let Some(o) = rel_owner[i].filter(|_| !is_membership(&t) && !is_import(&t)) { + let owner_props: &[(&str, &str)] = if conforms(&t, "Subclassification") { + &[("owningType", "Type"), ("owningClassifier", "Classifier")] + } else if conforms(&t, "Subsetting") || conforms(&t, "FeatureTyping") { + &[("owningType", "Type"), ("owningFeature", "Feature")] + } else if conforms(&t, "Specialization") + || conforms(&t, "Conjugation") + || conforms(&t, "Disjoining") + { + &[("owningType", "Type")] + } else if t == "FeatureInverting" { + &[("owningFeature", "Feature")] + } else if t == "TypeFeaturing" { + &[("owningFeatureOfType", "Feature")] + } else { + &[] + }; + let owner_id = eid(&elements[o]); + let owner_is_source = derived + .get("source") + .and_then(Value::as_array) + .and_then(|ends| ends.first()) + .is_none_or(|source| ref_of(source).as_deref() == Some(owner_id)); + if owner_is_source { + let oty = ty(&elements[o]); + let oref = id_ref(owner_id); + for (prop, kind) in owner_props { + if conforms(oty, kind) { + derived.insert((*prop).into(), oref.clone()); + } + } + } + } + } // Derived redefinitions with non-nullable schema types. if is_membership(&t) { // Owning-membership family: the owned member element under // redefining names. - let owned_member = related_elems[i] - .first() - .map(|&k| id_ref(&eid(&elements[k]))); + let owned_member = related_elems[i].first().map(|&k| id_ref(eid(&elements[k]))); if let Some(m) = &owned_member { - derived.insert("ownedMemberElement".into(), m.clone()); - derived.insert("ownedMemberFeature".into(), m.clone()); - if let Some(id) = ref_of(m) { + if !projected { + derived.insert("ownedMemberElement".into(), m.clone()); + derived.insert("ownedMemberFeature".into(), m.clone()); + } + if let (Some(id), false) = (ref_of(m), projected) { derived.insert("ownedMemberElementId".into(), Value::String(id.clone())); if let Some(&k) = index.get(&id) { // An unnamed member falls back to its effective @@ -760,13 +1319,19 @@ pub(crate) fn full_from_compact_with( } } // The type owning a feature membership. - if let Some(o) = rel_owner[i] { - derived.insert("owningType".into(), id_ref(&eid(&elements[o]))); + if !projected { + if let Some(o) = rel_owner[i] { + derived.insert("owningType".into(), id_ref(eid(&elements[o]))); + } } } - if is_import(&t) { + // Import-side names (importOwningNamespace, importedElement) are + // projected from the layer; an unprojected import gets the + // array-level derivation (an in-document membership target is + // dereferenced to its member, a library one stays the membership). + if !projected && is_import(&t) { if let Some(o) = rel_owner[i] { - derived.insert("importOwningNamespace".into(), id_ref(&eid(&elements[o]))); + derived.insert("importOwningNamespace".into(), id_ref(eid(&elements[o]))); } if let Some(target) = elements[i] .get("importedNamespace") @@ -788,56 +1353,60 @@ pub(crate) fn full_from_compact_with( .filter(|v| v.get("@id").is_some()) .cloned() .or_else(|| { - related_elems[m] - .first() - .map(|&k| id_ref(&eid(&elements[k]))) + related_elems[m].first().map(|&k| id_ref(eid(&elements[k]))) }) }) .unwrap_or(target); derived.insert("importedElement".into(), target); } } - // Features: featureTarget = last chaining feature, else self. - let self_ref = id_ref(&eid(&elements[i])); - let chain_rels: Vec = owned_rels[i] - .iter() - .copied() - .filter(|&r| ty(&elements[r]) == "FeatureChaining") - .collect(); - let last_chain = chain_rels - .last() - .and_then(|&r| elements[r].get("chainingFeature").cloned()); - derived.insert( - "chainingFeature".into(), - Value::Array( - chain_rels - .iter() - .filter_map(|&r| elements[r].get("chainingFeature").cloned()) - .collect(), - ), - ); - derived.insert( - "ownedFeatureChaining".into(), - Value::Array( - chain_rels - .iter() - .map(|&r| id_ref(&eid(&elements[r]))) - .collect(), - ), - ); - derived.insert( - "featureTarget".into(), - last_chain.unwrap_or(self_ref.clone()), - ); - // Expressions: `result`/`function` — approximated by self-reference - // until result parameters are synthesized (documented). - derived.insert("result".into(), self_ref.clone()); - if t == "FeatureValue" { + // Features: featureTarget = last chaining feature, else self + // (projected from the layer; the fallback for an unprojected + // element). + let self_ref = id_ref(&this_id); + if !projected { + let chain_rels: Vec = owned_rels[i] + .iter() + .copied() + .filter(|&r| ty(&elements[r]) == "FeatureChaining") + .collect(); + let last_chain = chain_rels + .last() + .and_then(|&r| elements[r].get("chainingFeature").cloned()); + derived.insert( + "chainingFeature".into(), + Value::Array( + chain_rels + .iter() + .filter_map(|&r| elements[r].get("chainingFeature").cloned()) + .collect(), + ), + ); + derived.insert( + "ownedFeatureChaining".into(), + Value::Array( + chain_rels + .iter() + .map(|&r| id_ref(eid(&elements[r]))) + .collect(), + ), + ); + derived.insert( + "featureTarget".into(), + last_chain.unwrap_or_else(|| self_ref.clone()), + ); + } + // Expressions: `result` (projected: the return parameter) — + // the self-reference placeholder for an unprojected element. + if !projected { + derived.insert("result".into(), self_ref.clone()); + } + if !projected && t == "FeatureValue" { if let Some(o) = rel_owner[i] { - derived.insert("featureWithValue".into(), id_ref(&eid(&elements[o]))); + derived.insert("featureWithValue".into(), id_ref(eid(&elements[o]))); } if let Some(&k) = related_elems[i].first() { - derived.insert("value".into(), id_ref(&eid(&elements[k]))); + derived.insert("value".into(), id_ref(eid(&elements[k]))); } } // Expression-family derived references. @@ -849,59 +1418,52 @@ pub(crate) fn full_from_compact_with( .get("memberElement") .cloned() .filter(|v| !v.is_null()) - .or_else(|| { - related_elems[r] - .first() - .map(|&k| id_ref(&eid(&elements[k]))) - }) + .or_else(|| related_elems[r].first().map(|&k| id_ref(eid(&elements[k])))) }); match t.as_str() { - "FeatureReferenceExpression" => { + "FeatureReferenceExpression" if !projected => { if let Some(m) = &membership_target { derived.insert("referent".into(), m.clone()); } } - "FeatureChainExpression" => { + "FeatureChainExpression" if !projected => { if let Some(m) = &membership_target { derived.insert("targetFeature".into(), m.clone()); } } - "ReferenceSubsetting" => { + "ReferenceSubsetting" if !projected => { if let Some(o) = rel_owner[i] { - derived.insert("referencingFeature".into(), id_ref(&eid(&elements[o]))); + derived.insert("referencingFeature".into(), id_ref(eid(&elements[o]))); } } - "CrossSubsetting" => { + "CrossSubsetting" if !projected => { if let Some(o) = rel_owner[i] { - derived.insert("crossingFeature".into(), id_ref(&eid(&elements[o]))); + derived.insert("crossingFeature".into(), id_ref(eid(&elements[o]))); } } - "PortDefinition" => { + "PortDefinition" if !projected => { if let Some(&c) = owned_kids .iter() .find(|&&k| ty(&elements[k]) == "ConjugatedPortDefinition") { - derived.insert( - "conjugatedPortDefinition".into(), - id_ref(&eid(&elements[c])), - ); + derived.insert("conjugatedPortDefinition".into(), id_ref(eid(&elements[c]))); } } - "ConjugatedPortDefinition" => { + "ConjugatedPortDefinition" if !projected => { derived.insert("isConjugated".into(), Value::Bool(true)); if let Some(o) = owner_idx { - derived.insert("originalPortDefinition".into(), id_ref(&eid(&elements[o]))); + derived.insert("originalPortDefinition".into(), id_ref(eid(&elements[o]))); } if let Some(&pc) = owned_rels[i] .iter() .find(|&&r| ty(&elements[r]) == "PortConjugation") { - derived.insert("ownedPortConjugator".into(), id_ref(&eid(&elements[pc]))); + derived.insert("ownedPortConjugator".into(), id_ref(eid(&elements[pc]))); } } // The conjugated definition: a PortConjugation's owner, a // State sub-actions: the entry/do/exit members by kind. - "StateUsage" | "StateDefinition" => { + "StateUsage" | "StateDefinition" if !projected => { for &r in &owned_rels[i] { if ty(&elements[r]) != "StateSubactionMembership" { continue; @@ -923,11 +1485,7 @@ pub(crate) fn full_from_compact_with( .get("memberElement") .cloned() .filter(|v| v.get("@id").is_some()) - .or_else(|| { - related_elems[r] - .first() - .map(|&k| id_ref(&eid(&elements[k]))) - }); + .or_else(|| related_elems[r].first().map(|&k| id_ref(eid(&elements[k])))); if let Some(v) = target { derived.insert(prop.into(), v); } @@ -936,7 +1494,7 @@ pub(crate) fn full_from_compact_with( // The verified requirement is the member's *referenced* target // — the chain's last link when the reference is a chain — not // the implicit member itself. - "RequirementVerificationMembership" => { + "RequirementVerificationMembership" if !projected => { let target = related_elems[i].first().and_then(|&member| { let refsub = owned_rels[member] .iter() @@ -967,7 +1525,7 @@ pub(crate) fn full_from_compact_with( } // The requirements a verification case verifies: the // objective's RequirementVerificationMembership members. - "VerificationCaseUsage" | "VerificationCaseDefinition" => { + "VerificationCaseUsage" | "VerificationCaseDefinition" if !projected => { let mut verified = Vec::new(); for &r in &owned_rels[i] { if ty(&elements[r]) != "ObjectiveMembership" { @@ -985,7 +1543,7 @@ pub(crate) fn full_from_compact_with( .or_else(|| { related_elems[rr] .first() - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) }); verified.extend(target); } @@ -997,7 +1555,7 @@ pub(crate) fn full_from_compact_with( } // The membership's referenced rendering: the member's // reference target, like ViewUsage::viewRendering below. - "ViewRenderingMembership" => { + "ViewRenderingMembership" if !projected => { let target = related_elems[i].first().and_then(|&member| { owned_rels[member] .iter() @@ -1016,7 +1574,7 @@ pub(crate) fn full_from_compact_with( // The rendering a view uses: the ViewRenderingMembership // member's *referenced* rendering when the member is a // reference (`render asTreeDiagram;`), else the member itself. - "ViewUsage" | "ViewDefinition" => { + "ViewUsage" | "ViewDefinition" if !projected => { let member = owned_rels[i] .iter() .find(|&&r| ty(&elements[r]) == "ViewRenderingMembership") @@ -1031,7 +1589,7 @@ pub(crate) fn full_from_compact_with( .cloned() .filter(|v| v.get("@id").is_some()) }) - .or_else(|| Some(id_ref(&eid(&elements[k])))) + .or_else(|| Some(id_ref(eid(&elements[k])))) }); if let Some(v) = target { derived.insert("viewRendering".into(), v); @@ -1040,7 +1598,7 @@ pub(crate) fn full_from_compact_with( // The element whose metadata is accessed: the owned // Membership's member (the generic required-ref fill would // self-refer). - "MetadataAccessExpression" => { + "MetadataAccessExpression" if !projected => { let target = owned_rels[i] .iter() .find(|&&r| ty(&elements[r]) == "Membership") @@ -1050,9 +1608,7 @@ pub(crate) fn full_from_compact_with( .cloned() .filter(|v| v.get("@id").is_some()) .or_else(|| { - related_elems[r] - .first() - .map(|&k| id_ref(&eid(&elements[k]))) + related_elems[r].first().map(|&k| id_ref(eid(&elements[k]))) }) }); if let Some(v) = target { @@ -1062,8 +1618,10 @@ pub(crate) fn full_from_compact_with( // ConjugatedPortTyping's type. "PortConjugation" => { if let Some(o) = rel_owner[i] { - let r = id_ref(&eid(&elements[o])); - derived.insert("conjugatedPortDefinition".into(), r.clone()); + let r = id_ref(eid(&elements[o])); + if !projected { + derived.insert("conjugatedPortDefinition".into(), r.clone()); + } derived.insert("conjugatedType".into(), r); } } @@ -1072,12 +1630,12 @@ pub(crate) fn full_from_compact_with( derived.insert("conjugatedPortDefinition".into(), t); } } - "TransitionUsage" => { + "TransitionUsage" if !projected => { if let Some(succ) = owned_kids .iter() .find(|&&k| ty(&elements[k]) == "SuccessionAsUsage") { - derived.insert("succession".into(), id_ref(&eid(&elements[*succ]))); + derived.insert("succession".into(), id_ref(eid(&elements[*succ]))); } } // Association-family definitions: the end lists derive from the @@ -1093,9 +1651,9 @@ pub(crate) fn full_from_compact_with( let ends: Vec = owned_kids .iter() .filter(|&&k| elements[k].get("isEnd").and_then(|v| v.as_bool()) == Some(true)) - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(); - if !ends.is_empty() { + if !ends.is_empty() && !projected { derived.insert("associationEnd".into(), Value::Array(ends.clone())); derived.insert("connectionEnd".into(), Value::Array(ends.clone())); if t == "InterfaceDefinition" { @@ -1112,13 +1670,13 @@ pub(crate) fn full_from_compact_with( .copied() .filter(|&k| ty(&elements[k]) == "FlowEnd") .collect(); - if !flow_ends.is_empty() { + if !flow_ends.is_empty() && !projected { derived.insert( "flowEnd".into(), Value::Array( flow_ends .iter() - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(), ), ); @@ -1129,7 +1687,7 @@ pub(crate) fn full_from_compact_with( .iter() .find(|&&r| ty(&elements[r]) == "FeatureMembership") .and_then(|&r| related_elems[r].first()) - .map(|&f| id_ref(&eid(&elements[f]))) + .map(|&f| id_ref(eid(&elements[f]))) }; if let Some(v) = flow_ends.first().copied().and_then(feature_of) { derived.insert("sourceOutputFeature".into(), v); @@ -1138,14 +1696,16 @@ pub(crate) fn full_from_compact_with( derived.insert("targetInputFeature".into(), v); } } - if let Some(&p) = owned_kids - .iter() - .find(|&&k| ty(&elements[k]) == "PayloadFeature") - { - derived.insert("payloadFeature".into(), id_ref(&eid(&elements[p]))); + if let (Some(&p), false) = ( + owned_kids + .iter() + .find(|&&k| ty(&elements[k]) == "PayloadFeature"), + projected, + ) { + derived.insert("payloadFeature".into(), id_ref(eid(&elements[p]))); } } - "AcceptActionUsage" => { + "AcceptActionUsage" if !projected => { // payloadParameter = the first reference parameter (the // payload); receiverArgument = the receiver parameter's // bound value expression. @@ -1156,7 +1716,7 @@ pub(crate) fn full_from_compact_with( .filter(|&k| matches!(ty(&elements[k]), "ReferenceUsage" | "Feature")) .collect(); if let Some(&p) = ref_params.first() { - derived.insert("payloadParameter".into(), id_ref(&eid(&elements[p]))); + derived.insert("payloadParameter".into(), id_ref(eid(&elements[p]))); } if let Some(&r) = ref_params.get(1) { if let Some(&a) = owned_rels[r] @@ -1164,14 +1724,16 @@ pub(crate) fn full_from_compact_with( .find(|&&fv| ty(&elements[fv]) == "FeatureValue") .and_then(|&fv| related_elems[fv].first()) { - derived.insert("receiverArgument".into(), id_ref(&eid(&elements[a]))); + derived.insert("receiverArgument".into(), id_ref(eid(&elements[a]))); } } } "PerformActionUsage" | "EventOccurrenceUsage" | "ExhibitStateUsage" - | "IncludeUseCaseUsage" => { + | "IncludeUseCaseUsage" + if !projected => + { // The referenced action/occurrence — dereferenced through // an owned feature chain to its target (the pilot resolves // `perform a.b` to `b`, not to the chain feature), else @@ -1199,54 +1761,67 @@ pub(crate) fn full_from_compact_with( derived.insert("exhibitedState".into(), referenced.clone()); derived.insert("useCaseIncluded".into(), referenced); } - "MetadataUsage" | "MetadataFeature" => { - let explicit: Vec = owned_rels[i] - .iter() - .filter(|&&r| ty(&elements[r]) == "Annotation") - .filter_map(|&r| elements[r].get("annotatedElement").cloned()) - .collect(); - let annotated = if explicit.is_empty() { - owner_idx - .map(|o| vec![id_ref(&eid(&elements[o]))]) - .unwrap_or_default() - } else { - explicit - }; - derived.insert("annotatedElement".into(), Value::Array(annotated)); - } _ => {} } - // Annotating elements: annotated/documented element defaults to - // the owning element when no explicit `about` annotation exists. - if matches!( - t.as_str(), - "Comment" | "Documentation" | "TextualRepresentation" - ) { - let explicit: Vec = owned_rels[i] + // Annotating elements. `annotation` is the owning Annotation (the + // prefix-annotation shape) followed by the owned ones (`about` + // clauses); `ownedAnnotatingRelationship` is the owned ones that + // annotate another element, the complement of `ownedAnnotation`. + // `annotatedElement` follows those Annotations; an annotating + // element with none annotates its owner implicitly. + // All of them are projected from the layer (a target outside the + // model is a `Reference` there); this is the fallback. + if !projected && conforms(&t, "AnnotatingElement") { + let owning = owner_rel[i].filter(|&r| ty(&elements[r]) == "Annotation"); + let owned_relating: Vec = owned_annotations .iter() - .filter(|&&r| ty(&elements[r]) == "Annotation") - .filter_map(|&r| elements[r].get("annotatedElement").cloned()) + .copied() + .filter(|&r| !annotates_self(r)) .collect(); - let annotated = if explicit.is_empty() { - owner_idx - .map(|o| vec![id_ref(&eid(&elements[o]))]) - .unwrap_or_default() - } else { - explicit - }; - if let Some(first) = annotated.first() { - derived.insert("documentedElement".into(), first.clone()); - derived.insert("representedElement".into(), first.clone()); - derived.insert("annotation".into(), Value::Array(Vec::new())); + let mut annotation: Vec = owning.into_iter().collect(); + annotation.extend(owned_relating.iter().copied()); + let mut annotated: Vec = annotation + .iter() + .filter_map(|&r| { + elements[r] + .get("annotatedElement") + .cloned() + .filter(|v| !v.is_null()) + // The owning Annotation may be completed from its + // owner (the Annotation ends above); apply the same + // rule here, whatever the element order. + .or_else(|| { + (Some(r) == owning) + .then(|| rel_owner[r].map(|o| id_ref(eid(&elements[o])))) + .flatten() + }) + }) + .collect(); + if annotated.is_empty() { + annotated.extend(owner_idx.map(|o| id_ref(eid(&elements[o])))); + } + if matches!( + t.as_str(), + "Comment" | "Documentation" | "TextualRepresentation" + ) { + if let Some(first) = annotated.first() { + derived.insert("documentedElement".into(), first.clone()); + derived.insert("representedElement".into(), first.clone()); + } } derived.insert("annotatedElement".into(), Value::Array(annotated)); + let refs = |rels: &[usize]| -> Value { + Value::Array(rels.iter().map(|&r| id_ref(eid(&elements[r]))).collect()) + }; + derived.insert("ownedAnnotatingRelationship".into(), refs(&owned_relating)); + derived.insert("annotation".into(), refs(&annotation)); } - if t == "MultiplicityRange" { + if !projected && t == "MultiplicityRange" { let bounds: Vec = owned_rels[i] .iter() .filter(|&&r| ty(&elements[r]) == "OwningMembership") - .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(&eid(&elements[k])))) + .flat_map(|&r| related_elems[r].iter().map(|&k| id_ref(eid(&elements[k])))) .collect(); if !bounds.is_empty() { derived.insert( @@ -1264,13 +1839,15 @@ pub(crate) fn full_from_compact_with( // Membership extras. if is_membership(&t) { - if let Some(target) = elements[i].get("memberElement").cloned().or_else(|| { - related_elems[i] - .first() - .map(|&k| id_ref(&eid(&elements[k]))) - }) { + if let Some(target) = elements[i] + .get("memberElement") + .cloned() + .or_else(|| related_elems[i].first().map(|&k| id_ref(eid(&elements[k])))) + { if let Some(id) = ref_of(&target) { - derived.insert("memberElementId".into(), Value::String(id.clone())); + if !projected { + derived.insert("memberElementId".into(), Value::String(id.clone())); + } if elements[i].get("memberName").is_none() { let name = index .get(&id) @@ -1294,12 +1871,14 @@ pub(crate) fn full_from_compact_with( } derived.insert("memberElement".into(), target); } - derived.insert( - "membershipOwningNamespace".into(), - rel_owner[i] - .map(|o| id_ref(&eid(&elements[o]))) - .unwrap_or(Value::Null), - ); + if !projected { + derived.insert( + "membershipOwningNamespace".into(), + rel_owner[i] + .map(|o| id_ref(eid(&elements[o]))) + .unwrap_or(Value::Null), + ); + } } // Overlay: computed derived values (only those the metaclass @@ -1307,15 +1886,18 @@ pub(crate) fn full_from_compact_with( // for anything still missing. let el = &mut elements[i]; el.insert("isImpliedIncluded".into(), json!(implied_included)); - if let Some(props) = catalog.get(t.as_str()) { - let declared: std::collections::HashSet<&str> = props.iter().map(|(n, _)| *n).collect(); + if let Some(props) = metaclass_props(&t) { + // The property list is sorted by name (asserted in this + // module's tests), so membership is a search over the static + // table rather than a set built afresh for every element. + let declared = |name: &str| props.binary_search_by_key(&name, |(n, _)| n).is_ok(); for (k, v) in derived { - if declared.contains(k.as_str()) { + if declared(&k) { el.entry(k).or_insert(v); } } for (k, v) in std::mem::take(&mut overrides) { - if declared.contains(k.as_str()) { + if declared(&k) { el.insert(k, v); } } @@ -1329,11 +1911,6 @@ pub(crate) fn full_from_compact_with( .and_then(|a| a.first()) .cloned() }); - let self_id = el - .get("@id") - .and_then(|v| v.as_str()) - .unwrap_or("") - .to_string(); for (name, shape) in props.iter() { if el.get(*name).map(|v| !v.is_null()).unwrap_or(false) { continue; @@ -1348,7 +1925,7 @@ pub(crate) fn full_from_compact_with( if is_membership(&t) && member_alias.is_some() { member_alias.clone().unwrap() } else { - json!({ "@id": self_id }) + id_ref(&this_id) } } _ => Value::Null, @@ -1359,9 +1936,7 @@ pub(crate) fn full_from_compact_with( // (dialect mismatches would trip additionalProperties). let keys: Vec = el .keys() - .filter(|k| { - !k.starts_with('@') && !declared.contains(k.as_str()) && *k != "elementId" - }) + .filter(|k| !k.starts_with('@') && !declared(k) && *k != "elementId") .cloned() .collect(); for k in keys { @@ -1391,12 +1966,16 @@ fn inject_unresolved_reps(elements: &mut Vec>) { let by_id: HashMap = elements .iter() .enumerate() - .map(|(i, e)| (eid(e), i)) + .map(|(i, e)| (eid(e).to_string(), i)) .collect(); fn collect_refs(v: &Value, out: &mut Vec) { match v { Value::Object(m) => { if let Some(Value::String(s)) = m.get("@ref") { + // Id-shaped spellings are ids, not names to recover. + if Uuid::parse_str(s.trim_matches('\'')).is_ok() { + return; + } out.push(s.clone()); return; } @@ -1448,7 +2027,7 @@ fn inject_unresolved_reps(elements: &mut Vec>) { if !seen.insert((root, name.clone())) { continue; } - let root_id = eid(&elements[root]); + let root_id = eid(&elements[root]).to_string(); let mem_id = Uuid::new_v5( &Uuid::NAMESPACE_OID, format!("unresolved-rep-m:{root_id}:{name}").as_bytes(), @@ -1488,9 +2067,15 @@ fn patch_refs(v: &mut Value) { match v { Value::Object(m) => { if let Some(Value::String(s)) = m.get("@ref") { - // Deterministic dangling ID for unresolvable references. - let id = Uuid::new_v5(&Uuid::NAMESPACE_OID, format!("unresolved:{s}").as_bytes()); - let id = id.to_string(); + // An id-shaped spelling is a reference by id (the lift + // spells a target it cannot name — an unnamed element, or + // a library element with no library loaded — as its quoted + // id): keep the id. Anything else gets a deterministic + // dangling id. + let id = match Uuid::parse_str(s.trim_matches('\'')) { + Ok(id) => id.to_string(), + Err(_) => dangling_id(s), + }; m.clear(); m.insert("@id".into(), Value::String(id)); return; @@ -1512,6 +2097,16 @@ fn patch_refs(v: &mut Value) { /// declared name, else the name of the first feature this one explicitly /// redefines (`Feature::namingFeature`) or references (SysML reference /// forms), else — for chain features — the last chaining target's name. +/// +/// One naming rule, four representations. The implementations are this +/// one (over the full form's element maps, the only one that also +/// derives the positional implied names), +/// `json::Builder::graph_effective_name` (over the lowered element +/// graph, where `Builder::effective_name` is the declaration-only half), +/// `lift::Lifter::effective_name` (over payload JSON), and the fixpoint +/// inside `ids::walk` (over a compact payload, for id segments). They +/// agree by construction and by the differential test in the round-trip +/// gate; a change to one belongs in all of them. fn effective_name_of( i: usize, elements: &[Map], @@ -1670,9 +2265,10 @@ fn implied_member_name( } /// The positional name of an invocation/constructor argument: the pilot -/// implicitly redefines the callee's `in` parameters in declaration order. -/// Only derivable when the callee is in-document; a feature owning any -/// Redefinition is a named argument and keeps that name (even unresolved). +/// implicitly redefines the callee's input parameters (`in`, `inout`) in +/// declaration order, an unnamed one holding its position. Only derivable +/// when the callee is in-document; a feature owning any Redefinition is a +/// named argument and keeps that name (even unresolved). fn invocation_arg_name( i: usize, rel: usize, @@ -1727,14 +2323,15 @@ fn invocation_arg_name( ) { return None; } - // The callee: the invocation's fn/type Membership target. + // The callee: the invocation's fn/type Membership target (an + // OwningMembership when the callee is a feature chain). let callee_id = owner_rels .iter() - .find(|&&r| ty(&elements[r]) == "Membership") + .find(|&&r| matches!(ty(&elements[r]), "Membership" | "OwningMembership")) .and_then(|&r| elements[r].get("memberElement")) .and_then(ref_of)?; let callee = *index.get(&callee_id)?; - let params: Vec<&str> = elements[callee] + let params: Vec> = elements[callee] .get("ownedRelationship") .and_then(|v| v.as_array())? .iter() @@ -1748,14 +2345,19 @@ fn invocation_arg_name( .and_then(ref_of) .and_then(|id| index.get(&id).copied()) }) - .filter(|&k| elements[k].get("direction").and_then(|v| v.as_str()) == Some("in")) - .filter_map(|k| elements[k].get("declaredName").and_then(|v| v.as_str())) + .filter(|&k| { + matches!( + elements[k].get("direction").and_then(|v| v.as_str()), + Some("in" | "inout") + ) + }) + .map(|k| elements[k].get("declaredName").and_then(|v| v.as_str())) .collect(); let pos = owner_rels .iter() .filter(|&&r| ty(&elements[r]) == "ParameterMembership") .position(|&r| r == rel)?; - params.get(pos).map(|n| n.to_string()) + params.get(pos).copied().flatten().map(|n| n.to_string()) } fn qname_of( @@ -1800,13 +2402,14 @@ fn fill_relationship_endpoints( i: usize, rel_owner: &[Option], related_elems: &[Vec], + projected: bool, ) { let el = &elements[i]; let t = ty(el); - let owner = rel_owner[i].map(|o| id_ref(&eid(&elements[o]))); + let owner = rel_owner[i].map(|o| id_ref(eid(&elements[o]))); let owned: Vec = related_elems[i] .iter() - .map(|&k| id_ref(&eid(&elements[k]))) + .map(|&k| id_ref(eid(&elements[k]))) .collect(); let get = |k: &str| el.get(k).cloned().filter(|v| !v.is_null()); @@ -1815,13 +2418,13 @@ fn fill_relationship_endpoints( .or_else(|| owned.first().cloned()) .into_iter() .collect(); - (owner.clone().into_iter().collect(), target) + (owner.into_iter().collect(), target) } else if is_import(t) { let target = get("importedNamespace") .or_else(|| get("importedMembership")) .into_iter() .collect(); - (owner.clone().into_iter().collect(), target) + (owner.into_iter().collect(), target) } else { match t { "Subclassification" | "Specialization" => { @@ -1851,7 +2454,9 @@ fn fill_relationship_endpoints( "Subsetting" | "Redefinition" | "ReferenceSubsetting" | "CrossSubsetting" => { let source = get("subsettingFeature") .or_else(|| get("redefiningFeature")) - .or(owner.clone()); + .or_else(|| get("referencingFeature")) + .or_else(|| get("crossingFeature")) + .or_else(|| owner.clone()); let target = get("subsettedFeature") .or_else(|| get("redefinedFeature")) .or_else(|| get("referencedFeature")) @@ -1880,25 +2485,38 @@ fn fill_relationship_endpoints( (client, supplier) } "Annotation" => { - let target = get("annotatedElement").into_iter().collect(); - (owner.clone().into_iter().collect(), target) + // The annotating element: the owner in the `about` shape, + // the owned annotating element otherwise (derived above, or + // spelled by a foreign payload); the annotated element may + // likewise have been completed from the owner. + let source = derived + .get("annotatingElement") + .cloned() + .or_else(|| get("annotatingElement")) + .or_else(|| owner.clone()); + let target = get("annotatedElement") + .or_else(|| derived.get("annotatedElement").cloned()) + .into_iter() + .collect(); + (source.into_iter().collect(), target) } "Conjugation" | "PortConjugation" => { + let source = get("conjugatedType").or_else(|| owner.clone()); let target = get("originalType").into_iter().collect(); - (owner.clone().into_iter().collect(), target) + (source.into_iter().collect(), target) } "Disjoining" => { - let source = get("typeDisjoined").or(owner.clone()); + let source = get("typeDisjoined").or_else(|| owner.clone()); let target = get("disjoiningType"); (source.into_iter().collect(), target.into_iter().collect()) } "FeatureInverting" => { - let source = get("featureInverted").or(owner.clone()); + let source = get("featureInverted").or_else(|| owner.clone()); let target = get("invertingFeature"); (source.into_iter().collect(), target.into_iter().collect()) } "TypeFeaturing" => { - let source = get("featureOfType").or(owner.clone()); + let source = get("featureOfType").or_else(|| owner.clone()); let target = get("featuringType"); (source.into_iter().collect(), target.into_iter().collect()) } @@ -1915,105 +2533,53 @@ fn fill_relationship_endpoints( .or_else(|| owned.first().cloned()) .into_iter() .collect(); - (owner.clone().into_iter().collect(), target) + (owner.into_iter().collect(), target) } _ => return, // not a relationship } }; - let mut related: Vec = source.clone(); - related.extend(target.clone()); + if !projected { + let mut related: Vec = source.clone(); + related.extend(target.clone()); + derived.insert("relatedElement".into(), Value::Array(related)); + } derived.insert("source".into(), Value::Array(source)); derived.insert("target".into(), Value::Array(target)); - derived.insert("relatedElement".into(), Value::Array(related)); } -/// Materialize implied specializations per SysML 8.4.2 Tables 31/32: every -/// definition/usage kind implicitly specializes its library base unless an -/// explicit specialization of the covering kind is present -/// (anti-redundancy, approximated as "any explicit same-kind -/// specialization"). +/// Append the implied relationships the derivation layer holds for every +/// projected element (SysML 8.4.2 Tables 31/32 library specializations and +/// the variant specializations): one array element each, listed under +/// the owner's `ownedRelationship`, with the owned properties the layer +/// spells (`isImplied`, the two ends) and the structure the full form +/// expects of a relationship owned directly by its specific side. fn add_implied_relationships( elements: &mut Vec>, - lib_by_name: &HashMap, + resolved: &mut crate::json::ResolvedModel, ) { let mut additions: Vec<(usize, Map)> = Vec::new(); for (i, el) in elements.iter().enumerate() { - let t = ty(el).to_string(); let own_id = eid(el); - let rel_types: Vec = el - .get("ownedRelationship") - .and_then(|v| v.as_array()) - .map(|a| { - a.iter() - .filter_map(|r| r.get("@id").and_then(|x| x.as_str())) - .map(|s| s.to_string()) - .collect() - }) - .unwrap_or_default(); - let _ = rel_types; - - let (bases, rel_ty, src_key, tgt_key, covering): (&[&str], &str, &str, &str, &[&str]) = - if let Some(kind) = def_kind_of(&t) { - ( - implicit_def_bases(kind), - "Subclassification", - "subclassifier", - "superclassifier", - &["Subclassification", "Specialization"], - ) - } else if let Some(kind) = usage_kind_of(&t, Dialect::Sysml) { - ( - implicit_usage_bases(kind), - "Subsetting", - "subsettingFeature", - "subsettedFeature", - &["Subsetting", "Redefinition", "ReferenceSubsetting"], - ) - } else { - continue; - }; - if bases.is_empty() { - continue; - } - // Anti-redundancy: skip when an explicit covering specialization - // exists (its general transitively reaches the implied base through - // its own implied relationships). - let ids: Vec = el - .get("ownedRelationship") - .and_then(|v| v.as_array()) - .map(|a| a.iter().filter_map(ref_of).collect()) - .unwrap_or_default(); - let has_covering = ids.iter().any(|rid| { - elements - .iter() - .find(|e| eid(e) == *rid) - .map(|r| covering.contains(&ty(r))) - .unwrap_or(false) - }); - if has_covering { + let t = ty(el); + // Same id *and* same metaclass, as the projection requires. + let Some(e) = resolved + .element_by_id(own_id) + .filter(|&e| resolved.element_type(e) == t) + else { continue; - } - for (n, base) in bases.iter().enumerate() { - let Some(base_id) = lib_by_name.get(*base) else { - continue; - }; - let rel_id = Uuid::new_v5( - &Uuid::NAMESPACE_OID, - format!("{own_id}/implied{n}").as_bytes(), - ) - .to_string(); + }; + for r in resolved.implied_relationships(e) { + let rel_id = resolved.element_id(r).to_string(); let mut rel = Map::new(); - rel.insert("@type".into(), json!(rel_ty)); + rel.insert("@type".into(), json!(resolved.element_type(r))); rel.insert("@id".into(), json!(rel_id)); rel.insert("elementId".into(), json!(rel_id)); - rel.insert("isImplied".into(), json!(true)); rel.insert("isImpliedIncluded".into(), json!(true)); rel.insert("ownedRelationship".into(), json!([])); rel.insert("ownedRelatedElement".into(), json!([])); - rel.insert("owningRelatedElement".into(), id_ref(&own_id)); + rel.insert("owningRelatedElement".into(), id_ref(own_id)); rel.insert("owningRelationship".into(), Value::Null); - rel.insert(src_key.into(), id_ref(&own_id)); - rel.insert(tgt_key.into(), id_ref(base_id)); + rel.extend(resolved.element_properties(r)); rel.insert("aliasIds".into(), json!([])); rel.insert("declaredName".into(), Value::Null); rel.insert("declaredShortName".into(), Value::Null); @@ -2021,10 +2587,43 @@ fn add_implied_relationships( } } for (owner_idx, rel) in additions { - let rel_id = eid(&rel); + let rel_ref = id_ref(eid(&rel)); if let Some(Value::Array(rels)) = elements[owner_idx].get_mut("ownedRelationship") { - rels.push(id_ref(&rel_id)); + rels.push(rel_ref); } elements.push(rel); } } + +#[cfg(test)] +mod tests { + use super::*; + + /// The generated property catalog is looked up by binary search, in + /// the metaclass table and in every property list. Regenerating the + /// tables in another order would make those searches miss silently — + /// properties would go missing from the exported form — so the order + /// is asserted here rather than assumed. + #[test] + fn the_property_catalog_is_sorted_for_lookup() { + assert!( + METACLASS_PROPS.windows(2).all(|w| w[0].0 < w[1].0), + "the metaclass table must be sorted by name" + ); + for (metaclass, props) in METACLASS_PROPS { + assert!( + props.windows(2).all(|w| w[0].0 < w[1].0), + "{metaclass}'s property list must be sorted by name" + ); + for (name, _) in *props { + assert_eq!( + metaclass_props(metaclass).and_then(|p| p + .binary_search_by_key(name, |(n, _)| n) + .ok() + .map(|i| p[i].0)), + Some(*name) + ); + } + } + } +} diff --git a/crates/sysmlv2-model/src/ids.rs b/crates/sysmlv2-model/src/ids.rs index e4ee14e..293fa07 100644 --- a/crates/sysmlv2-model/src/ids.rs +++ b/crates/sysmlv2-model/src/ids.rs @@ -23,6 +23,55 @@ use std::collections::{HashMap, HashSet}; use sysmlv2_syntax::ast::escape_name; use uuid::Uuid; +/// Why a derivation could not run over a payload. A caller distinguishes +/// a malformed payload (every variant but the last) from a payload that +/// is well formed but does not carry enough identity to complete an +/// assignment ([`IdError::NoIdentity`], reachable only from +/// [`assign_ids`]). +/// +/// Non-exhaustive: the derivation may come to distinguish further +/// malformed shapes, and naming one is not a breaking change. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum IdError { + /// The payload is not a flat array of elements. + NotAnElementArray, + /// The element at this index is not a JSON object. + NotAnObject(usize), + /// The element at this index carries no string `@id`. + MissingId(usize), + /// The element at this index carries no string `@type`. + MissingType(usize), + /// An `@id` that is not a UUID, so nothing can chain from it. + InvalidId(String), + /// The element at this index has neither a derivable id nor an + /// exception entry naming it. + NoIdentity(usize), +} + +impl std::fmt::Display for IdError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + IdError::NotAnElementArray => f.write_str("compact payload is a flat element array"), + IdError::NotAnObject(i) => write!(f, "element {i} is an object"), + IdError::MissingId(i) => write!(f, "element {i} has a string @id"), + IdError::MissingType(i) => write!(f, "element {i} has a string @type"), + IdError::InvalidId(id) => write!(f, "invalid @id `{id}`"), + IdError::NoIdentity(i) => { + write!(f, "element {i}: no derivable id and no exception entry") + } + } + } +} + +impl std::error::Error for IdError {} + +impl From for String { + fn from(error: IdError) -> String { + error.to_string() + } +} + /// Per element of `compact` (payload order): the graph-derived id, or /// `None` where the scheme assigns rather than derives (document /// roots) or the element is unreachable from any root. `external_name` @@ -32,8 +81,8 @@ use uuid::Uuid; pub fn derive_ids( compact: &Value, external_name: &dyn Fn(&str) -> Option, -) -> Result>, String> { - Ok(walk(compact, external_name, None)?.0) +) -> Result>, IdError> { + Ok(walk(compact, external_name, None, Paths::Discard)?.0) } /// Per element of `compact` (payload order): the ownership path that @@ -46,8 +95,8 @@ pub fn derive_ids( pub fn segment_paths( compact: &Value, external_name: &dyn Fn(&str) -> Option, -) -> Result>, String> { - Ok(walk(compact, external_name, None)?.1) +) -> Result>, IdError> { + Ok(walk(compact, external_name, None, Paths::Keep)?.1) } /// Compute the **final** id of every element of a payload whose `@id` @@ -60,8 +109,8 @@ pub fn assign_ids( compact: &Value, exceptions: &HashMap, external_name: &dyn Fn(&str) -> Option, -) -> Result, String> { - let derived = walk(compact, external_name, Some(exceptions))?.0; +) -> Result, IdError> { + let derived = walk(compact, external_name, Some(exceptions), Paths::Discard)?.0; derived .into_iter() .enumerate() @@ -70,35 +119,80 @@ pub fn assign_ids( .get(&i) .copied() .or(d) - .ok_or_else(|| format!("element {i}: no derivable id and no exception entry")) + .ok_or(IdError::NoIdentity(i)) }) .collect() } -type Paths = Vec>; +type SegmentPaths = Vec>; + +/// Whether the walk materializes segment paths. Only [`segment_paths`] +/// reads them, and building one costs a string per element plus a copy +/// of the parent's whole path per step — an id derivation, which every +/// encoded payload runs, pays none of it. +#[derive(Clone, Copy, PartialEq, Eq)] +enum Paths { + Keep, + Discard, +} + +/// The ownership paths built during a walk, when they are wanted. +struct Trail(Option); + +impl Trail { + fn new(n: usize, mode: Paths) -> Trail { + Trail((mode == Paths::Keep).then(|| vec![None; n])) + } + + /// A root's path: itself, and no segments. + fn seed(&mut self, root: usize) { + if let Some(paths) = self.0.as_mut() { + paths[root] = Some((root, String::new())); + } + } + + /// `child`'s path is `parent`'s extended by `seg`. A parent with no + /// path (unreachable from any root) gives its children none either. + fn extend(&mut self, child: usize, parent: usize, seg: &str) { + let Some(paths) = self.0.as_mut() else { return }; + let Some((root, parent_path)) = &paths[parent] else { + return; + }; + let (root, path) = ( + *root, + if parent_path.is_empty() { + seg.to_owned() + } else { + format!("{parent_path}/{seg}") + }, + ); + paths[child] = Some((root, path)); + } + + fn finish(self, n: usize) -> SegmentPaths { + self.0.unwrap_or_else(|| vec![None; n]) + } +} fn walk( compact: &Value, external_name: &dyn Fn(&str) -> Option, finals: Option<&HashMap>, -) -> Result<(Vec>, Paths), String> { - let elems = compact - .as_array() - .ok_or_else(|| "compact payload is a flat element array".to_string())?; + keep_paths: Paths, +) -> Result<(Vec>, SegmentPaths), IdError> { + let elems = compact.as_array().ok_or(IdError::NotAnElementArray)?; let n = elems.len(); let obj = |i: usize| elems[i].as_object().expect("checked below"); let mut index: HashMap<&str, usize> = HashMap::with_capacity(n); for (i, e) in elems.iter().enumerate() { - let o = e - .as_object() - .ok_or_else(|| format!("element {i} is an object"))?; + let o = e.as_object().ok_or(IdError::NotAnObject(i))?; let id = o .get("@id") .and_then(Value::as_str) - .ok_or_else(|| format!("element {i} has a string @id"))?; + .ok_or(IdError::MissingId(i))?; o.get("@type") .and_then(Value::as_str) - .ok_or_else(|| format!("element {i} has a string @type"))?; + .ok_or(IdError::MissingType(i))?; index.insert(id, i); } let ty = |i: usize| obj(i).get("@type").and_then(Value::as_str).unwrap_or(""); @@ -114,8 +208,16 @@ fn walk( _ => Vec::new(), } }; + // Both ownership lists, resolved once: the name fixpoint below reads + // the relationship list of every element on every pass, and the walk + // reads both again. + let owned_rels: Vec> = (0..n).map(|i| targets(i, "ownedRelationship")).collect(); + let owned_elems: Vec> = (0..n).map(|i| targets(i, "ownedRelatedElement")).collect(); - // Names: declared, else the graph-effective fixpoint. + // Names: declared, else the graph-effective fixpoint. This is the + // id-segment reading of the one naming rule — see + // `full::effective_name_of` for the rule and its other + // implementations; a change to one belongs in all of them. let declared = |i: usize| -> Option { let o = obj(i); o.get("declaredName") @@ -125,7 +227,7 @@ fn walk( }; let mut names: Vec> = (0..n).map(declared).collect(); let effective = |i: usize, names: &[Option]| -> Option { - for r in targets(i, "ownedRelationship") { + for &r in &owned_rels[i] { let key = match ty(r) { "Redefinition" => "redefinedFeature", "ReferenceSubsetting" => "referencedFeature", @@ -162,10 +264,10 @@ fn walk( // Roots: elements owned by nothing in the payload. let mut owned: vec::BitSet = vec::BitSet::new(n); for i in 0..n { - for r in targets(i, "ownedRelationship") { + for &r in &owned_rels[i] { owned.set(r); } - for k in targets(i, "ownedRelatedElement") { + for &k in &owned_elems[i] { owned.set(k); } } @@ -175,29 +277,24 @@ fn walk( // (`derive_ids` — divergence must not cascade), the parent's // computed/exception id when assigning (`assign_ids` — the payload // carries placeholders). - let final_of = |k: usize, derived: &Vec>| -> Result { + let final_of = |k: usize, derived: &Vec>| -> Result { match finals { Some(exceptions) => exceptions .get(&k) .copied() .or(derived[k]) - .ok_or_else(|| format!("element {k}: no derivable id and no exception entry")), - None => Uuid::parse_str(id_str(k)).map_err(|_| format!("invalid @id `{}`", id_str(k))), + .ok_or(IdError::NoIdentity(k)), + None => { + Uuid::parse_str(id_str(k)).map_err(|_| IdError::InvalidId(id_str(k).to_string())) + } } }; - let mut paths: Paths = vec![None; n]; + let mut paths = Trail::new(n, keep_paths); let mut stack: Vec = (0..n).filter(|&i| !owned.get(i)).collect(); for &root in &stack { - paths[root] = Some((root, String::new())); + paths.seed(root); } let mut visited = vec::BitSet::new(n); - let join = |p: &str, seg: &str| { - if p.is_empty() { - seg.to_owned() - } else { - format!("{p}/{seg}") - } - }; while let Some(owner) = stack.pop() { if visited.get(owner) { continue; @@ -205,8 +302,8 @@ fn walk( visited.set(owner); let owner_ns = final_of(owner, &derived)?; let mut used: HashSet = HashSet::new(); - for (i, rel) in targets(owner, "ownedRelationship").into_iter().enumerate() { - let kids = targets(rel, "ownedRelatedElement"); + for (i, &rel) in owned_rels[owner].iter().enumerate() { + let kids = &owned_elems[rel]; let membership = ty(rel).ends_with("Membership"); // A single-member membership whose member has an id-name // chains **past the membership**: the member @@ -221,15 +318,11 @@ fn walk( if used.insert(named.clone()) { let kid = kids[0]; derived[kid] = Some(Uuid::new_v5(&owner_ns, named.as_bytes())); - if let Some((root, p)) = paths[owner].clone() { - paths[kid] = Some((root, join(&p, &named))); - } + paths.extend(kid, owner, &named); stack.push(kid); let kid_ns = final_of(kid, &derived)?; derived[rel] = Some(Uuid::new_v5(&kid_ns, b"m")); - if let Some((root, p)) = paths[kid].clone() { - paths[rel] = Some((root, join(&p, "m"))); - } + paths.extend(rel, kid, "m"); stack.push(rel); continue; } @@ -250,15 +343,13 @@ fn walk( } } derived[rel] = Some(Uuid::new_v5(&owner_ns, seg.as_bytes())); - if let Some((root, p)) = paths[owner].clone() { - paths[rel] = Some((root, join(&p, &seg))); - } + paths.extend(rel, owner, &seg); // A relationship can own relationships of its own // (annotations, filters) — it is an owner in its own right. stack.push(rel); let rel_ns = final_of(rel, &derived)?; let mut kid_used: HashSet = HashSet::new(); - for (j, kid) in kids.into_iter().enumerate() { + for (j, &kid) in kids.iter().enumerate() { let mut kseg = format!("e{j}"); if membership { if let Some(name) = &names[kid] { @@ -269,14 +360,12 @@ fn walk( } } derived[kid] = Some(Uuid::new_v5(&rel_ns, kseg.as_bytes())); - if let Some((root, p)) = &paths[rel] { - paths[kid] = Some((*root, format!("{p}/{kseg}"))); - } + paths.extend(kid, rel, &kseg); stack.push(kid); } } } - Ok((derived, paths)) + Ok((derived, paths.finish(n))) } /// Tiny fixed-size bit set (no dependency). diff --git a/crates/sysmlv2-model/src/json.rs b/crates/sysmlv2-model/src/json.rs index 5d583e0..af0860f 100644 --- a/crates/sysmlv2-model/src/json.rs +++ b/crates/sysmlv2-model/src/json.rs @@ -17,8 +17,32 @@ //! until multi-file/library resolution lands (which replaces these with the //! normative UUIDv5 library IDs). +mod behavior; +mod cases; +mod closures; +mod derived; +mod derived_compositions; +mod implied; +mod naming; +mod scope_table; +mod typeops; +pub use closures::{CLOSURE_NAMES, ClosurePolicy}; +pub use derived::dangling_id; +pub use derived::{ + CatalogEntry, Derived, DerivedValue, Derives, PropertyShape, Reference, computed_names, + derives, derives_under, is_owned_property, metaclass_conforms, property_catalog, +}; + use serde_json::{Map, Value, json}; use std::collections::{HashMap, HashSet}; +use std::sync::Arc; + +/// Recursion budget shared by name lookup and the import, heritage and +/// semantic-metadata walks: a chain deeper than this is treated as a +/// cycle and cut. Inherited-member enumeration reports reaching it +/// through [`InheritedBindings::truncated`]; lookup stays silent, as a +/// missing name is already a diagnostic. +pub(crate) const MAX_RESOLUTION_DEPTH: usize = 24; use sysmlv2_syntax::ast::*; use sysmlv2_syntax::span::Span; use uuid::Uuid; @@ -41,9 +65,9 @@ pub fn library_name_map(model: &crate::model::Model) -> HashMap HashMap= boundary) - .map(|&(start, orig)| (start - boundary, model.units()[orig].name.clone())) + .map(|&(start, orig)| (start - boundary, model.unit_meta(orig).0.to_owned())) .collect(); (b.finish(boundary), units) } @@ -115,7 +139,7 @@ pub fn library_to_compact_json_with_units( .unit_starts .iter() .filter(|&&(start, _)| start < boundary) - .map(|&(start, orig)| (start, model.units()[orig].name.clone())) + .map(|&(start, orig)| (start, model.unit_meta(orig).0.to_owned())) .collect(); (b.finish_range(0, boundary), units) } @@ -167,7 +191,9 @@ pub fn library_resolver_artifact( ) }) .collect(); - let units = model.units().iter().filter(|u| u.is_library).count(); + let units = (0..model.unit_count()) + .filter(|&i| model.is_library_unit(i)) + .count(); serde_json::json!({ "format": "sysmlv2-stdlib-resolver", "formatVersion": 1, @@ -183,6 +209,11 @@ pub fn library_resolver_artifact( } /// Convenience: pretty-printed JSON text. +/// +/// # Panics +/// +/// Never in practice: the compact form is built from owned values that +/// always serialize. pub fn to_compact_json_string(unit: &SourceUnit) -> String { serde_json::to_string_pretty(&to_compact_json(unit)).expect("JSON serialization cannot fail") } @@ -203,6 +234,63 @@ pub struct ResolutionReport { /// Namespace imports whose target transitively imports the importing /// namespace back (including direct self-imports). pub import_cycles: Vec<(usize, QualifiedName)>, + /// User root memberships whose name is also a standard-library root + /// name — see [`RootShadowing`]. + pub shadowed_roots: Vec, + /// Unresolved references whose name does exist in the searched scope + /// under a visibility the reference cannot see — see + /// [`BlockedReference`]. + pub blocked: Vec, +} + +/// An unresolved reference that names a member the resolver found only +/// by ignoring visibility: widening that member's visibility would let +/// the reference resolve. Produced for chain steps (`c.maxTime` where +/// `maxTime` is a private member of `c`'s type), qualified names +/// (`T::m`) and redefinitions of inherited private members. +#[derive(Clone, Debug)] +pub struct BlockedReference { + /// Index into [`crate::model::Model::units`] of the reference. + pub unit: usize, + /// The reference as written — for a chain step, the member segment + /// only (its span is the diagnostic's). + pub name: QualifiedName, + /// The whole spelling as written, chain links included + /// (`c.maxTime`), for messages. + pub spelling: String, + /// The member a wider visibility would expose. + pub member: ElementRef, + /// The member's declared visibility (`private` or `protected`). + pub visibility: &'static str, + /// Making the member `protected` would already let the reference + /// resolve: it reaches the member through a specialization of the + /// owning type. Always false for a `protected` member. + pub protected_suffices: bool, +} + +/// A root membership of a user unit whose name collides with a root +/// membership of a library unit (`package Requirements {}` next to the +/// standard `Requirements` library). Root lookups keep their existing +/// behavior — the library declaration wins (or, for same-kind +/// declarations, the name is ambiguous) — so every qualified reference +/// through the name silently bypasses the user declaration; this record +/// is the resolution-time evidence the referential check reports. +#[derive(Clone, Debug)] +pub struct RootShadowing { + /// Index into [`crate::model::Model::units`] of the user declaration. + pub unit: usize, + /// Span of the user declaration's name (the member span when the + /// declaration is unnamed on the colliding side). + pub span: Span, + /// The colliding name as it appears in the root namespace. + pub name: String, + /// Metaclass of the user declaration (`Package`, `PartDefinition`, …). + pub metaclass: &'static str, + /// Metaclass of the library declaration the name reaches at the root. + pub library_metaclass: &'static str, + /// `true` when a root lookup of the name lands on the library + /// declaration; `false` when it is ambiguous between the two. + pub resolves_to_library: bool, } /// Resolve a model and report referential findings instead of JSON. @@ -212,31 +300,35 @@ pub struct ResolutionReport { /// cache was recorded in. Conservative: any identification on a top-level /// package, definition, usage, or alias counts. fn top_level_shadowing(model: &crate::model::Model) -> bool { - use std::collections::HashSet; - use sysmlv2_syntax::ast::MemberKind; - let names_of = |lib: bool| -> HashSet { - let mut names = HashSet::new(); - for mu in model.units().iter().filter(|u| u.is_library == lib) { - for m in &mu.unit.members { - let id = match &m.kind { - MemberKind::Package(p) => &p.id, - MemberKind::Definition(d) => &d.id, - MemberKind::Usage(u) => &u.declaration.id, - MemberKind::Alias(a) => &a.id, - _ => continue, - }; - for n in [&id.name, &id.short_name].into_iter().flatten() { - names.insert(n.value.clone()); - } + let user = top_level_names(model.user_units().map(|(_, u)| u)); + if let Some(library) = &model.prepared { + !user.is_disjoint(&library.root_names) + } else { + !user.is_disjoint(&top_level_names( + model.units().iter().filter(|u| u.is_library), + )) + } +} + +pub(crate) fn top_level_names<'a>( + units: impl Iterator, +) -> HashSet { + let mut names = HashSet::new(); + for mu in units { + for m in &mu.unit.members { + let id = match &m.kind { + MemberKind::Package(p) => &p.id, + MemberKind::Definition(d) => &d.id, + MemberKind::Usage(u) => &u.declaration.id, + MemberKind::Alias(a) => &a.id, + _ => continue, + }; + for n in [&id.name, &id.short_name].into_iter().flatten() { + names.insert(n.value.clone()); } } - names - }; - let lib = names_of(true); - if lib.is_empty() { - return false; } - !lib.is_disjoint(&names_of(false)) + names } pub fn model_resolution_report(model: &crate::model::Model) -> ResolutionReport { @@ -245,96 +337,327 @@ pub fn model_resolution_report(model: &crate::model::Model) -> ResolutionReport resolution_report_from(&mut b) } -/// [`model_resolution_report`] over an already-built graph (drains the -/// builder's unresolved list). +/// [`model_resolution_report`] over an already-built graph (the +/// builder's lists stay in place). pub(crate) fn resolution_report_from(b: &mut Builder) -> ResolutionReport { - let unresolved = std::mem::take(&mut b.unresolved) - .into_iter() - .map(|(elem, qn)| (b.unit_of_elem(elem), qn)) + // Reported, not drained: `unresolved_references` and the lint rules + // read the same lists after the report has been taken. + let unresolved = b + .unresolved + .iter() + .map(|(elem, qn)| (b.unit_of_elem(*elem), qn.clone())) .collect(); - let ambiguous = std::mem::take(&mut b.ambiguous) - .into_iter() - .map(|(elem, qn)| (b.unit_of_elem(elem), qn)) + let ambiguous = b + .ambiguous + .iter() + .map(|(elem, qn)| (b.unit_of_elem(*elem), qn.clone())) + .collect(); + let blocked = b + .blocked + .iter() + .map(|site| BlockedReference { + unit: b.unit_of_elem(site.owner), + name: site.name.clone(), + spelling: site.spelling.clone(), + member: ElementRef(site.member), + visibility: site.visibility, + protected_suffices: site.protected_suffices, + }) .collect(); ResolutionReport { unresolved, ambiguous, unresolved_aliases: b.check_aliases(), import_cycles: b.check_import_cycles(), + shadowed_roots: b.check_root_shadowing(), + blocked, } } +/// Statements and control-flow edges require execution, even when their +/// enclosing calculation also has an ordinary return-value expression. +pub(crate) fn member_requires_execution(member: &Member) -> bool { + member.leading_then + || matches!(member.kind, MemberKind::InitialNode(_)) + || matches!(&member.kind, MemberKind::Usage(u) if matches!(u.kind, + UsageKind::Action | UsageKind::Perform | UsageKind::Succession + | UsageKind::SuccessionFlow | UsageKind::Accept | UsageKind::Send + | UsageKind::Assign | UsageKind::Terminate | UsageKind::IfNode + | UsageKind::WhileLoop | UsageKind::ForLoop | UsageKind::Merge + | UsageKind::Decide | UsageKind::Join | UsageKind::Fork | UsageKind::Step)) +} + /// Fixed UUIDv5 namespace for this library's deterministic element IDs. -fn id_namespace() -> Uuid { +/// Derived once: every created element and relationship hashes its path +/// against it, and the derivation is a SHA-1 in its own right. +static ID_NAMESPACE: std::sync::LazyLock = std::sync::LazyLock::new(|| { Uuid::new_v5( &Uuid::NAMESPACE_URL, b"https://crates.io/crates/sysmlv2-parser", ) +}); + +#[cfg(test)] +mod id_namespace_test { + /// Element identities are derived from this namespace, so it is part + /// of the interchange contract and may not drift. + #[test] + fn the_identity_namespace_is_pinned() { + assert_eq!( + super::ID_NAMESPACE.to_string(), + "6e8a6e90-78ac-5309-8f3b-3151fa7a09e1" + ); + } +} + +/// One import declared in a user unit: its relationship element, the +/// member's span (where a visibility keyword goes), the importing scope +/// and the visibility as written. +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] +pub(crate) struct UserImport { + pub(crate) rel: usize, + pub(crate) span: Span, + pub(crate) scope: usize, + pub(crate) visibility: Option, +} + +/// The access a lookup walked an import under — what the resolver +/// checked against the import's visibility at that moment. Ordered from +/// most to least restrictive. +#[derive( + Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, serde::Serialize, serde::Deserialize, +)] +pub enum AccessMode { + /// Reached from outside the importing namespace: only a public + /// import serves. + Public, + /// Reached through a specialization of the importing type: a + /// protected import serves. + Protected, + /// Walked with full access — lexically from inside the importing + /// namespace, through an `import all`, or as the last segment of an + /// alias or import target: any visibility serves. + Any, +} + +/// The visibility an import's dependents require — see +/// [`ResolvedModel::import_visibility_advice`]. +#[derive(Clone, Debug)] +pub struct ImportVisibilityAdvice { + /// The import relationship. + pub import: ElementRef, + /// Unit and member span of the import declaration (a visibility + /// keyword goes at the span's start). + pub unit: usize, + pub span: Span, + /// The keyword as written, if any. + pub declared: Option<&'static str>, + /// `private`, `protected` or `public`. + pub recommended: &'static str, + /// Reference sites that walked the import under a restricted access + /// (from outside the importing namespace, or through a + /// specialization of it) — the ones a `private` keyword would break + /// — as (unit, span). + pub outside_sites: Vec<(usize, Span)>, + /// Qualified name of the importing namespace, for messages. + pub namespace: Option, +} + +/// Import relationships a resolution walked through, each with the +/// access the walk ran under. +pub(crate) type ImportWalks = Vec<(usize, LookupAccess)>; + +/// A recorded visibility-blocked miss — see [`BlockedReference`]. +#[derive(Clone, Debug)] +pub(crate) struct BlockedSite { + pub(crate) owner: usize, + pub(crate) name: QualifiedName, + pub(crate) spelling: String, + pub(crate) member: usize, + pub(crate) visibility: &'static str, + pub(crate) protected_suffices: bool, +} + +/// One enumeration outcome ([`Builder::inherited_bindings`]): the +/// `(member element, contributing scope)` pairs, the inherited alias +/// Membership relationships, and whether a depth guard cut the walk short. +#[derive(Clone, Default)] +pub(crate) struct InheritedBindings { + pub(crate) members: Vec<(usize, usize)>, + pub(crate) alias_rels: Vec, + /// A heritage or import chain reached [`MAX_RESOLUTION_DEPTH`], so + /// members beyond it are missing from `members`. + pub(crate) truncated: bool, + /// `(dropped, shadowing)` pairs removed by the SysML implicit + /// same-name usage redefinition (condition (c) of the removal pass): + /// `dropped` is the inherited member a same-named usage-family member + /// `shadowing` (owned by the enumerated scope, or inherited from a + /// nearer base) hides without a spelled `:>>`. Lookup treats the pair + /// as a redefinition; the namespace-distinguishability check reads it + /// as the collision the normative rule reports. + pub(crate) implicit_redefinitions: Vec<(usize, usize)>, +} + +/// Replace an id-spelled `@ref` placeholder atom (or any nested in an +/// array) with a reference to that id. +fn bind_atom(atom: &mut crate::properties::Atom, bound: &mut HashSet) { + use crate::properties::Atom; + match atom { + Atom::Array(items) => items.iter_mut().for_each(|a| bind_atom(a, bound)), + Atom::Object(_) => { + let spelled = atom + .get("@ref") + .and_then(|v| v.as_str()) + .map(str::to_string); + let Some(spelled) = spelled else { + return; + }; + // The lift quotes the id; the spelling may carry the quotes. + let Ok(id) = Uuid::parse_str(spelled.trim_matches('\'')) else { + return; + }; + *atom = Atom::from_json(json!({ "@id": id.to_string() })); + bound.insert(id); + } + _ => {} + } } -#[derive(Default)] +/// A visit of the import walk ([`Builder::collect_import_scope`]): the +/// scope, the access it was entered at, whether the visit descends +/// recursively (`::**`), and the filter chain that applied. Recursion is +/// part of the key because a plain `Q::*` visit must not stand in for a +/// later `::**` one that also descends into `Q`'s members. +type ImportVisit = (usize, u8, bool, Vec<(usize, usize)>); + +#[derive(Clone, Default, serde::Serialize, serde::Deserialize)] pub(crate) struct Builder { dialect: Dialect, + pub(crate) semantic_memo: crate::semantic_memo::SemanticMemo, + #[serde(skip)] + pub(crate) semantic_ready: bool, + /// Immutable library facts; never retain facts about user additions. + #[serde(skip)] + pub(crate) library_facts: Option>, + /// Names that found no binding in the root scope while this library was + /// prepared. Only these lookups can change when a model adds root + /// declarations or root-level imports; root hits are owned members, + /// which take precedence over anything a later import contributes. + pub(crate) root_misses: HashSet, /// Flat element list in ownership (depth-first) order. - pub(crate) elements: Vec, - scopes: Vec, + #[serde(with = "element_table")] + pub(crate) elements: crate::layered::LayeredVec, + #[serde(with = "scope_table")] + scopes: crate::layered::LayeredVec, /// Element index → its body scope (for namespace-owning elements). - pub(crate) elem_scope: HashMap, + pub(crate) elem_scope: crate::layered::LayeredMap, /// Per-scope cache of resolved namespace-import target scopes (with the /// recursive flag and the import's bracket-filter indices). + #[serde(skip)] import_cache: Vec>>, /// Import relationships a lookup actually resolved a name through /// (admitted hits only) — the unused-import check's evidence. pub(crate) used_imports: HashSet, + /// Import relationships the resolution in progress walked through, + /// each with the access the walk ran under; cleared per user + /// reference and recorded on its [`RefSite`]. + #[serde(skip)] + pub(crate) query_imports: ImportWalks, + /// Unresolved user references that name a member visible only + /// under a wider visibility. Kept beside `unresolved`, which the + /// report copies; this list is read by `blocked_references`. + #[serde(skip)] + pub(crate) blocked: Vec, + /// A visibility-blind probe is running: every lookup admits every + /// membership and no import use is recorded. + #[serde(skip)] + probing: bool, + /// One member admitted as if it had the given visibility, for + /// checking that widening it would let a reference resolve. + #[serde(skip)] + widen: Option<(usize, LookupAccess)>, /// Every textual `import` member lowered from a source unit: /// (relationship element, whole-member span, spelled `private`). - pub(crate) user_imports: Vec<(usize, Span, bool)>, + pub(crate) user_imports: Vec, /// Per-scope cache of resolved specialization-base scopes. - base_cache: Vec>>, + #[serde(skip)] + base_cache: Vec, usize)>>, + /// Per-(scope, include_implied) memo of the inherited-member + /// enumeration ([`Self::inherited_bindings`]), cleared with the + /// other lookup caches. Shared, so a hit costs a pointer copy. + #[serde(skip)] + inherited_cache: HashMap<(usize, bool), Arc>, + /// The same memo keyed by heritage for scopes that own nothing (a + /// bodiless usage or definition): their enumeration is a function of + /// their base scopes alone, and a large model has thousands of such + /// scopes over a few hundred distinct heritages. + #[serde(skip)] + inherited_by_heritage: HashMap<(Vec, bool), Arc>, /// Per-scope visit marks and outcomes for the current name query /// ([`Self::lookup`]). `None` under the active stamp means the scope is /// currently being evaluated (a cyclic re-entry is a miss); `Some` /// memoizes the completed result so multiple import paths can apply /// their own filters without re-walking the graph. + #[serde(skip)] visit_stamp: Vec<[u64; 3]>, + #[serde(skip)] visit_result: Vec<[Option; 3]>, /// The active lookup query number (one per (start scope, name) chase). + #[serde(skip)] query_stamp: u64, /// Per-import-entry resolution outcomes, keyed by (importing scope, /// target spelling): the element each namespace-import entry resolved /// to during [`Self::import_scopes`], consumed when the entry's own /// `importedNamespace` pending serializes so the reference and the /// resolution machinery can never disagree. - import_targets: HashMap<(usize, String), Option>, + #[serde(skip)] + /// Resolved target of each namespace import per scope, with the + /// import walks its own resolution took (attributed to the import's + /// reference site, not to whichever lookup first filled the cache). + import_targets: HashMap<(usize, String), (Option, ImportWalks)>, /// Library element IDs → qualified-name segments (collected while /// assigning normative IDs). - lib_qnames: Vec<(Uuid, Vec)>, + lib_qnames: crate::layered::LayeredVec<(Uuid, Vec)>, /// Library *membership* IDs (`…/owningMembership`, alias Memberships) → /// the member's qualified-name segments. Kept separate from /// [`Self::lib_qnames`] so name→id inversions (full-form implied /// relationships) never collide with the member element; merged into /// [`library_name_map`] for lift, which names import targets by id. - lib_mem_qnames: Vec<(Uuid, Vec)>, + lib_mem_qnames: crate::layered::LayeredVec<(Uuid, Vec)>, /// Syntactic effective names of unnamed features (KerML 8.2.3.5 — the /// last segment of the first redefined/referenced feature's spelling), /// recorded at lowering time so `assign_library_ids` can give /// effective-named library members their normative qualified-name IDs /// (`ShapeItems::PlanarSurface::shape`) before resolution runs. - effective_hint: HashMap, + effective_hint: crate::layered::LayeredMap, /// Unresolved references to patch after all scopes exist. A property key /// of the form `base#n` appends to the array property `base`. pending: Vec, /// Library-cache replay: recorded outcomes for library-origin pending /// refs, consumed positionally by `resolve_pending` (see /// [`crate::libcache`]). - lib_hints: Option>>, - /// Sealed-snapshot replay: final library element ids consumed - /// positionally at element creation, skipping ownership-path - /// construction and UUIDv5 hashing for the whole library prefix. - lib_ids_in: Option>, + #[serde(skip)] + lib_hints: Option, Vec)>>, + /// Root names the user units of the model being built introduce, from + /// declarations, inferred names and root imports; `None` when a root + /// construct's contribution needs the resolver. Replay skips every + /// recorded outcome whose root misses intersect this set. + #[serde(skip)] + replay_completions: Option>, + /// Root misses seen while resolving the current pending reference. + #[serde(skip)] + current_misses: Vec, + /// Sealed-snapshot replay: the cache whose final library element ids + /// are consumed positionally at element creation — skipping + /// ownership-path construction and UUIDv5 hashing for the whole + /// library prefix — with the count already taken. The ids are read + /// where they lie rather than copied out of the cache. + #[serde(skip)] + lib_ids_in: Option<(Arc, usize)>, /// Library-cache recording: outcomes of library-origin pending refs, /// collected during `resolve_pending`. - lib_record: Option>>, + #[serde(skip)] + lib_record: Option, Vec)>>, /// Element that must not be a resolution result right now: while a /// scope's specialization-base names resolve, its own element is /// excluded so an unnamed feature's effective name (taken from its @@ -352,29 +675,35 @@ pub(crate) struct Builder { pending_declared_only: bool, /// Feature-value expressions for the evaluator: element → (scope the /// expression resolves from, the syntax expression). - pub(crate) values: HashMap, + pub(crate) values: crate::layered::LayeredMap, /// Elements whose feature value is a `default` (KerML FeatureValue /// isDefault): a redefining feature with no value of its own inherits /// such an expression, re-evaluated in the redefining context. pub(crate) default_values: HashSet, + /// Static contracts for synthesized action parameters and trigger arguments. + /// Separate from feature values: these do not provide runtime bindings. + pub(crate) owned_cross_features: crate::layered::LayeredMap, + pub(crate) payload_flows: HashSet, + pub(crate) contract_exprs: crate::layered::LayeredMap, /// Multiplicities for semantic checks: (owning element, scope, clause). - pub(crate) multiplicities: Vec<(usize, usize, Multiplicity)>, + pub(crate) multiplicities: crate::layered::LayeredVec<(usize, usize, Multiplicity)>, /// Connector-family end features with reference targets, for the /// featuring-accessibility check: (connector, end feature, target span). - pub(crate) connector_ends: Vec<(usize, usize, Span)>, + pub(crate) connector_ends: crate::layered::LayeredVec<(usize, usize, Span)>, /// Chain-written subsetting targets (`part m :> a.b;`): (subsetting /// feature, scope the chain resolves from, chain links, span) — for /// the featuring-accessibility semantic check. - pub(crate) chain_subsettings: Vec<(usize, usize, Vec, Span)>, + pub(crate) chain_subsettings: + crate::layered::LayeredVec<(usize, usize, Vec, Span)>, /// Satisfaction claims (`satisfy R by x;`): the SatisfyRequirementUsage /// element, the scope it was written in, and the `by` target — the /// satisfied requirement itself rides the element's /// ReferenceSubsetting. Consumed by [`ResolvedModel::satisfactions`]. - pub(crate) satisfy_by: Vec<(usize, usize, TargetRef)>, + pub(crate) satisfy_by: crate::layered::LayeredVec<(usize, usize, TargetRef)>, /// Transition guard expressions, kept as syntax for diagram labels /// (the built element tree has no source text): transition element → /// (scope, expression). - pub(crate) transition_guards: HashMap, + pub(crate) transition_guards: crate::layered::LayeredMap, /// Resolved reference sites: every qualified name written in a /// *user* unit that resolved to an element, recorded as the pendings /// resolve. Library-internal sites are not recorded — the sealed @@ -386,35 +715,42 @@ pub(crate) struct Builder { /// Declared-name span per element (the primary name; the short name /// only when it is the sole identifier) — declaration sites for /// find-usages/rename. - pub(crate) decl_spans: HashMap, + pub(crate) decl_spans: crate::layered::LayeredMap, /// Full member source extent (keyword through body or terminator) per /// member element — the transformation SDK's remove/insert anchor. - pub(crate) member_spans: HashMap, + pub(crate) member_spans: crate::layered::LayeredMap, /// Explicit specialization targets for semantic checks: /// (owning element, relationship metaclass, scope, target as written). - pub(crate) spec_targets: Vec<(usize, &'static str, usize, QualifiedName)>, + #[serde(deserialize_with = "crate::prepared::specializations")] + pub(crate) spec_targets: + crate::layered::LayeredVec<(usize, &'static str, usize, QualifiedName)>, /// Resolution outcome per `spec_targets` index, recorded as the pending /// refs resolve — consumers (redefinition conformance) read the target /// here instead of re-resolving (`:>>` names self-hit and fall through /// to full import scans, ~0.2 ms each on import-heavy scopes). - pub(crate) spec_resolved: Vec>, + pub(crate) spec_resolved: crate::layered::LayeredVec>, /// `spec_targets` index the next created pending ref reports into. pending_spec_idx: Option, /// Trailing result expressions for constraint verdicts and calculation /// invocation: (owning element, scope the expression resolves from, /// expression). - pub(crate) result_exprs: Vec<(usize, usize, Expr)>, + pub(crate) result_exprs: crate::layered::LayeredVec<(usize, usize, Expr)>, + /// Calculation/function bodies containing executable statements. The + /// expression evaluator must not mistake their return expressions for + /// the result of executing the body. This is derived from source on + /// every build, including builds that replay a library cache. + pub(crate) executable_calculations: HashSet, /// Named `in`/`inout` parameters per owning element, in declaration /// order — the binding targets for user-defined calculation invocation. - pub(crate) in_params: HashMap>, + pub(crate) in_params: crate::layered::LayeredMap>, /// Every named usage member per owning element, in declaration order /// with its element index — the binding targets for `new T(…)` /// constructor evaluation (filtered to data usages at use). - pub(crate) ctor_fields: HashMap>, + pub(crate) ctor_fields: crate::layered::LayeredMap>, /// Return-parameter element per owning element — a calculation written /// `return x = expr;` yields its return parameter's bound value (the /// evaluator's fallback when there is no trailing result expression). - pub(crate) return_params: HashMap, + pub(crate) return_params: crate::layered::LayeredMap, /// Direct usage members of enum-definition bodies (enum literals) — /// identity-comparable values for the evaluator. (Fidelity gap: these /// still lower as ReferenceUsage/FeatureMembership instead of @@ -423,64 +759,87 @@ pub(crate) struct Builder { /// typing/specialization edges, shared by [`ResolvedModel:: /// explicit_supertypes`] and the evaluator's classification /// operators). + #[serde(skip)] pub(crate) spec_index: Option>>, /// Lazily built interchange-id → element index map (the inverse of /// id assignment) — resolves id-valued relationship properties like /// `referencedFeature` without a [`ResolvedModel`] at hand. Rebuilt /// when the element count moves (edit sessions append). + #[serde(skip)] id_index: Option>, + /// Element count `id_index` was built for (the map itself is shorter + /// than the element list when ids collide, which must not force a + /// rebuild per lookup). + #[serde(skip)] + id_index_built_for: usize, + /// Lazily built owning element → first [`Self::multiplicities`] row, + /// with the row count it was built from. The table is + /// library-inclusive, so the scan it replaces was proportional to + /// the library on every lookup. + #[serde(skip)] + mult_index: Option<(usize, HashMap)>, /// First non-library element index (libraries build first) — the /// `boundary` of [`Self::build_model`], kept for library-ownership /// tests. pub(crate) lib_boundary: usize, + /// Index of the first *implied* relationship the derivation layer + /// materialized past the explicit elements (`json/implied.rs`); + /// `None` until it did. Everything that iterates the element list as + /// the model's content stops at [`Self::explicit_len`]. + #[serde(skip)] + pub(crate) implied_from: Option, /// Set while building an enum definition's direct body members. in_enum_body: bool, /// Usage elements with an expected featuring type (owned by a Type via /// a FeatureMembership, or a variant of such a variation usage) — the /// pilot's `UsageUtil.hasFeaturingType`, which drives `isComposite` /// for SysML usages. - usage_featuring: HashMap, + usage_featuring: crate::layered::LayeredMap, /// Featuring flag for the usage element about to be created (set by /// `build_usage_with`/`build_usage_element_scoped`, read by /// `build_usage_element` immediately after — never across recursion). pending_featuring: bool, /// Membership-implied parameter direction for the usage element about /// to be created (same lifetime discipline as `pending_featuring`). + #[serde(skip)] pending_direction: Option<&'static str>, /// Metaclass of the owner of the usage element about to be created /// (same lifetime discipline) — drives the port-usage composite rule. + #[serde(skip)] pending_owner_ty: Option<&'static str>, /// Per-owner count of `prefixmeta{n}` segments handed out — prefix /// metadata and canonicalized bare `@M;` members share one sequence. - prefix_meta_next: HashMap, + prefix_meta_next: crate::layered::LayeredMap, /// (first element index, original unit index) per built unit, in build /// order — attributes elements back to their source unit. unit_starts: Vec<(usize, usize)>, /// (first scope index, original unit index) per built unit. scope_starts: Vec<(usize, usize)>, /// References that stayed unresolved: (element, name as written). - unresolved: Vec<(usize, QualifiedName)>, + pub(crate) unresolved: Vec<(usize, QualifiedName)>, /// References whose lookup found multiple same-precedence targets. ambiguous: Vec<(usize, QualifiedName)>, /// Import filter conditions — `filter expr;` members and bracketed /// `import P::*[expr]` filters: (scope the expression's names resolve /// from, the syntax expression). Applied by [`Self::lookup`] to every /// hit that arrives through an import (see [`Self::filter_verdict`]). - filter_exprs: Vec<(usize, Expr)>, + pub(crate) filter_exprs: crate::layered::LayeredVec<(usize, Expr)>, /// Per-filter re-entrancy guard: resolving a filter's own metaclass /// names may walk back through the filtered import; a re-entered /// filter answers *undecided* (member stays visible). + #[serde(skip)] filters_active: Vec, /// Direct metadata annotations per annotated element: `#M` prefix /// metadata and about-less body `@M;` / `metadata m : M;` members /// (`@M about x;` annotates `x`, not its owner — not recorded). - pub(crate) metadata_of: HashMap>, + pub(crate) metadata_of: crate::layered::LayeredMap>, /// Port definition element → its implicit ConjugatedPortDefinition /// (`~P` typings resolve through the original and substitute this). - conjugated_defs: HashMap, + conjugated_defs: crate::layered::LayeredMap, /// Memoized `Metaobjects::SemanticMetadata` element (`Some(None)` = /// resolved once, library absent — semantic-metadata implied bases /// stay inert). + #[serde(skip)] semantic_metadata: Option>, /// Membership-import entries currently resolving their own target — /// `(scope, index into member_imports)`. A membership import must not @@ -488,6 +847,7 @@ pub(crate) struct Builder { /// entry matches `vehicle` and would recurse to the depth guard, /// permanently caching an empty `import_scopes` for the scope on the /// way down). + #[serde(skip)] member_import_active: std::collections::HashSet<(usize, usize)>, } @@ -501,7 +861,7 @@ pub(crate) enum Tri { Unknown, } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] struct Binding { elem: usize, sub_scope: Option, @@ -512,8 +872,8 @@ struct Binding { /// Visibility admitted by a lookup. The ordering is intentional: /// public-only < public-or-protected < all memberships. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -enum LookupAccess { +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] +pub(crate) enum LookupAccess { Public = 0, Protected = 1, All = 2, @@ -532,7 +892,15 @@ impl LookupAccess { } } -#[derive(Clone, Copy, Debug, PartialEq, Eq)] +fn access_mode(access: LookupAccess) -> AccessMode { + match access { + LookupAccess::Public => AccessMode::Public, + LookupAccess::Protected => AccessMode::Protected, + LookupAccess::All => AccessMode::Any, + } +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] enum LookupResult { Missing, Found(usize, Option), @@ -548,7 +916,7 @@ impl LookupResult { } } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] struct NamespaceImport { target: QualifiedName, recursive: bool, @@ -559,7 +927,7 @@ struct NamespaceImport { is_public: bool, } -#[derive(Clone, Debug)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] struct MemberImport { target: QualifiedName, is_import_all: bool, @@ -570,7 +938,7 @@ struct MemberImport { /// A scope made visible by a namespace import. `is_import_all` controls /// whether non-public memberships of the source namespace participate. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, serde::Serialize, serde::Deserialize)] struct ImportedScope { scope: usize, recursive: bool, @@ -581,6 +949,7 @@ struct ImportedScope { } /// A reference recorded for the post-pass, once all scopes exist. +#[derive(Clone, serde::Serialize, serde::Deserialize)] struct PendingRef { /// Element the resolved value is set on. elem: usize, @@ -613,17 +982,45 @@ struct PendingWork { record_pos: Option, } +#[derive(Clone, serde::Serialize)] pub(crate) struct Elem { pub(crate) ty: &'static str, id: Uuid, /// Ownership path used to derive `id` and children's ids. path: String, - pub(crate) props: Map, - pub(crate) owned_relationships: Vec, + pub(crate) props: crate::properties::Properties, + pub(crate) owned_relationships: crate::flat::Row, + pub(crate) children: crate::flat::Row, pub(crate) owning_relationship: Option, } -#[derive(Default)] +impl<'de> serde::Deserialize<'de> for Elem { + fn deserialize>(d: D) -> Result { + #[derive(serde::Deserialize)] + struct Wire { + ty: String, + id: Uuid, + path: String, + props: crate::properties::Properties, + owned_relationships: crate::flat::Row, + children: crate::flat::Row, + owning_relationship: Option, + } + let w = Wire::deserialize(d)?; + Ok(Self { + ty: crate::metaclass::canonical_name(&w.ty) + .ok_or_else(|| serde::de::Error::custom("unknown metaclass"))?, + id: w.id, + path: w.path, + props: w.props, + owned_relationships: w.owned_relationships, + children: w.children, + owning_relationship: w.owning_relationship, + }) + } +} + +#[derive(Clone, Default, serde::Serialize, serde::Deserialize)] struct Scope { parent: Option, /// The element whose body this scope is (for base-resolution @@ -633,11 +1030,17 @@ struct Scope { /// candidate is required both for ambiguity detection and KerML /// namespace distinguishability; insertion order must never choose a /// semantic target. - names: HashMap>, + #[serde(skip)] + names: scope_table::Names, /// Effective names of unnamed features (from their first referenced or /// redefined feature). Consulted after `names`, and skipped entirely for /// feature-chain steps (which do not resolve lexically). - effective_names: HashMap>, + #[serde(skip)] + effective_names: scope_table::Names, + /// Simple redefinition targets of this scope's owner. When resolving + /// one with that owner excluded, sibling inferred names in its parent + /// cannot establish the target they themselves are derived from. + redefinition_names: HashSet, /// Namespace imports (`P::*` / `P::*::**`) visible in this scope, with /// the recursive flag and the indices (into [`Builder::filter_exprs`]) /// of the import's own bracket filters (`import P::*[@Safety]`). @@ -659,10 +1062,19 @@ struct Scope { /// connected feature, so chain members (`source.x`) resolve through it. /// Lift names these ends positionally (`implied_end_name`) — the two /// must stay in sync or the round-trip gate trips. + #[serde(deserialize_with = "crate::prepared::implied_ends")] implied_ends: Vec<(&'static str, usize, usize)>, /// Specialization/typing targets of the element owning this scope — /// members of these resolve as inherited members. bases: Vec, + /// *Implied* heritage (resolution only, never emitted to JSON): the SysML + /// Tables 31/32 library bases of the owner's kind, the binary + /// connector/interface library base, and the implicit parameter + /// redefinition's own-name base. Split from [`Self::bases`] so + /// inherited-member enumeration can distinguish explicit heritage + /// from implied ([`Builder::base_scopes_split`]); lookup treats both + /// alike. + implied_bases: Vec, /// Specialization/typing targets written as feature chains — the /// chain's last link contributes inherited members exactly like a /// plain-name base (`part m :> a.b { attribute :>> x; }` finds `x` @@ -684,6 +1096,11 @@ impl Builder { /// Build all units of a model into one graph (library units first) and /// return the element index where non-library output starts. pub(crate) fn build_model(&mut self, model: &crate::model::Model) -> usize { + if let Some(library) = &model.prepared { + if !top_level_shadowing(model) && !library.builder.user_completes_library(model) { + return self.build_on_library(model, &library.builder); + } + } match self.build_model_inner(model, false) { Ok(boundary) => boundary, // Sealed-snapshot validation failed (a lowering change at the @@ -699,6 +1116,379 @@ impl Builder { } } + fn user_completes_library(&self, model: &crate::model::Model) -> bool { + // An unresolved library reference may become resolvable when a model + // introduces its root name. In that case resolve everything together. + // Owned root members shadow imported ones, so a root import or an + // inferred root name matters only through recorded root misses. + self.root_completions(model) + .is_none_or(|names| names.iter().any(|n| self.completes_root_name(n))) + } + + /// The names a model's user units make visible in the root namespace. + /// `None` when a root construct's contribution needs the resolver, so + /// callers must assume any recorded outcome could change. + fn root_completions(&self, model: &crate::model::Model) -> Option> { + let mut names = HashSet::new(); + for (_, unit) in model.user_units() { + for member in &unit.unit.members { + // Only root identifications matter. Avoid lowering user bodies. + let id = match &member.kind { + MemberKind::Import(import) | MemberKind::Expose(import) => { + names.extend(self.imported_root_names(model, import)?); + None + } + // A root filter also constrains the library's own root + // imports, so it always requires joint resolution. + MemberKind::Filter(_) => return None, + MemberKind::Package(p) => Some(&p.id), + MemberKind::Definition(d) => Some(&d.id), + // An anonymous root feature can introduce an inferred + // binding from its redefinition/reference target. + MemberKind::Usage(u) => { + if u.declaration.id.name.is_none() { + names.extend(effective_ref_name(&u.declaration)); + } + Some(&u.declaration.id) + } + MemberKind::Alias(a) => Some(&a.id), + MemberKind::Dependency(d) => Some(&d.id), + MemberKind::Relationship(r) => Some(&r.id), + MemberKind::MultiplicityDecl(m) => Some(&m.id), + MemberKind::Comment(c) => Some(&c.id), + MemberKind::Doc(d) => Some(&d.id), + MemberKind::TextualRep(r) => Some(&r.id), + // Other root constructs may also add named memberships; + // use joint resolution instead of guessing their effects. + _ => return None, + }; + if let Some(id) = id { + names.extend( + [&id.name, &id.short_name] + .into_iter() + .flatten() + .map(|n| n.value.clone()), + ); + } + } + } + Some(names) + } + + /// Whether a name newly visible in the root namespace can change an + /// outcome recorded while this library was prepared. + fn completes_root_name(&self, name: &str) -> bool { + self.root_misses.contains(name) + || self + .unresolved + .iter() + .chain(&self.ambiguous) + .any(|(_, q)| q.segments.first().is_some_and(|s| s.value == name)) + } + + /// The names a root-level import of a model makes visible in the root + /// namespace, located through user syntax or this library's scope tables + /// alone: no resolver, no aliases, no user-side re-exports. `None` when + /// the target cannot be located that way; the caller then resolves + /// jointly instead of guessing. + fn imported_root_names( + &self, + model: &crate::model::Model, + import: &Import, + ) -> Option> { + let mut names = HashSet::new(); + let first = import.target.segments.first()?.value.as_str(); + let mut roots = model.user_units().flat_map(|(_, u)| u.unit.members.iter()); + if let Some(root) = roots.find(|m| member_id(m).is_some_and(|id| id_matches(id, first))) { + let mut member = root; + for segment in &import.target.segments[1..] { + member = member_body(member)? + .iter() + .find(|m| member_id(m).is_some_and(|id| id_matches(id, &segment.value)))?; + } + if matches!(member.kind, MemberKind::Alias(_)) { + return None; + } + if import.is_namespace { + user_member_names( + member_body(member).unwrap_or(&[]), + import.is_recursive, + &mut names, + )?; + } else { + member_names(member, &mut names)?; + if import.is_recursive { + user_member_names(member_body(member).unwrap_or(&[]), true, &mut names)?; + } + } + return Some(names); + } + let mut seen = HashSet::new(); + if import.is_namespace { + let scope = self.library_path_scope(0, &import.target)?; + self.library_scope_names(scope, import.is_recursive, &mut seen, &mut names)?; + } else { + let (owner, elem) = self.library_path_member(0, &import.target)?; + self.library_elem_names(owner, elem, &mut names); + if import.is_recursive { + if let Some(&sub) = self.elem_scope.get(&elem) { + self.library_scope_names(sub, true, &mut seen, &mut names)?; + } + } + } + Some(names) + } + + /// The single element a library path names, walking declared names only, + /// with the scope it was found in. + fn library_path_member(&self, from: usize, qn: &QualifiedName) -> Option<(usize, usize)> { + let first = qn.segments.first()?; + let mut scope = if qn.is_global { + 0 + } else { + let mut s = from; + loop { + if self.scopes[s].names.get(&first.value).is_some() { + break s; + } + s = self.scopes[s].parent?; + } + }; + let mut found = None; + for segment in &qn.segments { + let bindings = self.scopes[scope].names.get(&segment.value)?; + let elem = bindings.first()?.elem; + if bindings.iter().any(|b| b.elem != elem) { + return None; + } + found = Some((scope, elem)); + scope = match bindings.iter().find_map(|b| b.sub_scope) { + Some(sub) => sub, + None if std::ptr::eq(segment, qn.segments.last()?) => break, + None => return None, + }; + } + found + } + + fn library_path_scope(&self, from: usize, qn: &QualifiedName) -> Option { + let (_, elem) = self.library_path_member(from, qn)?; + self.elem_scope.get(&elem).copied() + } + + /// Every declared or inferred name of `elem` within `scope`. + fn library_elem_names(&self, scope: usize, elem: usize, out: &mut HashSet) { + let scope = &self.scopes[scope]; + for (name, bindings) in scope.names.iter().chain(scope.effective_names.iter()) { + if bindings.iter().any(|b| b.elem == elem) { + out.insert(name.to_owned()); + } + } + } + + /// Names visible through a namespace import of library scope `s`, + /// including re-exports through its public imports. `None` when a + /// re-export target cannot be located without the resolver. + fn library_scope_names( + &self, + s: usize, + recursive: bool, + seen: &mut HashSet<(usize, bool)>, + out: &mut HashSet, + ) -> Option<()> { + if !seen.insert((s, recursive)) { + return Some(()); + } + let scope = &self.scopes[s]; + for (name, bindings) in scope.names.iter().chain(scope.effective_names.iter()) { + out.insert(name.to_owned()); + if recursive { + for sub in bindings.iter().filter_map(|b| b.sub_scope) { + self.library_scope_names(sub, true, seen, out)?; + } + } + } + for (name, _, _) in &scope.aliases { + out.insert(name.clone()); + } + for &(name, _, _) in &scope.implied_ends { + out.insert(name.to_owned()); + } + for import in &scope.imports { + if import.is_public { + let target = self.library_path_scope(s, &import.target)?; + self.library_scope_names(target, recursive || import.recursive, seen, out)?; + } + } + for import in &scope.member_imports { + if import.is_public { + let (owner, elem) = self.library_path_member(s, &import.target)?; + self.library_elem_names(owner, elem, out); + if recursive { + if let Some(&sub) = self.elem_scope.get(&elem) { + self.library_scope_names(sub, true, seen, out)?; + } + } + } + } + Some(()) + } + + fn build_on_library(&mut self, model: &crate::model::Model, library: &Builder) -> usize { + *self = library.clone(); + self.semantic_ready = false; + let boundary = self.elements.len(); + // Query outcomes are local to this model. In particular a root miss + // in a library-only world must not hide a newly introduced user name. + self.reset_lookup_caches(); + self.exclude = None; + self.pending_exclude = None; + self.declared_only = false; + self.pending_declared_only = false; + let mut roots = Vec::new(); + for (orig, unit) in model.user_units() { + self.unit_starts.push((self.elements.len(), orig)); + self.scope_starts.push((self.scopes.len(), orig)); + self.dialect = unit.unit.dialect; + let root = self.new_element("Namespace", None, format!("$root/{}", unit.name)); + roots.push(root); + for (i, member) in unit.unit.members.iter().enumerate() { + self.build_member(member, root, 0, i); + } + } + self.resolve_pending(); + self.assign_user_ids(boundary, &roots); + boundary + } + + pub(crate) fn prepare_facts(&mut self) -> crate::check::facts::Facts { + let used = self.used_imports.clone(); + let facts = crate::check::facts::Facts::new(self); + self.used_imports = used; + facts + } + + pub(crate) fn reset_lookup_caches(&mut self) { + let n = self.scopes.len(); + self.import_cache = vec![None; n]; + self.base_cache = vec![None; n]; + self.visit_stamp = vec![[0; 3]; n]; + self.visit_result = vec![[None; 3]; n]; + self.query_stamp = 0; + self.import_targets.clear(); + self.semantic_metadata = None; + self.id_index = None; + self.spec_index = None; + self.mult_index = None; + self.inherited_cache.clear(); + self.inherited_by_heritage.clear(); + self.filters_active = vec![false; self.filter_exprs.len()]; + self.member_import_active.clear(); + } + + pub(crate) fn freeze_library(&mut self) { + for i in 0..self.elements.len() { + if !self.elements[i].path.is_empty() && self.elements[i].path != "first" { + let first = self.elements[i].path.ends_with("first"); + self.elements[i].path = if first { "first".into() } else { String::new() }; + } + } + self.elements.freeze(); + self.scopes.freeze(); + self.semantic_memo.freeze(); + self.id_index = None; + self.spec_index = None; + self.mult_index = None; + self.inherited_cache.clear(); + self.inherited_by_heritage.clear(); + self.elem_scope.freeze(); + self.effective_hint.freeze(); + self.values.freeze(); + self.owned_cross_features.freeze(); + self.contract_exprs.freeze(); + self.transition_guards.freeze(); + self.decl_spans.freeze(); + self.member_spans.freeze(); + self.in_params.freeze(); + self.ctor_fields.freeze(); + self.return_params.freeze(); + self.usage_featuring.freeze(); + self.prefix_meta_next.freeze(); + self.metadata_of.freeze(); + self.conjugated_defs.freeze(); + self.lib_qnames.freeze(); + self.lib_mem_qnames.freeze(); + self.multiplicities.freeze(); + self.connector_ends.freeze(); + self.chain_subsettings.freeze(); + self.satisfy_by.freeze(); + self.spec_targets.freeze(); + self.spec_resolved.freeze(); + self.result_exprs.freeze(); + self.filter_exprs.freeze(); + } + + pub(crate) fn valid_library(&self, units: usize) -> bool { + let n = self.elements.len(); + let ns = self.scopes.len(); + self.lib_boundary == n + && ns > 0 + && self.pending.is_empty() + && self.ref_sites.is_empty() + && self.unit_starts.len() == units + && self.scope_starts.len() == units + && self + .unit_starts + .iter() + .enumerate() + .all(|(u, &(e, orig))| e < n && u == orig) + && self.scope_starts.iter().all(|&(s, u)| s <= ns && u < units) + && self.import_cache.len() == ns + && self.base_cache.len() == ns + && self.visit_stamp.len() == ns + && self.visit_result.len() == ns + && self.spec_resolved.len() == self.spec_targets.len() + && self.elements.iter().all(|e| { + e.owning_relationship.is_none_or(|r| r < n) + && e.owned_relationships.iter().all(|&r| r < n) + && e.children.iter().all(|&r| r < n) + }) + && self.elements.iter().enumerate().all(|(i, e)| { + e.children + .iter() + .all(|&c| self.elements[c].owning_relationship == Some(i)) + && e.owning_relationship + .is_none_or(|r| self.elements[r].children.contains(&i)) + }) + && self.semantic_memo.valid(n, ns) + && self.scopes.iter().enumerate().all(|(s, scope)| { + scope.parent.is_none_or(|p| p < s) + && scope.owner.is_none_or(|e| e < n) + && scope + .names + .values() + .chain(scope.effective_names.values()) + .flatten() + .all(|b| b.elem < n && b.sub_scope.is_none_or(|s| s < ns)) + }) + && self.elem_scope.iter().all(|(&e, &s)| e < n && s < ns) + && self + .spec_targets + .iter() + .all(|(e, _, s, _)| *e < n && *s < ns) + && self.spec_resolved.iter().all(|t| t.is_none_or(|e| e < n)) + && self + .values + .iter() + .chain(&self.contract_exprs) + .chain(&self.transition_guards) + .all(|(&e, (s, _))| e < n && *s < ns) + && self + .multiplicities + .iter() + .all(|(e, s, _)| *e < n && *s < ns) + } + fn build_model_inner( &mut self, model: &crate::model::Model, @@ -731,10 +1521,10 @@ impl Builder { } else { model.take_lib_cache_for_build() }; - let mut snapshot: Option = None; + let mut snapshot: Option> = None; match slot { crate::model::LibCacheSlot::Use(cache) if !top_level_shadowing(model) => { - self.lib_ids_in = Some(cache.lib_ids.clone().into_iter()); + self.lib_ids_in = Some((Arc::clone(&cache), 0)); snapshot = Some(cache); } crate::model::LibCacheSlot::Record => { @@ -774,8 +1564,8 @@ impl Builder { let lib_names_pending = if let Some(cache) = snapshot { let exhausted = self .lib_ids_in - .as_mut() - .is_none_or(|it| it.next().is_none()); + .as_ref() + .is_none_or(|(cache, taken)| *taken >= cache.lib_ids.len()); self.lib_ids_in = None; if !exhausted || boundary != cache.lib_ids.len() @@ -783,9 +1573,22 @@ impl Builder { { return Err(()); } - self.lib_qnames = cache.lib_qnames; - self.lib_mem_qnames = cache.lib_mem_qnames; - self.lib_hints = Some(cache.outcomes.into_iter()); + self.lib_qnames = cache.lib_qnames.iter().cloned().collect(); + self.lib_mem_qnames = cache.lib_mem_qnames.iter().cloned().collect(); + // The pairs outlive the borrow of the cache they are read + // from, so they are owned here rather than iterated in place. + #[allow(clippy::needless_collect)] + let hints: Vec<_> = cache + .outcomes + .iter() + .copied() + .zip(cache.outcome_misses.iter().cloned()) + .collect(); + self.lib_hints = Some(hints.into_iter()); + // Recorded outcomes are replayed only where the user units cannot + // have changed them; an unlocatable root contribution disables + // replay for this build. + self.replay_completions = self.root_completions(model); false } else { self.assign_library_ids(&lib_roots); @@ -814,13 +1617,15 @@ impl Builder { .filter(|&start| start >= boundary) .collect(); self.assign_user_ids(boundary, &user_roots); - if let Some(outcomes) = self.lib_record.take() { + if let Some(recorded) = self.lib_record.take() { + let (outcomes, outcome_misses) = recorded.into_iter().unzip(); model.deposit_recorded(crate::libcache::LibraryCache { outcomes, + outcome_misses, fingerprint: lib_fingerprint, - lib_ids: self.elements[..boundary].iter().map(|e| e.id).collect(), - lib_qnames: self.lib_qnames.clone(), - lib_mem_qnames: self.lib_mem_qnames.clone(), + lib_ids: self.elements.iter().take(boundary).map(|e| e.id).collect(), + lib_qnames: self.lib_qnames.iter().cloned().collect(), + lib_mem_qnames: self.lib_mem_qnames.iter().cloned().collect(), }); } Ok(boundary) @@ -831,13 +1636,18 @@ impl Builder { /// positionally aligned with. fn lib_pending_fingerprint(&self) -> u64 { let mut h = crate::libcache::Fnv::new(); + // One buffer for every name: the references run to five figures + // on a full library and nothing outlives the hash. + let mut spelled = String::new(); for p in &self.pending { if p.elem >= self.lib_boundary { continue; } h.update(&(p.elem as u64).to_le_bytes()); h.update(p.key.as_bytes()); - h.update(p.qn.to_ref_string().as_bytes()); + spelled.clear(); + p.qn.write_ref_string(&mut spelled); + h.update(spelled.as_bytes()); } h.finish() } @@ -864,7 +1674,7 @@ impl Builder { owned_by_rel[r].push(i); } } - let mut remap: HashMap = HashMap::new(); + let mut remap: HashMap = HashMap::new(); for &(root, prefix) in lib_roots { let rels = self.elements[root].owned_relationships.clone(); let mut tops: Vec<(usize, Uuid, String)> = Vec::new(); @@ -909,9 +1719,10 @@ impl Builder { } if !remap.is_empty() { // Patch `@id` references captured during the library build. - for e in &mut self.elements { + for i in 0..self.elements.len() { + let e = &mut self.elements[i]; for v in e.props.values_mut() { - patch_ids(v, &remap); + v.remap(&remap); } } } @@ -944,7 +1755,7 @@ impl Builder { } } // First explicit redefinition / reference-subsetting target id. - fn target_of(elements: &[Elem], i: usize) -> Option { + fn target_of(elements: &crate::layered::LayeredVec, i: usize) -> Option { for &r in &elements[i].owned_relationships { let rel = &elements[r]; let key = match rel.ty { @@ -1017,7 +1828,7 @@ impl Builder { segments: &[String], top: Uuid, owned_by_rel: &[Vec], - remap: &mut HashMap, + remap: &mut HashMap, ) { let rels = self.elements[e].owned_relationships.clone(); for rel in rels { @@ -1073,6 +1884,10 @@ impl Builder { } } + /// The declared half of the naming rule: an element's own declared + /// (short) name, with no derivation. `Self::graph_effective_name` + /// carries the derived half; see it for the rule and its other + /// implementations. pub(crate) fn effective_name(&self, e: usize) -> Option { let props = &self.elements[e].props; props @@ -1090,10 +1905,10 @@ impl Builder { .or_else(|| self.effective_hint.get(&e).cloned()) } - fn reassign_id(&mut self, e: usize, id: Uuid, remap: &mut HashMap) { + fn reassign_id(&mut self, e: usize, id: Uuid, remap: &mut HashMap) { let old = self.elements[e].id; if old != id { - remap.insert(old.to_string(), id.to_string()); + remap.insert(old, id); self.elements[e].id = id; } } @@ -1103,6 +1918,18 @@ impl Builder { /// `ownedRelationship` order, read from the *graph* — a resolved /// `{"@id"}` target names through `names`, a hermetic `{"@ref"}` /// placeholder carries the name itself (last qualification segment). + /// + /// One naming rule, four representations — an element is named by + /// its declaration (`Self::effective_name`), else by its *naming + /// feature*: the first feature it redefines, else the one it + /// references, else the last link of its chain, each followed + /// transitively. The implementations are this one (over the lowered + /// element graph), `lift::Lifter::effective_name` (over payload + /// JSON), `full::effective_name_of` (over the full form's element + /// maps, which also derives the positional implied names), and the + /// fixpoint inside `ids::walk` (over a compact payload, for id + /// segments). They agree by construction and by the differential test + /// in the round-trip gate; a change to one belongs in all of them. fn graph_effective_name( &self, e: usize, @@ -1117,11 +1944,10 @@ impl Builder { _ => continue, }; let target = rel.props.get(key)?; - if let Some(s) = target.get("@ref").and_then(Value::as_str) { + if let Some(s) = target.get("@ref").and_then(|v| v.as_str()) { return Some(s.rsplit("::").next().unwrap_or(s).to_string()); } - let s = target.get("@id").and_then(Value::as_str)?; - let t = *by_id.get(&Uuid::parse_str(s).ok()?)?; + let t = *by_id.get(&target.as_reference()?)?; return names[t].clone(); } None @@ -1185,7 +2011,7 @@ impl Builder { } // Top-down walk: parents carry their final ids before children // derive from them. - let mut remap: HashMap = HashMap::new(); + let mut remap: HashMap = HashMap::new(); let mut stack: Vec = roots.to_vec(); while let Some(owner) = stack.pop() { let owner_id = self.elements[owner].id; @@ -1221,8 +2047,8 @@ impl Builder { let props = &self.elements[rel].props; if let Some(name) = props .get("memberName") - .and_then(Value::as_str) - .or_else(|| props.get("memberShortName").and_then(Value::as_str)) + .and_then(|v| v.as_str()) + .or_else(|| props.get("memberShortName").and_then(|v| v.as_str())) { let named = format!("::{}", escape_name(name)); if used.insert(named.clone()) { @@ -1256,9 +2082,10 @@ impl Builder { } // Re-point every captured reference (library elements never // reference user elements, so the sweep stays in user range). - for e in &mut self.elements[boundary..] { + for i in boundary..self.elements.len() { + let e = &mut self.elements[i]; for v in e.props.values_mut() { - patch_ids(v, &remap); + v.remap(&remap); } } } @@ -1268,11 +2095,12 @@ impl Builder { self.finish_range(boundary, end) } - fn finish_range(mut self, start: usize, end: usize) -> Value { + fn finish_range(self, start: usize, end: usize) -> Value { // Materialize relationship arrays as {"@id"} references. let ids: Vec = self.elements.iter().map(|e| e.id).collect(); let mut out = Vec::with_capacity(end - start); - for elem in &mut self.elements[start..end] { + for i in start..end { + let elem = &self.elements[i]; let mut obj = Map::new(); obj.insert("@type".into(), json!(elem.ty)); obj.insert("@id".into(), json!(elem.id.to_string())); @@ -1293,7 +2121,13 @@ impl Builder { .map(|i| id_ref(ids[i])) .unwrap_or(Value::Null), ); - obj.append(&mut elem.props); + obj.extend(elem.props.to_json()); + if !elem.children.is_empty() { + obj.insert( + "ownedRelatedElement".into(), + Value::Array(elem.children.iter().map(|&i| id_ref(ids[i])).collect()), + ); + } out.push(Value::Object(obj)); } Value::Array(out) @@ -1316,10 +2150,31 @@ impl Builder { /// Register an element's declared name and short name in `scope`, with /// its body scope `sub_scope`. fn register(&mut self, scope: usize, id: &Identification, elem: usize, sub_scope: usize) { + self.bind_names(scope, id, elem, Some(sub_scope)); + self.elem_scope.insert(elem, sub_scope); + self.scopes[sub_scope].owner = Some(elem); + } + + /// Register the declared name and short name of an element that owns + /// no members of its own — a named comment, documentation, textual + /// representation, or dependency. Its owning membership names it in + /// `scope` like any other member, so `about` clauses and qualified + /// names reach it, but nothing resolves *through* it. + fn register_leaf(&mut self, scope: usize, id: &Identification, elem: usize) { + self.bind_names(scope, id, elem, None); + } + + fn bind_names( + &mut self, + scope: usize, + id: &Identification, + elem: usize, + sub_scope: Option, + ) { let visibility = match self.elements[elem] .owning_relationship .and_then(|r| self.elements[r].props.get("visibility")) - .and_then(Value::as_str) + .and_then(|v| v.as_str()) { Some("private") => LookupAccess::All, Some("protected") => LookupAccess::Protected, @@ -1327,38 +2182,41 @@ impl Builder { }; let binding = Binding { elem, - sub_scope: Some(sub_scope), + sub_scope, visibility, }; for name in id.name.iter().chain(&id.short_name) { - self.scopes[scope] - .names - .entry(name.value.clone()) - .or_default() - .push(binding); + self.scopes[scope].names.push(name.value.clone(), binding); } - self.elem_scope.insert(elem, sub_scope); - self.scopes[sub_scope].owner = Some(elem); } /// Next replayed library element id, when a sealed snapshot is active. fn next_lib_id(&mut self) -> Option { - self.lib_ids_in.as_mut().and_then(|it| it.next()) + self.lib_ids_in.as_mut().and_then(|(cache, taken)| { + let id = cache.lib_ids.get(*taken).copied(); + *taken += 1; + id + }) } fn new_element(&mut self, ty: &'static str, owner_rel: Option, path: String) -> usize { let id = self .next_lib_id() - .unwrap_or_else(|| Uuid::new_v5(&id_namespace(), path.as_bytes())); + .unwrap_or_else(|| Uuid::new_v5(&ID_NAMESPACE, path.as_bytes())); self.elements.push(Elem { ty, id, path, - props: Map::new(), - owned_relationships: Vec::new(), + props: crate::properties::Properties::new(), + owned_relationships: Default::default(), + children: Default::default(), owning_relationship: owner_rel, }); - self.elements.len() - 1 + let idx = self.elements.len() - 1; + if let Some(rel) = owner_rel { + self.elements[rel].children.push(idx); + } + idx } /// Create a relationship element owned by `owner` (appended to its @@ -1368,13 +2226,19 @@ impl Builder { self.elements[i].id } + /// The number of explicit elements — the element list without the + /// implied relationships the derivation layer may have appended. + pub(crate) fn explicit_len(&self) -> usize { + self.implied_from.unwrap_or(self.elements.len()) + } + fn new_relationship(&mut self, ty: &'static str, owner: usize, path_seg: &str) -> usize { let (path, id) = match self.next_lib_id() { // Sealed snapshot: paths only feed id derivation, so skip both. Some(id) => (String::new(), id), None => { let path = format!("{}/{}", self.elements[owner].path, path_seg); - let id = Uuid::new_v5(&id_namespace(), path.as_bytes()); + let id = Uuid::new_v5(&ID_NAMESPACE, path.as_bytes()); (path, id) } }; @@ -1382,8 +2246,9 @@ impl Builder { ty, id, path, - props: Map::new(), - owned_relationships: Vec::new(), + props: crate::properties::Properties::new(), + owned_relationships: Default::default(), + children: Default::default(), owning_relationship: None, }); let idx = self.elements.len() - 1; @@ -1392,7 +2257,7 @@ impl Builder { let owner_id = self.elements[owner].id; self.elements[idx] .props - .insert("owningRelatedElement".into(), id_ref(owner_id)); + .insert("owningRelatedElement", id_ref(owner_id)); idx } @@ -1403,7 +2268,7 @@ impl Builder { Some(id) => (String::new(), id), None => { let path = format!("{}/{}", self.elements[rel].path, name_seg); - let id = Uuid::new_v5(&id_namespace(), path.as_bytes()); + let id = Uuid::new_v5(&ID_NAMESPACE, path.as_bytes()); (path, id) } }; @@ -1411,28 +2276,18 @@ impl Builder { ty, id, path, - props: Map::new(), - owned_relationships: Vec::new(), + props: crate::properties::Properties::new(), + owned_relationships: Default::default(), + children: Default::default(), owning_relationship: Some(rel), }); let idx = self.elements.len() - 1; - let id_val = id_ref(id); - let rel_elem = &mut self.elements[rel]; - match rel_elem.props.entry("ownedRelatedElement") { - serde_json::map::Entry::Occupied(mut e) => { - if let Value::Array(a) = e.get_mut() { - a.push(id_val); - } - } - serde_json::map::Entry::Vacant(e) => { - e.insert(Value::Array(vec![id_val])); - } - } + self.elements[rel].children.push(idx); idx } fn set(&mut self, elem: usize, key: &str, value: Value) { - self.elements[elem].props.insert(key.to_string(), value); + self.elements[elem].props.insert(key, value); } fn set_identification(&mut self, elem: usize, id: &Identification) { @@ -1495,6 +2350,14 @@ impl Builder { // resolves lexically, link *k* as a member (owned or // inherited via typing) of link *k−1*. let base = key.split('#').next().unwrap_or(key); + // A membership that owns the chain feature is an + // OwningMembership (SysML.xtext `TransitionSourceMember`, + // KerMLExpressions.xtext `FeatureChainMember` / + // `InstantiatedTypeMember`), whatever the referencing + // site created it as. + if self.elements[elem].ty == "Membership" { + self.elements[elem].ty = "OwningMembership"; + } let feature = self.new_owned_element("Feature", elem, &format!("{base}.chain")); for (i, link) in links.iter().enumerate() { let fc = @@ -1682,6 +2545,13 @@ impl Builder { } fn build_member_inner(&mut self, member: &Member, owner: usize, scope: usize, index: usize) { + if matches!( + self.elements[owner].ty, + "CalculationDefinition" | "CalculationUsage" | "Function" | "Expression" + ) && member_requires_execution(member) + { + self.executable_calculations.insert(owner); + } // Implied empty succession from a bare leading `then`. The pilot's // EmptySuccession rule owns two bare ends (MultiplicitySourceEndMember // + EmptyTargetEndMember). @@ -1693,7 +2563,7 @@ impl Builder { self.set(succ, "isComposite", json!(false)); self.set(succ, "isVariation", json!(false)); let mut source = Self::empty_connector_end(); - source.multiplicity = member.leading_then_multiplicity.as_deref().cloned(); + source.multiplicity = member.leading_then_multiplicity.clone(); self.emit_connector_end(succ, &source, scope, 0); let empty = Self::empty_connector_end(); self.emit_connector_end(succ, &empty, scope, 1); @@ -1738,11 +2608,12 @@ impl Builder { Self::visibility_value(member.visibility), false, ); - self.user_imports.push(( + self.user_imports.push(UserImport { rel, - member.span, - member.visibility == Some(Visibility::Private), - )); + span: member.span, + scope, + visibility: member.visibility, + }); let fids = self.record_filters(&imp.filters, scope); let is_public = member.visibility.is_none() || member.visibility == Some(Visibility::Public); @@ -1818,6 +2689,7 @@ impl Builder { self.set(rel, "isImplied", json!(false)); let e = self.new_owned_element("Comment", rel, &format!("comment{index}")); self.set_identification(e, &c.id); + self.register_leaf(scope, &c.id, e); self.set(e, "body", json!(process_comment_body(&c.body))); self.set( e, @@ -1841,6 +2713,7 @@ impl Builder { self.set(rel, "isImplied", json!(false)); let e = self.new_owned_element("Documentation", rel, &format!("doc{index}")); self.set_identification(e, &d.id); + self.register_leaf(scope, &d.id, e); self.set(e, "body", json!(process_comment_body(&d.body))); self.set( e, @@ -1855,6 +2728,7 @@ impl Builder { let e = self.new_owned_element("TextualRepresentation", rel, &format!("rep{index}")); self.set_identification(e, &r.id); + self.register_leaf(scope, &r.id, e); self.set(e, "language", json!(r.language)); self.set(e, "body", json!(r.body)); } @@ -1880,6 +2754,7 @@ impl Builder { self.set(rel, "isImplied", json!(false)); let e = self.new_owned_element("Dependency", rel, &format!("dependency{index}")); self.set_identification(e, &d.id); + self.register_leaf(scope, &d.id, e); self.set(e, "isImplied", json!(false)); self.emit_prefix_metadata(e, &d.metadata, scope); for (i, c) in d.clients.iter().enumerate() { @@ -2205,7 +3080,7 @@ impl Builder { self.set_ref(r, key, scope, t); } } - if matches!(d.kind, DefKind::Occurrence | DefKind::Individual) { + if d.prefix.is_individual || matches!(d.kind, DefKind::Occurrence | DefKind::Individual) { self.set(e, "isIndividual", json!(d.prefix.is_individual)); } if d.kind == DefKind::State { @@ -2221,7 +3096,7 @@ impl Builder { } } for base in implicit_def_bases(d.kind) { - self.scopes[body_scope].bases.push(lib_qn(base)); + self.scopes[body_scope].implied_bases.push(lib_qn(base)); } for (i, target) in d.specializes.iter().enumerate() { if let TargetRef::Name(qn) = target { @@ -2469,6 +3344,7 @@ impl Builder { self.set(om, "isImplied", json!(false)); self.set(om, "visibility", json!("public")); let cf = self.new_owned_element("ReferenceUsage", om, "crossFeature"); + self.owned_cross_features.insert(e, cf); self.set(cf, "isVariation", json!(cross.is_variation)); // The cross feature's own basic prefix; flags are emitted only // when set so cross-feature-free models are unchanged. @@ -2522,7 +3398,11 @@ impl Builder { if self.dialect == Dialect::Kerml { self.set(e, "isComposite", json!(u.prefix.is_composite)); self.set(e, "isPortion", json!(u.prefix.is_portion)); - self.set(e, "isVariable", json!(u.prefix.is_variable)); + self.set( + e, + "isVariable", + json!(u.prefix.is_variable || u.prefix.is_constant), + ); self.set(e, "isSufficient", json!(u.declaration.is_sufficient)); } else { // SysML usages are composite by default (pilot `UsageImpl`), @@ -2588,23 +3468,22 @@ impl Builder { if u.declaration.id.name.is_none() && u.declaration.id.short_name.is_none() { if let Some(name) = effective_ref_name(&u.declaration) { self.effective_hint.insert(e, name.clone()); - self.scopes[scope] - .effective_names - .entry(name) - .or_default() - .push(Binding { + self.scopes[scope].effective_names.push( + name, + Binding { elem: e, sub_scope: Some(body_scope), visibility: match self.elements[rel] .props .get("visibility") - .and_then(Value::as_str) + .and_then(|v| v.as_str()) { Some("private") => LookupAccess::All, Some("protected") => LookupAccess::Protected, _ => LookupAccess::Public, }, - }); + }, + ); } } // Typing/subsetting/redefinition targets provide inherited-member @@ -2623,6 +3502,14 @@ impl Builder { for t in targets { match t { TargetRef::Name(qn) => { + if matches!(spec, FeatureSpecialization::Redefines(_)) + && !qn.is_global + && qn.segments.len() == 1 + { + self.scopes[body_scope] + .redefinition_names + .insert(qn.segments[0].value.clone()); + } self.scopes[body_scope].bases.push(qn.clone()); } TargetRef::Chain(links) if !links.is_empty() => { @@ -2647,7 +3534,7 @@ impl Builder { u.kind }; for base in implicit_usage_bases(base_kind) { - self.scopes[body_scope].bases.push(lib_qn(base)); + self.scopes[body_scope].implied_bases.push(lib_qn(base)); } } // Implicit parameter redefinition (SysML 8.3): a named directed @@ -2657,7 +3544,7 @@ impl Builder { // (`focus.image.isWellFocused` with `out item image;`). if u.prefix.direction.is_some() { if let Some(name) = &u.declaration.id.name { - self.scopes[body_scope].bases.push(QualifiedName { + self.scopes[body_scope].implied_bases.push(QualifiedName { is_global: false, segments: vec![name.clone()], span: name.span, @@ -2779,7 +3666,16 @@ impl Builder { for (i, link) in links.iter().enumerate() { let fc = self.new_relationship("FeatureChaining", e, &format!("chain{i}")); self.set(fc, "isImplied", json!(false)); - self.set_ref(fc, "chainingFeature", scope, &TargetRef::Name(link.clone())); + self.pending.push(PendingRef { + elem: fc, + key: "chainingFeature".to_string(), + scope, + qn: link.clone(), + exclude: self.pending_exclude, + declared_only: false, + chain: (i > 0 && !link.is_global).then(|| links[..i].to_vec()), + spec_idx: None, + }); } } else if let Some(t) = &decl.chains { let fc = self.new_relationship("FeatureChaining", e, "chain0"); @@ -2897,6 +3793,9 @@ impl Builder { } } + if matches!(u.kind, UsageKind::Flow | UsageKind::SuccessionFlow) { + self.payload_flows.insert(e); + } let end_elems = self.build_usage_detail(e, &detail, scope); // A *binary* connector-family usage (exactly two ends): its body @@ -2924,7 +3823,7 @@ impl Builder { _ => None, }; if let Some(base) = binary { - self.scopes[body_scope].bases.push(lib_qn(base)); + self.scopes[body_scope].implied_bases.push(lib_qn(base)); } } let UsageDetail::Connector { ends } = &detail else { @@ -2992,7 +3891,7 @@ impl Builder { ConnectorEnd { multiplicity: None, name: None, - target: TargetRef::Chain(Vec::new()), + target: TargetRef::unspelled(), } } @@ -3034,7 +3933,7 @@ impl Builder { self.emit_multiplicity(ru, mult, scope); } // Empty targets occur for implicit source ends of successions. - let is_empty = matches!(&end.target, TargetRef::Chain(links) if links.is_empty()); + let is_empty = end.target.is_unspelled(); if !is_empty { let span = match &end.target { TargetRef::Name(qn) => qn_span(qn), @@ -3138,6 +4037,7 @@ impl Builder { let pm = self.new_relationship("ParameterMembership", parent, seg); self.set(pm, "isImplied", json!(false)); let ru = self.new_owned_element(self.ref_feature_metaclass(), pm, seg); + self.contract_exprs.insert(ru, (scope, expr.clone())); self.set_synth_usage_flags(ru); let fv = self.new_relationship("FeatureValue", ru, "value"); self.set(fv, "isImplied", json!(false)); @@ -3270,16 +4170,12 @@ impl Builder { self.set(ru, "isVariation", json!(false)); // Pilot SatisfactionFeatureValue: the `by` target binds // as a FeatureValue whose FeatureReferenceExpression - // owns a FeatureChainMember (plain Membership for a - // name, OwningMembership for an owned chain). + // owns a FeatureChainMember (`set_ref` retypes it to an + // OwningMembership when the target is an owned chain). let fv = self.new_relationship("FeatureValue", ru, "value"); self.set(fv, "isImplied", json!(false)); let fre = self.new_owned_element("FeatureReferenceExpression", fv, "expr"); - let m_ty = match by { - TargetRef::Chain(links) if links.len() >= 2 => "OwningMembership", - _ => "Membership", - }; - let m = self.new_relationship(m_ty, fre, "ref"); + let m = self.new_relationship("Membership", fre, "ref"); self.set(m, "isImplied", json!(false)); self.set_ref(m, "memberElement", scope, by); } @@ -3302,6 +4198,7 @@ impl Builder { let pm = self.new_relationship("ParameterMembership", e, "trigger"); self.set(pm, "isImplied", json!(false)); let te = self.new_owned_element("TriggerInvocationExpression", pm, "trigger"); + self.contract_exprs.insert(te, (scope, t.expr.clone())); self.set(te, "kind", json!(kind)); let am = self.new_relationship("ParameterMembership", te, "arg"); self.set(am, "isImplied", json!(false)); @@ -3447,7 +4344,8 @@ impl Builder { self.set(gm, "isImplied", json!(false)); self.set(gm, "kind", json!("guard")); self.build_expr(guard, gm, t_scope, "expr"); - self.transition_guards.insert(e, (t_scope, guard.clone())); + self.transition_guards + .insert(e, (t_scope, (**guard).clone())); } if let Some(effect) = effect { let em = self.new_relationship("TransitionFeatureMembership", e, "effect"); @@ -3472,7 +4370,7 @@ impl Builder { Vec::new() } - /// Like [`build_usage_element`] but with an explicit pre-created scope + /// Like `build_usage_element` but with an explicit pre-created scope /// (for anonymous nested usages). fn build_usage_element_scoped( &mut self, @@ -3495,6 +4393,31 @@ impl Builder { /// Build the abstract-syntax element tree for `expr`, owned via /// relationship `rel`. Returns the expression element index. fn build_expr(&mut self, expr: &Expr, rel: usize, scope: usize, seg: &str) -> usize { + /// The wire value of a real literal. A JSON number is a double, + /// which holds neither more significant digits than its + /// precision nor an exponent that overflows it — and in-memory + /// evaluation reads the literal exactly, so a rounded number on + /// the wire would make the two disagree. The number therefore + /// travels only when printing and re-reading it yields exactly + /// the written value; otherwise the literal's own text does, + /// the way an integer beyond 64 bits already travels as text. + fn real_literal_value(raw: &str) -> Value { + use crate::rational::Rational; + let Some(number) = raw + .parse::() + .ok() + .and_then(serde_json::Number::from_f64) + else { + return json!(raw); + }; + match ( + Rational::parse_decimal(raw), + Rational::parse_decimal(&number.to_string()), + ) { + (Some(written), Some(printed)) if written == printed => Value::Number(number), + _ => json!(raw), + } + } match &expr.kind { ExprKind::Literal(lit) => { let (ty, value) = match lit { @@ -3506,12 +4429,7 @@ impl Builder { .map(|v| json!(v)) .unwrap_or_else(|_| json!(n)), ), - Literal::Real(r) => ( - "LiteralRational", - r.parse::() - .map(|v| json!(v)) - .unwrap_or_else(|_| json!(r)), - ), + Literal::Real(r) => ("LiteralRational", real_literal_value(r)), Literal::Infinity => ("LiteralInfinity", Value::Null), }; let e = self.new_owned_element(ty, rel, seg); @@ -3963,7 +4881,9 @@ impl Builder { fn resolve_pending(&mut self) { let pending = std::mem::take(&mut self.pending); let mut hints = self.lib_hints.take(); - let mut replay_active = hints.is_some(); + let completions = self.replay_completions.take(); + let mut replay_active = hints.is_some() && completions.is_some(); + let completions = completions.unwrap_or_default(); let recording = self.lib_record.is_some(); let mut lib_pos = 0usize; // Shadow filtering reads only recorded specialization outcomes to @@ -3978,7 +4898,12 @@ impl Builder { let is_lib_ref = self.lib_boundary > 0 && pending.elem < self.lib_boundary; let hint = if is_lib_ref && replay_active { match hints.as_mut().and_then(|it| it.next()) { - Some(hint) => Some(hint), + // An outcome that missed a root name the user units + // now supply is resolved afresh; the entry is still + // consumed to keep the positional alignment. + Some((outcome, misses)) => { + (!misses.iter().any(|m| completions.contains(m))).then_some(outcome) + } None => { replay_active = false; None @@ -4003,7 +4928,7 @@ impl Builder { }) .collect(); if let Some(record) = self.lib_record.as_mut() { - record.resize(lib_pos, None); + record.resize(lib_pos, (None, Vec::new())); } work.sort_by_key(|work| (work.pending.spec_idx.is_none(), work.source_order)); // Target-UUID validation map for replayed outcomes, built on first @@ -4032,8 +4957,9 @@ impl Builder { match lib_hint { Some(Some(id)) => { let ids = lib_ids.get_or_insert_with(|| { - self.elements[..self.lib_boundary] + self.elements .iter() + .take(self.lib_boundary) .enumerate() .map(|(i, e)| (e.id, i)) .collect() @@ -4068,7 +4994,9 @@ impl Builder { } } let (saved, saved_mode) = (self.exclude, self.declared_only); + self.query_imports.clear(); self.exclude = exclude; + self.current_misses.clear(); // Contextual chain-step resolution first (effective names are // legitimate inside the target's scope), then the recorded // lexical mode as fallback. @@ -4081,12 +5009,22 @@ impl Builder { // completed import (`import Domain::*` importing a package // that owns a member also named `Domain`). self.import_scopes(scope); - self.import_targets - .get(&(scope, qn.to_ref_string())) - .copied() - .flatten() + match self.import_targets.get(&(scope, qn.to_ref_string())) { + Some((target, walked)) => { + let walked = walked.clone(); + self.query_imports.extend(walked); + *target + } + None => None, + } } else { - self.resolve_chain_member(scope, chain.as_deref(), &qn) + let mark = self.query_imports.len(); + let hit = self.resolve_chain_member(scope, chain.as_deref(), &qn); + if hit.is_none() { + // A failed chain attempt's walks are not this site's. + self.query_imports.truncate(mark); + } + hit }; // Lexical fallback: a plain (non-chain) reference resolves from // its written scope, and a `$::`-rooted chain member re-roots @@ -4162,6 +5100,17 @@ impl Builder { plain, owner: ElementRef(elem), chain_root, + via_imports: { + let mut walks: Vec<(ElementRef, AccessMode)> = + std::mem::take(&mut self.query_imports) + .into_iter() + .map(|(rel, access)| (ElementRef(rel), access_mode(access))) + .collect(); + // Most restrictive access per import. + walks.sort_unstable(); + walks.dedup_by(|later, earlier| later.0 == earlier.0); + walks + }, }); } // Interior qualifier segments name ancestor elements @@ -4189,6 +5138,7 @@ impl Builder { plain: false, owner: ElementRef(elem), chain_root: None, + via_imports: Vec::new(), }); } } @@ -4210,6 +5160,13 @@ impl Builder { if was_ambiguous { self.ambiguous.push((elem, qn.clone())); } else { + if !is_lib_ref { + if let Some(site) = + self.blocked_site(scope, chain.as_deref(), &qn, elem) + { + self.blocked.push(site); + } + } self.unresolved.push((elem, qn.clone())); } json!({ "@ref": qn.to_ref_string() }) @@ -4223,7 +5180,10 @@ impl Builder { self.spec_resolved[si] = resolved; } if let Some(pos) = record_pos { - self.lib_record.as_mut().unwrap()[pos] = resolved.map(|t| self.elements[t].id); + self.lib_record.as_mut().unwrap()[pos] = ( + resolved.map(|t| self.elements[t].id), + std::mem::take(&mut self.current_misses), + ); } self.set_pending_value(elem, &key, value); } @@ -4242,33 +5202,17 @@ impl Builder { /// `key#n` spellings append to the `key` array property. fn set_pending_value(&mut self, elem: usize, key: &str, value: Value) { if let Some((base, _)) = key.split_once('#') { - let entry = self.elements[elem] - .props - .entry(base.to_string()) - .or_insert_with(|| Value::Array(vec![])); - if let Value::Array(a) = entry { - a.push(value); - } + self.elements[elem].props.append(base, value); } else { self.set(elem, key, value); } } - /// The elements owned by `e` through its owned memberships (any - /// Membership kind), in declaration order — KerML - /// `Namespace::ownedMember`. With `features_only`, just the members - /// owned via FeatureMembership kinds (`Type::ownedFeature`), so a - /// package answers none. Aliases own no element, so they never - /// appear; anonymous members do. - /// Element index for an interchange id string, if any element - /// carries it (see [`Self::id_index`]). - pub(crate) fn element_index_of_id(&mut self, id: &str) -> Option { - let id: Uuid = id.parse().ok()?; - let stale = self - .id_index - .as_ref() - .is_none_or(|m| m.len() != self.elements.len()); + /// Element index for a binary interchange identity. + pub(crate) fn element_index_of_uuid(&mut self, id: Uuid) -> Option { + let stale = self.id_index.is_none() || self.id_index_built_for != self.elements.len(); if stale { + self.id_index_built_for = self.elements.len(); self.id_index = Some( self.elements .iter() @@ -4280,29 +5224,54 @@ impl Builder { self.id_index.as_ref().unwrap().get(&id).copied() } + /// The multiplicity `e` declares of its own — the scope it was + /// written in and its clause — through the owner index. `None` when + /// `e` declares none; inherited ones are not walked. + pub(crate) fn declared_multiplicity_of(&mut self, e: usize) -> Option<(usize, &Multiplicity)> { + let rows = self.multiplicities.len(); + if self.mult_index.as_ref().is_none_or(|(n, _)| *n != rows) { + let mut map = HashMap::with_capacity(rows); + for (i, (owner, _, _)) in self.multiplicities.iter().enumerate() { + // First row wins, as the scan this replaces did. + map.entry(*owner).or_insert(i); + } + self.mult_index = Some((rows, map)); + } + let i = *self.mult_index.as_ref().unwrap().1.get(&e)?; + let (_, scope, mult) = &self.multiplicities[i]; + Some((*scope, mult)) + } + + /// Does `e` declare a multiplicity of its own? + pub(crate) fn declares_multiplicity(&mut self, e: usize) -> bool { + self.declared_multiplicity_of(e).is_some() + } + + /// The elements owned by `e` through its owned memberships (any + /// Membership kind), in declaration order — KerML + /// `Namespace::ownedMember`. With `features_only`, just the members + /// owned via FeatureMembership kinds (`Type::ownedFeature`), so a + /// package answers none. Aliases own no element, so they never + /// appear; anonymous members do. pub(crate) fn owned_member_elems(&self, e: usize, features_only: bool) -> Vec { - let rels: HashSet = self.elements[e] + let mut children: Vec<_> = self.elements[e] .owned_relationships .iter() .copied() .filter(|&r| { - let ty = self.elements[r].ty; if features_only { - is_feature_membership(ty) + is_feature_membership(self.elements[r].ty) } else { - ty.ends_with("Membership") + self.elements[r].ty.ends_with("Membership") } }) + .flat_map(|r| self.elements[r].children.iter().copied()) .collect(); - if rels.is_empty() { - return Vec::new(); - } - self.elements - .iter() - .enumerate() - .filter(|(_, el)| el.owning_relationship.is_some_and(|r| rels.contains(&r))) - .map(|(i, _)| i) - .collect() + // Preserve the former whole-graph scan's creation order even when + // children were appended to an earlier relationship later in lowering. + children.sort_unstable(); + children.dedup(); + children } /// Original unit index of the unit that built element `elem`. @@ -4336,6 +5305,62 @@ impl Builder { out } + /// Root memberships of user units whose name a library unit also + /// declares at the root, and that a root lookup of the name does not + /// select (the library declaration wins — earlier candidate of + /// non-overlapping metaclasses — or the pair is ambiguous). Read off + /// the shared root scope so the verdict is the lookup's own, not a + /// textual guess: a user root that *does* win the lookup is not + /// reported. Name-sorted for deterministic output. + fn check_root_shadowing(&self) -> Vec { + let mut out = Vec::new(); + if self.lib_boundary == 0 || self.scopes.is_empty() { + return out; + } + let boundary = self.lib_boundary; + let mut collisions: Vec<(String, Vec)> = self.scopes[0] + .names + .iter() + .filter(|(_, bindings)| { + bindings.iter().any(|b| b.elem < boundary) + && bindings.iter().any(|b| b.elem >= boundary) + }) + .map(|(name, bindings)| (name.to_owned(), bindings.to_vec())) + .collect(); + collisions.sort_by(|a, b| a.0.cmp(&b.0)); + for (name, bindings) in collisions { + let (library_elem, resolves_to_library) = + match self.binding_result(Some(&bindings), LookupAccess::All, None) { + LookupResult::Found(elem, _) if elem < boundary => (elem, true), + LookupResult::Found(..) => continue, + LookupResult::Ambiguous | LookupResult::Missing => { + let Some(first) = bindings.iter().find(|b| b.elem < boundary) else { + continue; + }; + (first.elem, false) + } + }; + for binding in bindings.iter().filter(|b| b.elem >= boundary) { + let elem = binding.elem; + let span = self + .decl_spans + .get(&elem) + .or_else(|| self.member_spans.get(&elem)) + .copied() + .unwrap_or_default(); + out.push(RootShadowing { + unit: self.unit_of_elem(elem), + span, + name: name.clone(), + metaclass: self.elements[elem].ty, + library_metaclass: self.elements[library_elem].ty, + resolves_to_library, + }); + } + } + out + } + /// Namespace imports that transitively import their own namespace back. /// Importing an *ancestor* namespace is not a cycle — only a loop in the /// import graph itself is. @@ -4375,6 +5400,110 @@ impl Builder { false } + /// After a user reference misses: the blocked-member record for it, + /// if a wider visibility on one member would make it resolve. The + /// probe finds the candidate; a re-resolution with that member + /// admitted as if public confirms the repair (a path through several + /// hidden members offers nothing); a second one as if protected says + /// whether the narrower keyword suffices (the site reaches the member + /// through a specialization). + fn blocked_site( + &mut self, + scope: usize, + chain: Option<&[QualifiedName]>, + qn: &QualifiedName, + owner: usize, + ) -> Option { + let (member, visibility) = self.probe_visibility_blocked(scope, chain, qn)?; + if !self.resolves_widened(scope, chain, qn, member, LookupAccess::Public) { + return None; + } + let protected_suffices = visibility == "private" + && self.resolves_widened(scope, chain, qn, member, LookupAccess::Protected); + let spelling = chain + .unwrap_or(&[]) + .iter() + .map(QualifiedName::to_display_string) + .chain(std::iter::once(qn.to_display_string())) + .collect::>() + .join("."); + Some(BlockedSite { + owner, + name: qn.clone(), + spelling, + member, + visibility, + protected_suffices, + }) + } + + /// The pending reference's own resolution, as the resolver first ran + /// it: a chain step contextually (effective names admitted), a plain + /// reference lexically under the pending's recorded mode. + fn resolve_as_pending( + &mut self, + scope: usize, + chain: Option<&[QualifiedName]>, + qn: &QualifiedName, + ) -> Option { + match chain { + Some(c) if !c.is_empty() => { + let saved = self.declared_only; + self.declared_only = false; + let found = self.resolve_chain_member(scope, Some(c), qn); + self.declared_only = saved; + found + } + _ => self.resolve(scope, qn, 0), + } + } + + /// Whether the reference resolves to `member` once that member is + /// admitted as if it had visibility `as_if` — the original access + /// modes otherwise in force. + fn resolves_widened( + &mut self, + scope: usize, + chain: Option<&[QualifiedName]>, + qn: &QualifiedName, + member: usize, + as_if: LookupAccess, + ) -> bool { + self.widen = Some((member, as_if)); + let found = self.resolve_as_pending(scope, chain, qn); + self.widen = None; + found == Some(member) + } + + /// After a miss: the member the reference would reach if visibility + /// were ignored, with its declared visibility — `None` when the name + /// is simply absent or the candidate is public anyway (the miss had + /// another cause). Runs with every access mode widened and records + /// no import use, so it never changes what the model resolves. The + /// reference's own exclusion and declared-only mode stay in force: + /// a redefinition must not capture the redefining feature through + /// its effective name. + fn probe_visibility_blocked( + &mut self, + scope: usize, + chain: Option<&[QualifiedName]>, + qn: &QualifiedName, + ) -> Option<(usize, &'static str)> { + self.probing = true; + let found = self.resolve_as_pending(scope, chain, qn); + self.probing = false; + let member = found?; + let visibility = self.elements[member] + .owning_relationship + .and_then(|rel| self.elements[rel].props.get("visibility")) + .and_then(|v| v.as_str())?; + match visibility { + "private" => Some((member, "private")), + "protected" => Some((member, "protected")), + _ => None, + } + } + /// Resolve a chain step's member in the scope of its spine target: /// resolve the first link lexically, each further link (and finally the /// member's segments) as a member — owned or inherited — of the previous @@ -4481,7 +5610,7 @@ impl Builder { depth: usize, allow_last_non_public: bool, ) -> LookupResult { - if depth > 24 || qn.segments.is_empty() { + if depth > MAX_RESOLUTION_DEPTH || qn.segments.is_empty() { return LookupResult::Missing; } let first = qn.segments[0].value.clone(); @@ -4540,20 +5669,40 @@ impl Builder { stamp: u64, access: LookupAccess, ) -> LookupResult { - if depth > 24 { - return LookupResult::Missing; - } - let mode = access as usize; - if self.visit_stamp[s][mode] == stamp { - return self.visit_result[s][mode].unwrap_or(LookupResult::Missing); + let hit = if depth > MAX_RESOLUTION_DEPTH { + LookupResult::Missing + } else { + let mode = access as usize; + if self.visit_stamp[s][mode] == stamp { + self.visit_result[s][mode].unwrap_or(LookupResult::Missing) + } else { + self.visit_stamp[s][mode] = stamp; + self.visit_result[s][mode] = None; + let hit = self.lookup_body(s, name, depth, stamp, access); + self.visit_result[s][mode] = Some(hit); + hit + } + }; + // Cyclic re-entries and depth cutoffs also count as misses; that + // only makes the prepared-path guard more conservative. + if s == 0 && hit == LookupResult::Missing { + self.note_root_miss(name); } - self.visit_stamp[s][mode] = stamp; - self.visit_result[s][mode] = None; - let hit = self.lookup_body(s, name, depth, stamp, access); - self.visit_result[s][mode] = Some(hit); hit } + // Kept out of line: `lookup_at` recurses deeply through imports and + // aliases, and unoptimized frames pay for every temporary. + #[inline(never)] + fn note_root_miss(&mut self, name: &str) { + if !self.root_misses.contains(name) { + self.root_misses.insert(name.to_owned()); + } + if !self.current_misses.iter().any(|m| m == name) { + self.current_misses.push(name.to_owned()); + } + } + fn merge_lookup(&self, left: LookupResult, right: LookupResult) -> LookupResult { match (left, right) { (LookupResult::Ambiguous, _) | (_, LookupResult::Ambiguous) => LookupResult::Ambiguous, @@ -4667,6 +5816,65 @@ impl Builder { self.scopes[self.scopes[s].parent?].owner } + /// Parameters include membership-defined subjects/actors and ordinary + /// directed features (`in`, `out`, `inout`) in calculation/action bodies. + pub(crate) fn is_parameter(&self, e: usize) -> bool { + self.elements[e].owning_relationship.is_some_and(|r| { + crate::metaclass::conforms(self.elements[r].ty, "ParameterMembership") + || (is_feature_membership(self.elements[r].ty) + && self.elements[e] + .props + .get("direction") + .and_then(|v| v.as_str()) + .is_some()) + }) + } + + /// A featured reference stands for another instance. Package-owned + /// usages also have isComposite=false, but remain ordinary usages + /// whose type defaults can be evaluated directly. + pub(crate) fn is_reference_feature(&self, e: usize) -> bool { + self.is_parameter(e) + || (self.elements[e] + .props + .get("isComposite") + .and_then(|v| v.as_bool()) + == Some(false) + && self.elements[e] + .owning_relationship + .is_some_and(|r| is_feature_membership(self.elements[r].ty))) + } + + /// Whether `e` declares its own non-default value expression. The + /// expression is fixed; its result may still depend on unknown inputs. + pub(crate) fn has_own_fixed_value(&self, e: usize) -> bool { + self.values.contains_key(&e) && !self.default_values.contains(&e) + } + + /// Whether evaluating this calculation would require running statements, + /// including a body inherited through typing or specialization. + pub(crate) fn calculation_requires_execution(&self, elem: usize) -> bool { + if self.executable_calculations.is_empty() { + return false; + } + let mut stack = vec![elem]; + let mut seen = HashSet::new(); + while let Some(e) = stack.pop() { + if !seen.insert(e) { + continue; + } + if self.executable_calculations.contains(&e) { + return true; + } + for (i, (owner, _, _, _)) in self.spec_targets.iter().enumerate() { + if *owner == e { + stack.extend(self.spec_resolved.get(i).copied().flatten()); + } + } + } + false + } + /// Is `sup` reachable from `sub` through *recorded* explicit /// specialization outcomes? Like [`Self::recorded_redefinition_targets`], /// a direct scan with no resolution and no index — this runs inside @@ -4723,15 +5931,118 @@ impl Builder { out } + /// [`Self::recorded_redefinition_targets`] through the specialization + /// index — for callers that run after lowering, when the index is + /// permanent (enumeration; never `lookup_body`). + pub(crate) fn indexed_redefinition_targets(&mut self, e: usize) -> Vec { + self.ensure_spec_index(); + let mut out = Vec::new(); + if let Some(entries) = self.spec_index.as_ref().unwrap().get(&e) { + for &i in entries { + if self.spec_targets[i].1 != "Redefinition" { + continue; + } + if let Some(t) = self.spec_resolved.get(i).copied().flatten() { + if t != e && !out.contains(&t) { + out.push(t); + } + } + } + } + out + } + + /// The element owning scope `s` (the type whose body it is), if any. + pub(crate) fn scope_owner(&self, s: usize) -> Option { + self.scopes[s].owner + } + + /// The resolved explicit specialization targets of `e` spelled with + /// one of the relationship `kinds` (`"Subsetting"`, `"Redefinition"`, + /// `"FeatureTyping"`, `"Subclassification"`), through the + /// specialization index (same caller restriction as + /// [`Self::indexed_redefinition_targets`]). + pub(crate) fn indexed_specialization_targets( + &mut self, + e: usize, + kinds: &[&str], + ) -> Vec { + self.ensure_spec_index(); + let mut out = Vec::new(); + if let Some(entries) = self.spec_index.as_ref().unwrap().get(&e) { + for &i in entries { + if !kinds.contains(&self.spec_targets[i].1) { + continue; + } + if let Some(t) = self.spec_resolved.get(i).copied().flatten() { + if t != e && !out.contains(&t) { + out.push(t); + } + } + } + } + out + } + + /// [`Self::recorded_conforms`] through the specialization index (same + /// caller restriction as [`Self::indexed_redefinition_targets`]). + pub(crate) fn indexed_conforms(&mut self, sub: usize, sup: usize) -> bool { + if sub == sup { + return true; + } + self.ensure_spec_index(); + let index = self.spec_index.as_ref().unwrap(); + let mut stack = vec![sub]; + let mut seen = HashSet::new(); + while let Some(x) = stack.pop() { + if !seen.insert(x) { + continue; + } + for &i in index.get(&x).into_iter().flatten() { + if let Some(t) = self.spec_resolved.get(i).copied().flatten() { + if t == sup { + return true; + } + if t != x { + stack.push(t); + } + } + } + } + false + } + + /// Whether the import relationship `rel` contributes memberships to a + /// walk running at `access`: the import's own visibility must be + /// admitted (KerML `nonPrivateMemberships` takes the public and the + /// protected imports; `expose` is protected). Unspelled means public. + fn import_admitted(&self, rel: usize, access: LookupAccess) -> bool { + let vis = match self.elements[rel] + .props + .get("visibility") + .and_then(|a| a.as_str()) + { + Some("private") => LookupAccess::All, + Some("protected") => LookupAccess::Protected, + _ => LookupAccess::Public, + }; + access.admits(vis) + } + fn binding_result( &self, - bindings: Option<&Vec>, + bindings: Option<&[Binding]>, access: LookupAccess, exclude: Option, ) -> LookupResult { let mut result = LookupResult::Missing; for binding in bindings.into_iter().flatten().copied() { - if Some(binding.elem) == exclude || !access.admits(binding.visibility) { + if Some(binding.elem) == exclude { + continue; + } + let widened = + matches!(self.widen, Some((e, as_if)) if e == binding.elem && access.admits(as_if)); + if !access.admits(binding.visibility) && !widened { continue; } result = @@ -4748,11 +6059,28 @@ impl Builder { stamp: u64, access: LookupAccess, ) -> LookupResult { + let access = if self.probing { + LookupAccess::All + } else { + access + }; let direct = self.binding_result(self.scopes[s].names.get(name), access, self.exclude); if direct != LookupResult::Missing { return direct; } - if !self.declared_only { + // An excluded redefining feature's target must not be supplied + // by anonymous siblings borrowing that same target's name. Keep + // declared local names and inherited effective names available. + // This applies equally to pending relationship refs and base-scope + // lookup, so emitted edges and inherited member lookup agree. + let circular_effective_name = self + .exclude + .and_then(|e| self.elem_scope.get(&e)) + .is_some_and(|&own| { + self.scopes[own].parent == Some(s) + && self.scopes[own].redefinition_names.contains(name) + }); + if !self.declared_only && !circular_effective_name { let effective = self.binding_result( self.scopes[s].effective_names.get(name), access, @@ -4815,7 +6143,10 @@ impl Builder { match resolved { LookupResult::Found(elem, _) => { if self.filters_admit(s, &entry.filters, elem, depth) { - self.used_imports.insert(entry.relationship); + if !self.probing { + self.used_imports.insert(entry.relationship); + self.query_imports.push((entry.relationship, access)); + } let sub = self.elem_scope.get(&elem).copied(); imported_members = self.merge_lookup(imported_members, LookupResult::Found(elem, sub)); @@ -4873,7 +6204,10 @@ impl Builder { match hit { LookupResult::Found(elem, sub) => { if self.filters_admit(s, &entry.filters, elem, depth) { - self.used_imports.insert(entry.relationship); + if !self.probing { + self.used_imports.insert(entry.relationship); + self.query_imports.push((entry.relationship, access)); + } imported = self.merge_lookup(imported, LookupResult::Found(elem, sub)); } } @@ -4895,9 +6229,14 @@ impl Builder { stamp: u64, access: LookupAccess, ) -> LookupResult { - if depth > 24 { + if depth > MAX_RESOLUTION_DEPTH { return LookupResult::Missing; } + let access = if self.probing { + LookupAccess::All + } else { + access + }; let mut result = self.lookup_at(s, name, depth, stamp, access); let mut subs: Vec = self.scopes[s] .names @@ -4928,6 +6267,19 @@ impl Builder { if let Some(cached) = &self.import_cache[s] { return cached.clone(); } + // The cache outlives any query: it must never hold what a + // visibility-blind probe or a widened member would resolve. + let (probing, widen) = ( + std::mem::replace(&mut self.probing, false), + self.widen.take(), + ); + let result = self.import_scopes_uncached(s); + self.probing = probing; + self.widen = widen; + result + } + + fn import_scopes_uncached(&mut self, s: usize) -> Vec { // Placeholder breaks cycles while computing. An import target may // itself be visible only through an earlier import of the same // scope (`import P::*; import P_Member::*;`), and resolving it @@ -4940,17 +6292,21 @@ impl Builder { self.import_cache[s] = Some(Vec::new()); let imports = self.scopes[s].imports.clone(); let mut outcomes: Vec> = vec![None; imports.len()]; + let mut walked: Vec = vec![Vec::new(); imports.len()]; + // The resolved outcomes, in import order, as the cache wants them. + // The vector is handed to the cache and taken back rather than + // rebuilt per entry, with entry `i`'s own row lifted out for the + // duration of its resolve — rebuilding it would copy every other + // entry's outcome once per entry per pass. + let mut seeds: Vec = Vec::new(); for _ in 0..=imports.len() { let mut changed = false; for i in 0..imports.len() { let entry = imports[i].clone(); - let others: Vec = outcomes - .iter() - .enumerate() - .filter(|(j, o)| *j != i && o.is_some()) - .map(|(_, o)| o.as_ref().unwrap().1.clone()) - .collect(); - self.import_cache[s] = Some(others); + let at = outcomes[..i].iter().filter(|o| o.is_some()).count(); + let mine = outcomes[i].as_ref().map(|_| seeds.remove(at)); + self.import_cache[s] = Some(std::mem::take(&mut seeds)); + let mark = self.query_imports.len(); let next = self.resolve(s, &entry.target, 0).and_then(|elem| { self.elem_scope.get(&elem).map(|&sc| { ( @@ -4966,9 +6322,18 @@ impl Builder { ) }) }); + walked[i] = self.query_imports.drain(mark..).collect(); + // Re-entry into this scope reads the seed; it never + // replaces it, so the vector comes back as it was left. + seeds = self.import_cache[s].take().unwrap_or_default(); if next != outcomes[i] { + if let Some((_, scope)) = &next { + seeds.insert(at, scope.clone()); + } outcomes[i] = next; changed = true; + } else if let Some(mine) = mine { + seeds.insert(at, mine); } } if !changed { @@ -4982,7 +6347,10 @@ impl Builder { let mut result: Vec = Vec::new(); for (i, o) in outcomes.into_iter().enumerate() { let key = (s, imports[i].target.to_ref_string()); - self.import_targets.insert(key, o.as_ref().map(|(e, _)| *e)); + self.import_targets.insert( + key, + (o.as_ref().map(|(e, _)| *e), std::mem::take(&mut walked[i])), + ); if let Some((_, scope)) = o { if !result.contains(&scope) { result.push(scope); @@ -5032,7 +6400,7 @@ impl Builder { /// resolution walks back through the filtered import) answers /// undecided. fn filter_verdict(&mut self, fid: usize, elem: usize, depth: usize) -> Tri { - if depth > 24 || self.filters_active[fid] { + if depth > MAX_RESOLUTION_DEPTH || self.filters_active[fid] { return Tri::Unknown; } self.filters_active[fid] = true; @@ -5087,19 +6455,25 @@ impl Builder { ExprKind::Classification { op: ClassificationOp::AtType, operand: None, - ty: TargetRef::Name(qn), - } => self.metadata_test(scope, qn, elem, depth), + ty, + } => match ty.as_name() { + Some(qn) => self.metadata_test(scope, qn, elem, depth), + None => Tri::Unknown, + }, // `(as M).attr` — a boolean attribute of the candidate's `M` // metadata annotation. ExprKind::ChainStep { target, member } => { let ExprKind::Classification { op: ClassificationOp::As, operand: None, - ty: TargetRef::Name(meta_qn), + ty, } = &target.kind else { return Tri::Unknown; }; + let TargetRef::Name(meta_qn) = &**ty else { + return Tri::Unknown; + }; let TargetRef::Name(attr) = member else { return Tri::Unknown; }; @@ -5280,11 +6654,40 @@ impl Builder { /// scope `s` (inherited-member resolution). Base names resolve from the /// owning scope's parent. fn base_scopes(&mut self, s: usize) -> Vec { + self.base_scopes_split(s).0 + } + + /// [`Self::base_scopes`] with the explicit/implied boundary: the + /// returned `usize` is the count of leading entries resolved from + /// *written* heritage (specializations, typings, chain bases); the + /// remainder are implied (Tables 31/32 library bases, binary connector + /// bases, implicit parameter redefinition, semantic metadata). + pub(crate) fn base_scopes_split(&mut self, s: usize) -> (Vec, usize) { if let Some(cached) = &self.base_cache[s] { return cached.clone(); } - self.base_cache[s] = Some(Vec::new()); + // As for `import_scopes`: cached bases never come from a probe, + // and the import walks that resolve the base names belong to the + // specialization's own reference sites, not to whichever lookup + // first fills the cache — a prepared library rebuilds its base + // caches under the user's lookups, and cold and warm builds must + // record identical sites. + let (probing, widen) = ( + std::mem::replace(&mut self.probing, false), + self.widen.take(), + ); + let mark = self.query_imports.len(); + let result = self.base_scopes_uncached(s); + self.query_imports.truncate(mark); + self.probing = probing; + self.widen = widen; + result + } + + fn base_scopes_uncached(&mut self, s: usize) -> (Vec, usize) { + self.base_cache[s] = Some((Vec::new(), 0)); let bases = self.scopes[s].bases.clone(); + let implied_bases = self.scopes[s].implied_bases.clone(); let chain_bases = self.scopes[s].chain_bases.clone(); let from = self.scopes[s].parent.unwrap_or(s); let mut result = Vec::new(); @@ -5320,6 +6723,16 @@ impl Builder { } } } + let explicit = result.len(); + for qn in &implied_bases { + if let Some(elem) = self.resolve(from, qn, 0) { + if let Some(&sc) = self.elem_scope.get(&elem) { + if sc != s && !result.contains(&sc) { + result.push(sc); + } + } + } + } self.exclude = saved; // Semantic metadata (KerML 9.2 metaobject semantics): an element // annotated with a SemanticMetadata subtype implicitly specializes @@ -5335,10 +6748,564 @@ impl Builder { } } } - self.base_cache[s] = Some(result.clone()); + self.base_cache[s] = Some((result.clone(), explicit)); + (result, explicit) + } + + /// Enumerate the members scope `s` inherits through its heritage — + /// the resolver's own walk ([`Self::base_scopes_split`]) run for + /// enumeration instead of name lookup. Returns + /// `(member element, contributing scope)` pairs — the heritage scope + /// or import that made the member visible — in breadth-first heritage + /// order, members within a level in creation (document) order (the + /// lowest-numbered contributing scope wins a tie, so the pairs are + /// deterministic), plus the inherited **alias Membership** + /// relationship indices from the heritage scopes and from every + /// imported scope the walk visited, and whether a depth guard cut + /// the walk short. Memoized per (scope, `include_implied`). + /// + /// Inheritance semantics (KerML `inheritableMemberships` / + /// `nonPrivateMemberships`, enumerated): + /// - private memberships do not inherit; **public and protected imported + /// memberships re-export** through heritage (membership imports, + /// namespace imports incl. `::**`, re-export chains, filter + /// conditions applied); + /// - removal is **redefinition-driven, not name-driven**: a member is + /// dropped when another *inherited* candidate (transitively) + /// redefines it, when its own redefinition closure meets a feature + /// **directly** redefined by an **owned** feature (the OCL + /// `ownedFeature.redefinition.redefinedFeature` intersection — one + /// hop from the owned side, by the normative text; redefiners of + /// unrelated branches never suppress each other), or under SysML's + /// implicit same-name usage redefinition + /// (strict one-way owner conformance — see `drop_redefined_hits`). + /// Same-name members of unrelated heritage branches are all + /// retained (name lookup answers ambiguous; the memberships still + /// inherit); + /// - `include_implied` extends the walk over the implied heritage + /// (Tables 31/32 library bases, binary connector bases, implicit + /// parameter redefinition, semantic metadata) at *every* level. + /// + /// Deliberate deviations from the normative operation: member + /// *elements* are returned, not Membership relationships; the + /// `excluded` namespace/type parameters are not taken; alias + /// memberships are not enumerated (they denote members declared + /// elsewhere — resolve them through lookup). Nearer-level direct + /// redefinitions are pooled across heritage branches for the + /// intersection condition (the same cross-branch approximation + /// lookup's `drop_redefined_hits` makes). + pub(crate) fn inherited_bindings( + &mut self, + s: usize, + include_implied: bool, + ) -> Arc { + if let Some(hit) = self.inherited_cache.get(&(s, include_implied)) { + return Arc::clone(hit); + } + // Enumeration resolves bases and import targets the way lookup + // does; that must not count as a use of the model's imports. + // (Its lookups may also add root-miss guard entries, which only + // make the prepared-path guard more conservative.) + let used_imports = self.used_imports.clone(); + let query_imports = std::mem::take(&mut self.query_imports); + // A scope with no members, imports or aliases of its own + // contributes nothing to its enumeration but its heritage. + let heritage_key = { + let sc = &self.scopes[s]; + (sc.names.values().next().is_none() + && sc.effective_names.values().next().is_none() + && sc.imports.is_empty() + && sc.member_imports.is_empty() + && sc.aliases.is_empty() + && sc.implied_ends.is_empty()) + .then(|| (self.base_scopes_split(s).0, include_implied)) + }; + let result = match heritage_key + .as_ref() + .and_then(|k| self.inherited_by_heritage.get(k)) + { + Some(hit) => Arc::clone(hit), + None => { + let result = Arc::new(self.inherited_bindings_uncached(s, include_implied)); + if let Some(k) = heritage_key { + self.inherited_by_heritage.insert(k, Arc::clone(&result)); + } + result + } + }; + self.used_imports = used_imports; + self.query_imports = query_imports; + self.inherited_cache + .insert((s, include_implied), Arc::clone(&result)); result } + fn inherited_bindings_uncached( + &mut self, + s: usize, + include_implied: bool, + ) -> InheritedBindings { + let heritage = |b: &mut Self, sc: usize| { + let (all, explicit) = b.base_scopes_split(sc); + if include_implied { + all + } else { + all[..explicit].to_vec() + } + }; + let mut visited: HashSet = HashSet::from([s]); + let mut level: Vec = heritage(self, s) + .into_iter() + .filter(|&b| visited.insert(b)) + .collect(); + // (element, contributing scope), breadth-first. + let mut collected: Vec<(usize, usize)> = Vec::new(); + let mut seen_elems: HashSet = HashSet::new(); + let mut alias_rels: Vec = Vec::new(); + let mut truncated = false; + for _depth in 1..=MAX_RESOLUTION_DEPTH { + if level.is_empty() { + break; + } + // This level's visible bindings, deterministically ordered by + // element creation index, then contributing scope (HashMap + // iteration order must never reach the result). + let mut found: Vec<(usize, usize)> = Vec::new(); + for &b in &level { + for map in [&self.scopes[b].names, &self.scopes[b].effective_names] { + for bindings in map.values() { + for binding in bindings { + if binding.visibility == LookupAccess::All { + continue; // private: not inherited + } + found.push((binding.elem, b)); + } + } + } + // Public imported memberships re-export through + // heritage (KerML nonPrivateMemberships); alias + // memberships inherit at inherited access. + let mut imported = InheritedBindings::default(); + self.imported_bindings(b, include_implied, LookupAccess::Protected, &mut imported); + found.extend(imported.members); + alias_rels.extend(imported.alias_rels); + truncated |= imported.truncated; + self.scope_alias_rels(b, LookupAccess::Protected, &[], &mut alias_rels); + } + found.sort_unstable(); + for (elem, scope) in found { + if seen_elems.insert(elem) { + collected.push((elem, scope)); + } + } + level = level + .clone() + .into_iter() + .flat_map(|b| heritage(self, b)) + .filter(|&b| visited.insert(b)) + .collect(); + } + // Heritage still pending after the last level means the budget, + // not the model, ended the walk. + truncated |= !level.is_empty(); + // Redefinition-driven removal (KerML removeRedefinedFeatures + + // the owned-features intersection condition + SysML implicit + // same-name usage redefinition). Owned members participate as + // depth 0. + let owned: Vec = { + let mut o: Vec = self.scopes[s] + .names + .values() + .chain(self.scopes[s].effective_names.values()) + .flatten() + .map(|b| b.elem) + .collect(); + o.sort_unstable(); + o.dedup(); + o + }; + // (a) KerML removeRedefinedFeatures, first condition: a candidate + // included in the redefined Features of *another inherited + // candidate* (its member plus everything it transitively + // redefines) is removed. Owned features do not seed this + // condition — they act through condition (b) only. + let mut shadow: HashSet = HashSet::new(); + let mut closures: HashMap> = HashMap::new(); + for &(e, _) in &collected { + let mut cl = HashSet::new(); + let mut stack = self.indexed_redefinition_targets(e); + while let Some(t) = stack.pop() { + if cl.insert(t) { + stack.extend(self.indexed_redefinition_targets(t)); + } + } + shadow.extend(cl.iter().copied()); + closures.insert(e, cl); + } + // (b) Intersection condition (KerML removeRedefinedFeatures, + // second condition — owned features only): an inherited + // member whose redefinition closure meets a feature + // *directly* redefined by an **owned** feature is not + // inherited (owned `z :>> A::x` removes the sibling + // `y :>> x` arriving from farther up). Redefiners inherited + // from unrelated branches never suppress one another. + let mut owned_direct: HashSet = HashSet::new(); + for &e in &owned { + owned_direct.extend(self.indexed_redefinition_targets(e)); + } + for &(e, _) in &collected { + if shadow.contains(&e) { + continue; + } + // The member itself counts among its redefined Features + // (OCL allRedefinedFeaturesOf includes the memberElement). + if owned_direct.contains(&e) { + shadow.insert(e); + continue; + } + let Some(cl) = closures.get(&e) else { continue }; + if cl.iter().any(|t| owned_direct.contains(t)) { + shadow.insert(e); + } + } + // (c) SysML implicit same-name usage redefinition: a usage-family + // member whose owning type strictly conforms over another + // candidate's owner redefines the same-named candidate + // without a spelled `:>>`. + let mut by_name: HashMap<&str, Vec> = HashMap::new(); + for e in owned + .iter() + .copied() + .chain(collected.iter().map(|&(e, _)| e)) + { + // Both spellings share the lookup name space: a short name can + // shadow (or be shadowed by) a declared name, as in lookup. + for key in ["declaredName", "declaredShortName"] { + if let Some(n) = self.elements[e].props.get(key).and_then(|a| a.as_str()) { + by_name.entry(n).or_default().push(e); + } + } + } + let groups: Vec> = by_name.into_values().filter(|g| g.len() > 1).collect(); + let mut implicit_redefinitions: Vec<(usize, usize)> = Vec::new(); + for group in groups { + for &x in &group { + if !self.elements[x].ty.ends_with("Usage") || shadow.contains(&x) { + continue; + } + let Some(ox) = self.owner_elem(x) else { + continue; + }; + for &y in &group { + if x == y || shadow.contains(&y) { + continue; + } + let Some(oy) = self.owner_elem(y) else { + continue; + }; + if ox != oy && self.indexed_conforms(ox, oy) && !self.indexed_conforms(oy, ox) { + shadow.insert(y); + implicit_redefinitions.push((y, x)); + } + } + } + } + let members = collected + .into_iter() + .filter(|&(e, _)| !shadow.contains(&e)) + .collect(); + implicit_redefinitions.sort_unstable(); + implicit_redefinitions.dedup(); + InheritedBindings { + members, + alias_rels, + truncated, + implicit_redefinitions, + } + } + + /// The bindings scope `b`'s imports contribute at `admitted` access — + /// the enumeration counterpart of `lookup_body`'s import arms: + /// `Protected` for an inheriting type (public and protected imports + /// of the base re-export, private ones do not — KerML + /// `nonPrivateMemberships`), `All` for the namespace's own + /// `importedMembership` (every owned import, whatever its + /// visibility). Member elements, alias Membership relationship + /// indices and the truncation flag land in `out`. + fn imported_bindings( + &mut self, + b: usize, + include_implied: bool, + admitted: LookupAccess, + out: &mut InheritedBindings, + ) { + let member_imports = self.scopes[b].member_imports.clone(); + for entry in member_imports { + if !self.import_admitted(entry.relationship, admitted) { + continue; + } + if let Some(elem) = self.resolve(b, &entry.target, 0) { + if self.filters_admit(b, &entry.filters, elem, 0) { + out.members.push((elem, b)); + } + } + } + let mut seen: HashSet = HashSet::new(); + for entry in self.import_scopes(b) { + if !self.import_admitted(entry.relationship, admitted) { + continue; + } + let access = if entry.is_import_all { + LookupAccess::All + } else { + LookupAccess::Public + }; + let chain = vec![(b, entry.filters.clone())]; + self.collect_import_scope( + entry.scope, + access, + entry.recursive, + include_implied, + &chain, + &mut seen, + out, + 0, + ); + } + } + + /// Enumerate what one namespace-import edge makes visible in scope + /// `sc` — the faithful mirror of `lookup_at` + `lookup_recursive` + /// over that scope: + /// - own (and effective-)named bindings admitted by `access`; + /// - alias memberships admitted by `access`; + /// - the scope's own member imports and namespace re-exports, each + /// under **its own** policy (filters, `import all`, `::**`) — an + /// outer entry never overrides a nested entry's policy; filter + /// conditions **compose** along the path (`chain`); + /// - the scope's heritage (`base_scopes`), at inherited access — + /// lookup resolves inherited members through an import, so + /// enumeration follows; + /// - for `::**` (`recursive`), descent into owned named members' + /// scopes only — exactly `lookup_recursive`'s traversal. + #[allow(clippy::too_many_arguments)] + fn collect_import_scope( + &mut self, + sc: usize, + access: LookupAccess, + recursive: bool, + include_implied: bool, + chain: &[(usize, Vec)], + seen: &mut HashSet, + out: &mut InheritedBindings, + depth: usize, + ) { + // The filter chain is part of the visit key: a scope first reached + // through a filtered path must still be visited through an + // unfiltered one, whatever the import order. + let mut signature: Vec<(usize, usize)> = chain + .iter() + .flat_map(|(scope, filters)| { + // The import's bracket filters plus the importing scope's own + // `filter` members, which `filters_admit` applies as well. + filters + .iter() + .chain(self.scopes[*scope].filters.iter()) + .map(move |&f| (*scope, f)) + }) + .collect(); + signature.sort_unstable(); + signature.dedup(); + let key: ImportVisit = (sc, access as u8, recursive, signature); + if seen.contains(&key) { + return; + } + // A cut visit is not recorded, so a shorter path found later can + // still complete it; only a genuinely new visit counts as a cut. + if depth > MAX_RESOLUTION_DEPTH { + out.truncated = true; + return; + } + seen.insert(key); + let mut candidates: Vec = Vec::new(); + for map in [&self.scopes[sc].names, &self.scopes[sc].effective_names] { + for bindings in map.values() { + for binding in bindings { + if access.admits(binding.visibility) { + candidates.push(binding.elem); + } + } + } + } + candidates.sort_unstable(); + candidates.dedup(); + for elem in candidates { + if self.chain_admits(chain, elem) { + out.members.push((elem, sc)); + } + } + self.scope_alias_rels(sc, access, chain, &mut out.alias_rels); + let member_imports = self.scopes[sc].member_imports.clone(); + for entry in member_imports { + if !self.import_admitted(entry.relationship, access) { + continue; + } + if let Some(elem) = self.resolve(sc, &entry.target, 0) { + if self.filters_admit(sc, &entry.filters, elem, 0) && self.chain_admits(chain, elem) + { + out.members.push((elem, sc)); + } + } + } + for sub in self.import_scopes(sc) { + if !self.import_admitted(sub.relationship, access) { + continue; + } + let sub_access = if sub.is_import_all { + LookupAccess::All + } else { + LookupAccess::Public + }; + let mut chain2 = chain.to_vec(); + chain2.push((sc, sub.filters.clone())); + self.collect_import_scope( + sub.scope, + sub_access, + sub.recursive, + include_implied, + &chain2, + seen, + out, + depth + 1, + ); + } + let (bases, explicit) = self.base_scopes_split(sc); + let bases = if include_implied { + bases + } else { + bases[..explicit].to_vec() + }; + for base in bases { + self.collect_import_scope( + base, + access.inherited(), + false, + include_implied, + chain, + seen, + out, + depth + 1, + ); + } + if recursive { + let mut subs: Vec = self.scopes[sc] + .names + .values() + .flatten() + .filter(|b| access.admits(b.visibility)) + .filter_map(|b| b.sub_scope) + .collect(); + subs.sort_unstable(); + subs.dedup(); + for sub in subs { + self.collect_import_scope( + sub, + access, + true, + include_implied, + chain, + seen, + out, + depth + 1, + ); + } + } + } + + /// Every filter set along an import path admits `elem`. + fn chain_admits(&mut self, chain: &[(usize, Vec)], elem: usize) -> bool { + chain + .iter() + .all(|(scope, filters)| self.filters_admit(*scope, filters, elem, 0)) + } + + /// Alias Membership relationships of scope `sc` admitted by `access` + /// (an alias's declared visibility maps like a member's) and by the + /// filter chain, tested against the alias's resolved target when it + /// resolves. Appended in relationship-creation order. + fn scope_alias_rels( + &mut self, + sc: usize, + access: LookupAccess, + chain: &[(usize, Vec)], + alias_out: &mut Vec, + ) { + let Some(owner) = self.scopes[sc].owner else { + return; + }; + let rels: Vec = self.elements[owner] + .owned_relationships + .iter() + .copied() + .filter(|&r| { + if self.elements[r].ty != "Membership" { + return false; + } + let named = self.elements[r] + .props + .get("memberName") + .is_some_and(|v| !v.is_null()) + || self.elements[r] + .props + .get("memberShortName") + .is_some_and(|v| !v.is_null()); + if !named { + return false; + } + let vis = match self.elements[r] + .props + .get("visibility") + .and_then(|a| a.as_str()) + { + Some("private") => LookupAccess::All, + Some("protected") => LookupAccess::Protected, + _ => LookupAccess::Public, + }; + access.admits(vis) + }) + .collect(); + for r in rels { + if let Some(target) = self.alias_target_elem(r) { + if !self.chain_admits(chain, target) { + continue; + } + } + alias_out.push(r); + } + } + + /// The element an alias Membership's resolved `memberElement` + /// denotes, when it resolved to an in-model id. + fn alias_target_elem(&mut self, rel: usize) -> Option { + let id = self.elements[rel] + .props + .get("memberElement")? + .as_reference()?; + self.element_index_of_uuid(id) + } + + /// The bases used by member lookup, including implicit library bases and + /// semantic metadata. This query preserves lookup's self-exclusion rules. + pub(crate) fn context_bases(&mut self, e: usize) -> Vec { + let Some(&scope) = self.elem_scope.get(&e) else { + return Vec::new(); + }; + self.base_scopes(scope) + .into_iter() + .filter_map(|s| self.scopes[s].owner) + .collect() + } + /// The resolved `baseType` targets of the element's SemanticMetadata /// annotations: for each annotation whose metadata definition conforms /// to `Metaobjects::SemanticMetadata`, resolve the definition's @@ -5347,7 +7314,7 @@ impl Builder { /// scope that value was written in. Never serialized — consumed by /// [`Self::base_scopes`] as implied bases only. fn semantic_base_targets(&mut self, elem: usize, depth: usize) -> Vec { - if depth > 24 { + if depth > MAX_RESOLUTION_DEPTH { return Vec::new(); } let metas = match self.metadata_of.get(&elem) { @@ -5849,28 +7816,6 @@ fn bare_end_member(m: &Member) -> Option { }) } -/// Recursively replace remapped `@id` values inside a JSON value. -fn patch_ids(v: &mut Value, remap: &HashMap) { - match v { - Value::Object(m) => { - if let Some(Value::String(id)) = m.get_mut("@id") { - if let Some(new) = remap.get(id.as_str()) { - *id = new.clone(); - } - } - for x in m.values_mut() { - patch_ids(x, remap); - } - } - Value::Array(a) => { - for x in a { - patch_ids(x, remap); - } - } - _ => {} - } -} - /// Build a [`QualifiedName`] for a library path like `"Parts::Part"`. /// The left spine of a feature-chain expression as link names, when it is /// statically a plain name chain (`subscribing.sub` → `[subscribing, sub]`). @@ -5886,9 +7831,9 @@ fn chain_spine(e: &Expr) -> Option> { // the filter idiom `(as T).m` — is a member of `T`. ExprKind::Classification { op: ClassificationOp::As, - ty: TargetRef::Name(qn), + ty, .. - } => Some(vec![qn.clone()]), + } => Some(vec![ty.as_name()?.clone()]), ExprKind::ChainStep { target, member } => { let mut spine = chain_spine(target)?; let TargetRef::Name(qn) = member else { @@ -5970,6 +7915,89 @@ fn process_comment_body_once(body: &str) -> String { /// Effective name of an unnamed feature: the last segment of the first /// redefined (KerML 8.2.3.5) or referenced (SysML reference forms) feature, /// in declaration order. +fn id_matches(id: &Identification, name: &str) -> bool { + [&id.name, &id.short_name] + .into_iter() + .flatten() + .any(|n| n.value == name) +} + +/// The usage a member declares directly or through a role keyword. +fn member_usage(m: &Member) -> Option<&Usage> { + match &m.kind { + MemberKind::Usage(u) + | MemberKind::Subject(u) + | MemberKind::Actor(u) + | MemberKind::Stakeholder(u) + | MemberKind::Objective(u) + | MemberKind::FramedConcern(u) + | MemberKind::RequirementVerification(u) + | MemberKind::Render(u) + | MemberKind::Return(u) => Some(u), + _ => None, + } +} + +fn member_id(m: &Member) -> Option<&Identification> { + match &m.kind { + MemberKind::Package(p) => Some(&p.id), + MemberKind::Definition(d) => Some(&d.id), + MemberKind::Alias(a) => Some(&a.id), + MemberKind::Dependency(d) => Some(&d.id), + MemberKind::Relationship(r) => Some(&r.id), + MemberKind::MultiplicityDecl(d) => Some(&d.id), + MemberKind::Comment(c) => Some(&c.id), + MemberKind::Doc(d) => Some(&d.id), + MemberKind::TextualRep(r) => Some(&r.id), + _ => member_usage(m).map(|u| &u.declaration.id), + } +} + +fn member_body(m: &Member) -> Option<&[Member]> { + match &m.kind { + MemberKind::Package(p) => p.body.as_deref(), + MemberKind::Definition(d) => d.body.as_deref(), + _ => member_usage(m).and_then(|u| u.body.as_deref()), + } +} + +/// The names one syntactic member contributes to its namespace. `None` for +/// members whose contribution needs resolution (re-exporting imports). +fn member_names(m: &Member, out: &mut HashSet) -> Option<()> { + match &m.kind { + MemberKind::Import(_) | MemberKind::Expose(_) => return None, + MemberKind::Filter(_) | MemberKind::Result(_) | MemberKind::InitialNode(_) => { + return Some(()); + } + _ => {} + } + let id = member_id(m)?; + out.extend( + [&id.name, &id.short_name] + .into_iter() + .flatten() + .map(|n| n.value.clone()), + ); + if let Some(u) = member_usage(m) { + if u.declaration.id.name.is_none() { + out.extend(effective_ref_name(&u.declaration)); + } + } + Some(()) +} + +fn user_member_names(members: &[Member], recursive: bool, out: &mut HashSet) -> Option<()> { + for m in members { + member_names(m, out)?; + if recursive { + if let Some(body) = member_body(m) { + user_member_names(body, true, out)?; + } + } + } + Some(()) +} + fn effective_ref_name(d: &FeatureDeclaration) -> Option { for s in &d.specializations { let target = match s { @@ -6352,19 +8380,21 @@ pub(crate) fn is_feature_membership(ty: &str) -> bool { /// An opaque handle to one element of a resolved model. Ordering follows /// element creation order — document/declaration order within a unit. -#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive( + Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, serde::Serialize, serde::Deserialize, +)] pub struct ElementRef(pub(crate) usize); /// An opaque handle to one name-resolution scope of a resolved model (a /// namespace body an expression's references resolve from). -#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)] +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, serde::Serialize, serde::Deserialize)] pub struct ScopeRef(pub(crate) usize); /// One resolved reference site: a qualified name written in a user unit /// and the element it resolved to (see [`ResolvedModel::references_to`]). /// The enabling record for find-usages and rename — a rename must respell /// the `name_span` text at every site of its element. -#[derive(Clone, Debug)] +#[derive(Clone, Debug, serde::Serialize, serde::Deserialize)] pub struct RefSite { /// Index into [`crate::model::Model::units`] of the unit the /// reference was written in. @@ -6406,6 +8436,12 @@ pub struct RefSite { /// *through* that usage, not through its definition — the distinction /// relocation eligibility runs on. pub chain_root: Option, + /// The import relationships the resolution walked through — the + /// imports this site depends on — each with the most restrictive + /// access any walk of it ran under. Sorted by import; empty for + /// `qualifier` sites and for sites replayed from a cache. + #[serde(default)] + pub via_imports: Vec<(ElementRef, AccessMode)>, } /// One reference that failed to resolve, with enough source provenance @@ -6487,9 +8523,17 @@ pub struct ResolvedModel { /// Relationship index → owning element, built lazily by /// [`Self::element_qualified_name`] (empty until first use). rel_owner: Vec>, + /// Membership index → owned member element, built lazily by + /// [`Self::membership_member`] (empty until first use). + rel_member: Vec>, /// Interchange `@id` → element index, built lazily by the connector / /// transition accessors (empty until first use). by_id: HashMap, + /// Element count `by_id` was built for. Compared instead of the map's + /// own length: duplicate ids (an id-scheme collision between + /// same-named units) make the map smaller than the element list, and + /// a length comparison would then rebuild it on every lookup. + by_id_built_for: usize, /// Per-unit (name, line index), aligned with the model's unit list — /// span-to-line conversion for declaration sites (diagram links). unit_meta: Vec<(String, sysmlv2_syntax::span::LineIndex)>, @@ -6497,13 +8541,45 @@ pub struct ResolvedModel { /// `mRef` unit definition), built lazily by /// [`Self::quantity_type_candidates`] (`None` until first use). pub(crate) quantity_index: Option, + /// Element index → its effective name (`Element::effectiveName()`), + /// memoized by `naming.rs` (empty until first use). + name_memo: Vec>>, + /// Names of elements outside the model, by id — a library name table + /// the caller supplied ([`Self::set_library_names`]) for a model built + /// without its library. The naming rule reads it for a naming feature + /// it has no element for; the implied-relationship synthesis reads + /// the inverse. + external_names: HashMap, + /// The same table inverted: qualified name → id. + external_by_name: HashMap, + /// Each external id's root package (the first segment of its + /// qualified name) — which library package a function belongs to. + external_package: HashMap, + /// The implied relationships, once materialized (`json/implied.rs`). + implied: Option, + /// How the inheritance-aware families answer (`json/closures.rs`). + closure_policy: ClosurePolicy, + /// Scope → whether its import walk was truncated, per implied flag + /// (`json/closures.rs`; `inherited_bindings` memoizes the heritage + /// side itself). + import_truncated: HashMap<(usize, bool), bool>, + /// [`derives`] per metaclass over every derived name of the catalog, + /// filled as metaclasses are met (`json/derived.rs`). + derives_memo: HashMap<&'static str, Box<[Derives]>>, + /// The names the layer computes per metaclass, in `computed_names()` + /// order ([`Self::computable_names`]). + plan_memo: HashMap<&'static str, Arc<[&'static str]>>, + /// User features by the elements their explicit redefinitions + /// target, built lazily by [`Self::redefiners`] (`None` until first + /// use). + pub(crate) redefiner_index: Option>>, } /// The lazily-built quantity-type index of a resolved model (see /// `crate::quantity`): scalar quantity types keyed by their dimension /// and by the unit definitions their `mRef`s name. pub(crate) struct QuantityIndex { - pub(crate) by_dims: HashMap>, + pub(crate) by_dims: HashMap>, pub(crate) by_unit_def: HashMap>, } @@ -6513,17 +8589,105 @@ impl ResolvedModel { pub fn build(model: &crate::model::Model) -> ResolvedModel { let mut b = Builder::default(); b.build_model(model); + Self::from_builder(b, model) + } + + pub(crate) fn from_builder(mut b: Builder, model: &crate::model::Model) -> Self { + // A user relationship can specialize a library feature without adding + // a root name. Such a graph cannot reuse derived library quantities. + if let Some(facts) = &b.library_facts { + let changed = b.elements.iter().skip(b.lib_boundary).any(|e| { + let source = match e.ty { + "FeatureTyping" | "ConjugatedPortTyping" => Some("typedFeature"), + "Subclassification" => Some("subclassifier"), + "Subsetting" | "ReferenceSubsetting" => Some("subsettingFeature"), + "Redefinition" => Some("redefiningFeature"), + "Specialization" => Some("specific"), + "Conjugation" => Some("conjugatedType"), + "TypeFeaturing" => Some("featureOfType"), + "FeatureInverting" => Some("featureInverted"), + _ => None, + }; + source + .and_then(|key| e.props.get(key)) + .and_then(|v| v.as_reference()) + .is_some_and(|id| facts.contains_id(&id)) + || e.props + .get("annotatedElement") + .and_then(|v| v.as_array()) + .is_some_and(|a| { + a.iter() + .filter_map(|v| v.as_reference()) + .any(|id| facts.contains_id(&id)) + }) + }); + if changed { + b.semantic_memo = Default::default(); + } + } + b.semantic_ready = true; ResolvedModel { b, rel_owner: Vec::new(), + rel_member: Vec::new(), by_id: HashMap::new(), - unit_meta: model - .units() - .iter() - .map(|u| (u.name.clone(), u.lines.clone())) + by_id_built_for: usize::MAX, + unit_meta: (0..model.unit_count()) + .map(|i| { + let (name, lines) = model.unit_meta(i); + (name.to_owned(), lines.clone()) + }) .collect(), quantity_index: None, + name_memo: Vec::new(), + external_names: HashMap::new(), + external_by_name: HashMap::new(), + external_package: HashMap::new(), + implied: None, + closure_policy: ClosurePolicy::default(), + import_truncated: HashMap::new(), + derives_memo: HashMap::new(), + plan_memo: HashMap::new(), + redefiner_index: None, + } + } + + /// Supply the names of library elements this model was built + /// without: `id → qualified-name segments`, as + /// [`library_element_name_map`] produces them for a model that has + /// the library. The specification's naming rule then names an unnamed + /// feature after a library feature it redefines or references + /// (`attribute :>> mass;` → `mass`) exactly as it would with the + /// library loaded, and the implied library specializations can be + /// synthesized. A model that has its library loaded needs none of + /// this. Call it before the first derived query: the naming memo is + /// reset, and the implied relationships are re-synthesized only if + /// none were materialized yet (materialized ones stay). + pub fn set_library_names(&mut self, names: &HashMap>) { + self.external_names.clear(); + self.external_by_name.clear(); + self.external_package.clear(); + if self + .implied + .as_ref() + .is_some_and(|t| t.from == self.b.elements.len()) + { + self.implied = None; + self.b.implied_from = None; + } + for (id, segments) in names { + let Ok(id) = Uuid::parse_str(id) else { + continue; + }; + if let Some(last) = segments.last() { + self.external_names.insert(id, last.clone()); + } + if let Some(first) = segments.first() { + self.external_package.insert(id, first.clone()); + } + self.external_by_name.insert(segments.join("::"), id); } + self.name_memo.clear(); } /// Resolve a `::`-separated qualified name (quoted segments allowed) @@ -6532,6 +8696,15 @@ impl ResolvedModel { self.resolve_segments(&split_qualified(name)) } + /// Look up an interchange UUID independently of an element's name. + /// Includes anonymous and library elements. Malformed or absent IDs + /// return `None`; the ID belongs to this resolved model state. + pub fn element_by_id(&mut self, id: &str) -> Option { + let id = Uuid::parse_str(id).ok()?; + self.ensure_by_id(); + self.by_id.get(&id).copied().map(ElementRef) + } + fn resolve_segments(&mut self, segments: &[String]) -> Option { if segments.is_empty() { return None; @@ -6563,6 +8736,11 @@ impl ResolvedModel { /// evaluates to a scalar, or a member only qualified lookup can /// reach), the element evaluates in its own scope as /// [`Self::evaluate`] does. + /// + /// # Panics + /// + /// Never in practice: the qualified name is split before it is read + /// back, so its last segment is always present. pub fn evaluate_qualified( &mut self, name: &str, @@ -6634,23 +8812,52 @@ impl ResolvedModel { } /// The element's declared short name (``), when it has one. - pub fn element_short_name(&self, e: ElementRef) -> Option<&str> { + pub fn element_declared_short_name(&self, e: ElementRef) -> Option<&str> { self.b.elements[e.0] .props .get("declaredShortName") .and_then(|v| v.as_str()) } - /// The element's declared name, declared short name, or syntactic - /// effective name inherited from its first redefinition/reference - /// target (`attribute :>> mass` → `mass`). This is the name lookup and - /// structural projections use for unnamed features. - pub fn element_effective_name(&self, e: ElementRef) -> Option { + /// The specification's `Element::shortName` — `effectiveShortName()`: + /// the declared short name, or — for a Feature that declares neither + /// name — the effective short name of the feature that names it (see + /// [`Self::element_effective_name`]). + pub fn element_short_name(&mut self, e: ElementRef) -> Option { + self.effective_short_name_of(e.0) + } + + /// The name lookup keys the element under: the declared name, else the + /// declared short name, else the syntactic effective name recorded at + /// lowering — the last segment of the first redefined or referenced + /// feature's written path (`attribute :>> mass` → `mass`), whether or + /// not that reference resolved. Structural projections that must + /// re-resolve the names they spell use this + /// ([`Self::element_reference_spelling`] joins it); the + /// specification's `name` is [`Self::element_effective_name`]. + pub fn element_lookup_name(&self, e: ElementRef) -> Option { self.b .effective_name(e.0) .or_else(|| self.b.effective_hint.get(&e.0).cloned()) } + /// The specification's `Element::name` — `effectiveName()` (KerML + /// 8.2.3.5): the declared name, else — for a Feature that declares + /// neither a name nor a short name — the effective name of its + /// naming feature: the feature it explicitly redefines, + /// else the positional name of the library feature its membership + /// kind implicitly redefines (a binary connector's ends `source` / + /// `target`, a return parameter `result`, a subject `subj`, an + /// invocation's positional argument the callee's parameter name, …), + /// else the feature it references, else the last link of its feature + /// chain. A naming feature that did not resolve names nothing, so an + /// unresolved `:>> mass` is unnamed here where + /// [`Self::element_lookup_name`] still answers `mass`. Never falls + /// back to the short name (`qualifiedName` does). + pub fn element_effective_name(&mut self, e: ElementRef) -> Option { + self.effective_name_of(e.0) + } + /// Whether the element carries a feature-value expression (`= …`). pub fn has_value(&self, e: ElementRef) -> bool { self.b.values.contains_key(&e.0) @@ -6677,9 +8884,28 @@ impl ResolvedModel { /// ``, recursively through quantities, instances, and /// sequences. Everything else matches the value's own `Display`. pub fn render_value(&self, v: &crate::eval::Value) -> String { + self.render_value_with(v, false) + } + + /// [`Self::render_value`] for glanceable surfaces (editor hints and + /// hovers): a rational without a terminating decimal expansion shows + /// as an approximate decimal (`≈0.3333333333333333`) rather than the + /// exact fraction. + pub fn render_value_approx(&self, v: &crate::eval::Value) -> String { + self.render_value_with(v, true) + } + + fn render_value_with(&self, v: &crate::eval::Value, approx: bool) -> String { use crate::eval::Value; + let leaf = |v: &Value| { + if approx { + v.to_approx_string() + } else { + v.to_string() + } + }; match v { - Value::Element(e) | Value::Unbound(e) => { + Value::Element(e) | Value::Unbound(e) | Value::UnboundMember(e) => { let el = &self.b.elements[e.0]; el.props .get("declaredName") @@ -6688,13 +8914,15 @@ impl ResolvedModel { .map(str::to_string) .unwrap_or_else(|| v.to_string()) } - Value::Quantity(n, u) => format!("{} [{}]", self.render_value(n), u.display()), + Value::Quantity(n, u) => { + format!("{} [{}]", self.render_value_with(n, approx), u.display()) + } Value::Instance { ty_name, fields, .. } => { let fields = fields .iter() - .map(|(name, v)| format!("{name} = {}", self.render_value(v))) + .map(|(name, v)| format!("{name} = {}", self.render_value_with(v, approx))) .collect::>() .join(", "); format!("{ty_name}({fields})") @@ -6703,12 +8931,12 @@ impl ResolvedModel { Value::Sequence(s) => { let items = s .iter() - .map(|v| self.render_value(v)) + .map(|v| self.render_value_with(v, approx)) .collect::>() .join(", "); format!("({items})") } - _ => v.to_string(), + _ => leaf(v), } } @@ -6759,7 +8987,9 @@ impl ResolvedModel { crate::eval::evaluate_query_in(&mut self.b, scope.0, expr) } - /// Build the relationship → owning-element map on first use. + /// Build the relationship → owning-element map on first use. An + /// implied relationship is owned through the side table, not its + /// owner's row. fn ensure_rel_owner(&mut self) { if self.rel_owner.len() != self.b.elements.len() { let mut map = vec![None; self.b.elements.len()]; @@ -6768,14 +8998,33 @@ impl ResolvedModel { map[r] = Some(i); } } + if let Some(table) = &self.implied { + for (k, &owner) in table.owner_of.iter().enumerate() { + map[table.from + k] = Some(owner); + } + } self.rel_owner = map; } } - /// The element's qualified name — declared (or short) names joined - /// with `::` from its document root, restricted names quoted. `None` - /// when the element or an ancestor is unnamed. - pub fn element_qualified_name(&mut self, e: ElementRef) -> Option { + /// Build the membership → owned-member map on first use. + fn ensure_rel_member(&mut self) { + if self.rel_member.len() != self.b.elements.len() { + let mut map = vec![None; self.b.elements.len()]; + for (i, el) in self.b.elements.iter().enumerate() { + if let Some(r) = el.owning_relationship { + map[r] = Some(i); + } + } + self.rel_member = map; + } + } + + /// The element's lookup names ([`Self::element_lookup_name`]) from its + /// document root, raw (unescaped) and root first — the segments a + /// re-resolvable reference spelling joins. `None` when the element or + /// an ancestor has no lookup name. + fn lookup_name_segments(&mut self, e: ElementRef) -> Option> { self.ensure_rel_owner(); let mut segs: Vec = Vec::new(); let mut cur = e.0; @@ -6786,19 +9035,64 @@ impl ResolvedModel { let Some(rel) = el.owning_relationship else { break; }; - let name = el - .props - .get("declaredName") - .and_then(|v| v.as_str()) - .or_else(|| el.props.get("declaredShortName").and_then(|v| v.as_str()))?; - segs.push(sysmlv2_syntax::ast::escape_name(name)); + segs.push(self.element_lookup_name(ElementRef(cur))?); cur = self.rel_owner[rel]?; } if segs.is_empty() { return None; } segs.reverse(); - Some(segs.join("::")) + Some(segs) + } + + /// The specification's `Element::qualifiedName`: the owning + /// namespace's qualified name and the element's `escapedName()` — its + /// [effective name](Self::element_effective_name), else its effective + /// short name — joined with `::` from the document root, non-basic + /// names quoted. `None` when the element or an ancestor is unnamed or + /// is owned other than through a membership (it then has no + /// `owningNamespace`). + /// + /// KerML 8.3.2.1 `escapedName`: a name with the *form* of a basic + /// name is returned as-is — the spelling the pilot implementation + /// derives and the normative library ids hash — so a reserved word + /// used as a name stays bare here (`ControlFunctions::if`). It is a + /// model property, not parseable text: splice + /// [`Self::element_reference_spelling`] into source instead. + pub fn element_qualified_name(&mut self, e: ElementRef) -> Option { + let segs = self.qualified_name_segments(e)?; + Some( + segs.iter() + .map(|s| sysmlv2_syntax::ast::escape_name(s)) + .collect::>() + .join("::"), + ) + } + + /// The element's lookup-name path spelled as reference text that + /// re-parses in either dialect and re-resolves to the element: every + /// segment that is a reserved word of SysML or KerML, or not a basic + /// name, is quoted (`'part'::'view'` for the element whose qualified + /// name is `part::view`). Joins [`Self::element_lookup_name`] rather + /// than the specification's name, so an unnamed feature is spelled by + /// the name it was written under — the segment name resolution finds + /// it by — even where the specification's `qualifiedName` would give + /// another (an implied positional name) or none (an unresolved naming + /// reference). Text going into a known unit can use its own table + /// instead: [`Self::unit_dialect`] with + /// [`sysmlv2_syntax::name::spell_path`]. + pub fn element_reference_spelling(&mut self, e: ElementRef) -> Option { + let segs = self.lookup_name_segments(e)?; + Some(sysmlv2_syntax::name::spell_path(None, &segs)) + } + + /// The dialect of a unit, by its name (`.kerml` is KerML, anything + /// else SysML): the reserved-word table that governs text spliced + /// into it. `None` for an unknown unit index. + pub fn unit_dialect(&self, unit: usize) -> Option { + self.unit_meta + .get(unit) + .map(|(name, _)| crate::model::Model::dialect_for(name)) } // ---- typed navigation (the transformation SDK's read side) ---- @@ -6867,80 +9161,206 @@ impl ResolvedModel { )) } - /// Textual `private import` members that provably feed nothing in - /// their unit: (import relationship, unit index, span of the whole - /// import member — the removal span). Two conditions, both required: - /// - /// 1. No lookup resolved a name through the import in this build - /// (recorded at the admitted-hit sites of the resolver walk). - /// 2. Nothing the unit references lives under the imported namespace - /// (owner-chain check). Condition 1 alone is resolver-*order* - /// truth, not semantic truth — a name can resolve through an - /// implied library base's own import before the unit's import is - /// consulted, yet removing the import would still break the file - /// in tools with a different search order. - /// - /// Callers filter to their user units: under a sealed library - /// snapshot, library-internal resolution replays without lookups, so - /// library imports always fail condition 1. Public (and KerML - /// default-visibility) imports are never reported — they re-export. - pub fn unused_private_imports(&mut self) -> Vec<(ElementRef, ElementRef, usize, Span)> { + /// Textual `private import` members that provably feed nothing in + /// their unit: (import relationship, unit index, span of the whole + /// import member — the removal span). Two conditions, both required: + /// + /// 1. No lookup resolved a name through the import in this build + /// (recorded at the admitted-hit sites of the resolver walk). + /// 2. Nothing the unit references lives under the imported namespace + /// (owner-chain check). Condition 1 alone is resolver-*order* + /// truth, not semantic truth — a name can resolve through an + /// implied library base's own import before the unit's import is + /// consulted, yet removing the import would still break the file + /// in tools with a different search order. + /// + /// Callers filter to their user units: under a sealed library + /// snapshot, library-internal resolution replays without lookups, so + /// library imports always fail condition 1. Public (and KerML + /// default-visibility) imports are never reported — they re-export. + pub fn unused_private_imports(&mut self) -> Vec<(ElementRef, ElementRef, usize, Span)> { + self.unused_private_imports_in(None) + } + + /// User-unit imports declared without a visibility keyword, in + /// declaration order: (import relationship, unit, member span). + /// The unit and span of a user-unit import declaration (the element + /// a [`RefSite::via_imports`] entry names). `None` for library + /// imports and for elements that are not imports. + pub fn import_extent(&self, import: ElementRef) -> Option<(usize, Span)> { + self.b + .user_imports + .iter() + .find(|i| i.rel == import.0) + .map(|i| (self.b.unit_of_elem(i.rel), i.span)) + } + + pub fn imports_without_visibility(&self) -> Vec<(ElementRef, usize, Span)> { + self.b + .user_imports + .iter() + .filter(|i| i.visibility.is_none()) + .map(|i| (ElementRef(i.rel), self.b.unit_of_elem(i.rel), i.span)) + .collect() + } + + /// The visibility an import's dependents require, judged from the + /// access each reference site walked it under — the check the + /// resolver itself applied: `private` when every walk ran with full + /// access (lexically from inside the importing namespace, nested + /// namespaces included), `protected` when the most restrictive walk + /// came through a specialization of the importing type, `public` + /// when any walk came from outside. `None` when `import` is not a + /// user-unit import or its own target does not resolve (the import + /// is diagnosed on its own; no advice is meaningful). + pub fn import_visibility_advice( + &mut self, + import: ElementRef, + ) -> Option { + let imp = self + .b + .user_imports + .iter() + .find(|i| i.rel == import.0)? + .clone(); + let target = self.b.elements[imp.rel] + .props + .get("importedNamespace") + .or_else(|| self.b.elements[imp.rel].props.get("importedMembership"))?; + if target.get("@ref").is_some() { + return None; + } + let mut outside_sites = Vec::new(); + let mut most_restrictive = AccessMode::Any; + for site in &self.b.ref_sites { + let Some((_, access)) = site.via_imports.iter().find(|(i, _)| *i == import) else { + continue; + }; + most_restrictive = most_restrictive.min(*access); + if *access != AccessMode::Any { + outside_sites.push((site.unit, site.span)); + } + } + outside_sites.sort_unstable_by_key(|(unit, span)| (*unit, span.start, span.end)); + outside_sites.dedup(); + let recommended = match most_restrictive { + AccessMode::Any => "private", + AccessMode::Protected => "protected", + AccessMode::Public => "public", + }; + let owner = self.b.scopes[imp.scope].owner; + let namespace = owner.and_then(|o| self.element_qualified_name(ElementRef(o))); + Some(ImportVisibilityAdvice { + import, + unit: self.b.unit_of_elem(imp.rel), + span: imp.span, + declared: imp.visibility.map(|v| match v { + Visibility::Public => "public", + Visibility::Private => "private", + Visibility::Protected => "protected", + }), + recommended, + outside_sites, + namespace, + }) + } + + /// The conservative unused-import check restricted to the supplied model + /// units. Filtering happens before candidate/reference analysis; passing an + /// empty slice performs no analysis. The result keeps declaration order. + pub fn unused_private_imports_for_units( + &mut self, + units: &[usize], + ) -> Vec<(ElementRef, ElementRef, usize, Span)> { + self.unused_private_imports_in(Some(&units.iter().copied().collect())) + } + + fn unused_private_imports_in( + &mut self, + units: Option<&HashSet>, + ) -> Vec<(ElementRef, ElementRef, usize, Span)> { let candidates: Vec<(usize, Span, usize)> = self .b .user_imports .iter() - .filter(|(rel, _, private)| *private && !self.b.used_imports.contains(rel)) - .map(|(rel, span, _)| (*rel, *span, self.b.unit_of_elem(*rel))) + .filter(|imp| { + imp.visibility == Some(Visibility::Private) + && !self.b.used_imports.contains(&imp.rel) + && units.is_none_or(|us| us.contains(&self.b.unit_of_elem(imp.rel))) + }) + .map(|imp| (imp.rel, imp.span, self.b.unit_of_elem(imp.rel))) + .collect(); + if candidates.is_empty() { + return Vec::new(); + } + let candidate_units: HashSet<_> = candidates.iter().map(|(_, _, unit)| *unit).collect(); + let sites: Vec<_> = self + .b + .ref_sites + .iter() + .filter(|s| candidate_units.contains(&s.unit)) + .map(|s| { + ( + s.unit, + s.span, + s.target, + s.kind == "importedNamespace" || s.kind == "importedMembership", + ) + }) .collect(); + // Source-range lookup retains the original reference-site ordering for + // the rare case of several targets contained in one import member. + let mut imports = + std::collections::BTreeMap::<(usize, u32), Vec<(u32, ElementRef, usize)>>::new(); + let mut ancestry = HashMap::>::new(); + let mut extents = HashMap::<(usize, ElementRef), (u32, u32)>::new(); + for (order, (unit, span, target, import)) in sites.into_iter().enumerate() { + if import { + imports + .entry((unit, span.start)) + .or_default() + .push((span.end, target, order)); + } + let ancestors = ancestry.entry(target).or_insert_with(|| { + let mut chain = vec![target]; + let mut e = target; + // Match the original conservative owner walk exactly: the + // target itself plus at most 64 owning elements. + for _ in 0..64 { + let Some(owner) = self.owner(e) else { + break; + }; + chain.push(owner); + e = owner; + } + chain + }); + for &ancestor in ancestors.iter() { + extents + .entry((unit, ancestor)) + .and_modify(|(start, end)| { + *start = (*start).min(span.start); + *end = (*end).max(span.end); + }) + .or_insert((span.start, span.end)); + } + } let mut out = Vec::new(); for (rel, span, unit) in candidates { - // The import's own target (recorded as a ref site inside the - // member span). An unresolved target already warns - // referentially — stay quiet here. - let Some(target) = self - .b - .ref_sites - .iter() - .find(|s| { - s.unit == unit - && s.span.start >= span.start - && s.span.end <= span.end - && (s.kind == "importedNamespace" || s.kind == "importedMembership") - }) - .map(|s| s.target) - else { + let target = imports + .range((unit, span.start)..=(unit, span.end)) + .flat_map(|(_, sites)| sites.iter()) + .filter(|(end, _, _)| *end <= span.end) + .min_by_key(|(_, _, order)| *order) + .map(|(_, target, _)| *target); + let Some(target) = target else { continue; }; - let sites: Vec = self - .b - .ref_sites - .iter() - .filter(|s| { - s.unit == unit && !(s.span.start >= span.start && s.span.end <= span.end) - }) - .map(|s| s.target) - .collect(); - let mut feeds = false; - for site_target in sites { - if site_target == target { - feeds = true; - break; - } - let mut e = site_target; - for _ in 0..64 { - match self.owner(e) { - Some(o) if o == target => { - feeds = true; - break; - } - Some(o) => e = o, - None => break, - } - } - if feeds { - break; - } - } + // There is a feeding reference outside the candidate precisely + // when the span envelope extends beyond its removal range. + let feeds = extents + .get(&(unit, target)) + .is_some_and(|(start, end)| *start < span.start || *end > span.end); if !feeds { out.push((ElementRef(rel), target, unit, span)); } @@ -6954,22 +9374,54 @@ impl ResolvedModel { /// check's textual condition, where over-listing only suppresses a /// finding. pub fn namespace_member_names(&mut self, e: ElementRef) -> Vec { - let mut out = Vec::new(); - let mut frontier = vec![(e, 0usize)]; - while let Some((cur, depth)) = frontier.pop() { - let props = &self.b.elements[cur.0].props; - for key in ["declaredName", "declaredShortName"] { - if let Some(name) = props.get(key).and_then(|v| v.as_str()) { - out.push(name.to_string()); + self.namespace_member_names_many(&[e]) + .remove(&e) + .unwrap_or_default() + } + + /// Enumerate several imported namespaces using one owned-members index. + /// Each name vector is identical to `namespace_member_names`, including + /// traversal order and its conservative depth/name limits. The index is + /// local to this call, so model edits cannot leave stale entries. + pub fn namespace_member_names_many( + &mut self, + targets: &[ElementRef], + ) -> HashMap> { + if targets.is_empty() { + return HashMap::new(); + } + self.ensure_rel_owner(); + let mut members = vec![Vec::new(); self.b.elements.len()]; + for (i, element) in self.b.elements.iter().enumerate() { + if let Some(rel) = element.owning_relationship { + if self.b.elements[rel].ty.ends_with("Membership") { + if let Some(owner) = self.rel_owner[rel] { + members[owner].push(i); + } } } - if depth < 8 && out.len() < 4096 { - for m in self.owned_members(cur) { - frontier.push((m, depth + 1)); + } + let mut names = HashMap::new(); + for &target in targets { + names.entry(target).or_insert_with(|| { + let mut out = Vec::new(); + let mut frontier = vec![(target.0, 0usize)]; + while let Some((cur, depth)) = frontier.pop() { + for key in ["declaredName", "declaredShortName"] { + if let Some(name) = + self.b.elements[cur].props.get(key).and_then(|v| v.as_str()) + { + out.push(name.to_string()); + } + } + if depth < 8 && out.len() < 4096 { + frontier.extend(members[cur].iter().map(|&m| (m, depth + 1))); + } } - } + out + }); } - out + names } /// The element whose declared-name span contains `offset` in `unit` — @@ -6998,6 +9450,21 @@ impl ResolvedModel { } } + /// The relationships `e` owns directly (`Element::ownedRelationship`: + /// its memberships, imports, specializations, typings, annotations, + /// …), in declaration order — the explicit ones. The implied + /// specializations are listed by [`Self::implied_relationships`] and + /// included by the relationship families of [`Self::derived`] + /// (`ownedSpecialization`, `ownedSubsetting`, …). + pub fn owned_relationships(&self, e: ElementRef) -> Vec { + self.b.elements[e.0] + .owned_relationships + .iter() + .copied() + .map(ElementRef) + .collect() + } + /// The elements owned by `e` through its owned memberships, in /// declaration order — KerML `Namespace::ownedMember`. pub fn owned_members(&self, e: ElementRef) -> Vec { @@ -7019,11 +9486,175 @@ impl ResolvedModel { .collect() } + /// The members `e` inherits through its specialization heritage — + /// KerML `Type::inheritedMemberships`, answered by the resolver's own + /// inheritance walk (the one name lookup uses). Private memberships + /// do not inherit; **public and protected imported memberships re-export** through + /// heritage (membership and namespace imports, `::**` and re-export + /// chains included, filters applied). Removal is redefinition-driven, + /// not name-driven, per KerML `removeRedefinedFeatures`: a member is + /// dropped when another inherited candidate (transitively) redefines + /// it, when its own redefinition closure meets a feature **directly** + /// redefined by one of `e`'s owned features (the normative + /// `ownedFeature.redefinition.redefinedFeature` set is one hop), or + /// under SysML's implicit same-name usage redefinition; same-name + /// members of *unrelated* branches are all retained (lookup answers + /// ambiguous — the memberships still inherit). Handles come in + /// breadth-first heritage order, creation order within a level. + /// + /// Returns **Membership relationship handles**, per the normative + /// operation: owning memberships for ordinary members, the imported + /// member's home membership for imports, and **alias Memberships** + /// of the heritage scopes (non-private). Navigate them with + /// [`Self::membership_member`] / [`Self::membership_member_name`] / + /// [`Self::membership_is_alias`]; the declaring namespace is the + /// membership's [`Self::owner`]. + /// + /// `include_implied` extends the walk over implied heritage — + /// the SysML Tables 31/32 library bases (every `action` inherits + /// `Actions::Action`'s members), binary connector bases, and + /// semantic-metadata bases — at every level; `false` walks written + /// specializations/typings only. + /// + /// The normative `excluded` namespace/type parameters are not taken + /// (they are the OCL recursion's cycle-guard plumbing; the guard here + /// is internal — [`Self::inheritance_walk_truncated`] reports when it + /// cut the walk). `e` without a body scope answers empty. + pub fn inherited_memberships( + &mut self, + e: ElementRef, + include_implied: bool, + ) -> Vec { + let Some(&s) = self.b.elem_scope.get(&e.0) else { + return Vec::new(); + }; + let bindings = self.b.inherited_bindings(s, include_implied); + let mut out: Vec = Vec::new(); + let mut seen: HashSet = HashSet::new(); + for &(elem, _) in &bindings.members { + if let Some(r) = self.b.elements[elem].owning_relationship { + if seen.insert(r) { + out.push(ElementRef(r)); + } + } + } + // Alias Memberships — direct heritage and imported alike; the + // aliased element is reachable through + // [`Self::membership_member`]. + for &r in &bindings.alias_rels { + if seen.insert(r) { + out.push(ElementRef(r)); + } + } + out + } + + /// Whether the inheritance walk behind [`Self::inherited_memberships`] + /// / [`Self::inherited_features`] for `e` hit the resolver's depth + /// budget (a heritage or import chain deeper than 24 levels), so the + /// enumeration may be incomplete. Cycles never trip it — the walk + /// tracks visited scopes and a cyclic heritage enumerates completely; + /// only a genuinely deeper chain does. The flag lets an emitter + /// refuse to present a cut enumeration as the closure. + pub fn inheritance_walk_truncated(&mut self, e: ElementRef, include_implied: bool) -> bool { + let Some(&s) = self.b.elem_scope.get(&e.0) else { + return false; + }; + self.b.inherited_bindings(s, include_implied).truncated + } + + /// [`Self::inherited_memberships`] projected to feature member + /// *elements*, selected by the **member's** metaclass — the view a + /// compartment or an object API wants, in which a package-owned part + /// arriving through an imported membership counts as a feature. + /// KerML `Type::inheritedFeature` selects by the *membership* kind + /// (`inheritedMembership->selectByKind(FeatureMembership).memberFeature`), + /// which the derived-property read API answers under that name + /// (`derived(e, "inheritedFeature")`); this accessor deliberately + /// keeps the wider view. + pub fn inherited_features(&mut self, e: ElementRef, include_implied: bool) -> Vec { + let Some(&s) = self.b.elem_scope.get(&e.0) else { + return Vec::new(); + }; + let bindings = self.b.inherited_bindings(s, include_implied); + bindings + .members + .iter() + .map(|&(elem, _)| ElementRef(elem)) + .filter(|m| crate::metaclass::conforms(self.b.elements[m.0].ty, "Feature")) + .collect() + } + + /// The member a Membership binds: the owned element for owning + /// membership kinds, the referenced `memberElement` for + /// non-owning Memberships (aliases, `first X;` markers, transition + /// sources). `None` when the reference did not resolve or `m` is + /// not a membership. + pub fn membership_member(&mut self, m: ElementRef) -> Option { + if !crate::metaclass::conforms(self.b.elements[m.0].ty, "Membership") { + return None; // a FeatureValue is an OwningMembership too + } + self.ensure_rel_member(); + if let Some(Some(member)) = self.rel_member.get(m.0) { + return Some(ElementRef(*member)); + } + self.ensure_by_id(); + self.prop_target(m.0, "memberElement").map(ElementRef) + } + + /// The name a Membership binds its member under: the membership's + /// declared `memberName` (an alias's own name), else the member's + /// effective name. + pub fn membership_member_name(&mut self, m: ElementRef) -> Option { + if let Some(n) = self.b.elements[m.0] + .props + .get("memberName") + .and_then(|a| a.as_str()) + { + return Some(n.to_string()); + } + let member = self.membership_member(m)?; + self.element_lookup_name(member) + } + + /// Whether `m` is an alias Membership: a plain `Membership` carrying + /// its own member name and owning no element. + pub fn membership_is_alias(&self, m: ElementRef) -> bool { + self.b.elements[m.0].ty == "Membership" + && (self.b.elements[m.0] + .props + .get("memberName") + .is_some_and(|v| !v.is_null()) + || self.b.elements[m.0] + .props + .get("memberShortName") + .is_some_and(|v| !v.is_null())) + } + + /// `e`'s owned features followed by everything it inherits, + /// shadowing already applied — the "effective members" view a + /// rendering compartment or an object-API `features` accessor wants. + /// `include_implied` as for [`Self::inherited_features`]: `true` + /// adds the members of the implied library bases (every part's + /// generic library ports, every action's `start`/`done`), `false` + /// stops at the written heritage. + pub fn effective_features(&mut self, e: ElementRef, include_implied: bool) -> Vec { + let mut out = self.owned_features(e); + let mut seen: HashSet = out.iter().copied().collect(); + for m in self.inherited_features(e, include_implied) { + if seen.insert(m) { + out.push(m); + } + } + out + } + /// Every element of the given abstract-syntax metaclass (library - /// elements included — filter with [`Self::is_library_element`]), in + /// elements included — filter with [`Self::is_library_element`]; + /// implied relationships excluded as in [`Self::elements`]), in /// creation (document) order. pub fn elements_of_metaclass(&self, ty: &str) -> Vec { - (0..self.b.elements.len()) + (0..self.b.explicit_len()) .filter(|&i| self.b.elements[i].ty == ty) .map(ElementRef) .collect() @@ -7035,21 +9666,33 @@ impl ResolvedModel { e.0 < self.b.lib_boundary } + /// `Type::isAbstract` as declared: the `abstract` keyword, or a + /// variation or enumeration definition or a variation usage, which the + /// lowering marks abstract. + pub fn is_abstract(&self, e: ElementRef) -> bool { + self.b.elements[e.0] + .props + .get("isAbstract") + .and_then(|v| v.as_bool()) + .unwrap_or(false) + } + /// Evaluated numeric bounds of `e`'s *explicitly declared* /// multiplicity: `[l..u]` → `(l, u)`, `[u]` → `(u, u)` except `[*]` /// → `(0, ∞)` — the same reading the multiplicity checks use. /// `None` when `e` declares no multiplicity of its own (inherited /// ones are not walked) or a bound does not evaluate to a number. pub fn declared_multiplicity(&mut self, e: ElementRef) -> Option<(f64, f64)> { + // Evaluating the bounds needs the builder mutably, so the clause + // is copied out of the table first; the table itself is not walked. let (scope, m) = self .b - .multiplicities - .iter() - .find(|(o, _, _)| *o == e.0) - .map(|(_, s, m)| (*s, m.clone()))?; + .declared_multiplicity_of(e.0) + .map(|(s, m)| (s, m.clone()))?; let as_num = |v: crate::eval::Value| match v { crate::eval::Value::Integer(i) => Some(i as f64), - crate::eval::Value::Rational(f) => Some(f), + crate::eval::Value::Rational(r) => Some(r.to_f64()), + crate::eval::Value::Real(f) => Some(f), _ => None, }; let hi = as_num(crate::eval::evaluate_expr_in(&mut self.b, scope, &m.upper).ok()?)?; @@ -7087,6 +9730,25 @@ impl ResolvedModel { self.b.unresolved.len() } + /// Unresolved user references that name a member visible only under + /// a wider visibility — see [`BlockedReference`]. Unlike the + /// resolution report, reading this does not drain anything. + pub fn blocked_references(&self) -> Vec { + self.b + .blocked + .iter() + .filter(|site| site.owner >= self.b.lib_boundary) + .map(|site| BlockedReference { + unit: self.b.unit_of_elem(site.owner), + name: site.name.clone(), + spelling: site.spelling.clone(), + member: ElementRef(site.member), + visibility: site.visibility, + protected_suffices: site.protected_suffices, + }) + .collect() + } + /// Every reference that failed to resolve: the element whose property /// carries it, the spelling as written, and the unit it was written /// in. Relocation edits (which must not create unresolved references) @@ -7112,7 +9774,7 @@ impl ResolvedModel { self.b.elements[rel] .props .get("visibility") - .and_then(Value::as_str) + .and_then(|v| v.as_str()) } /// The full source extent of the member declaration that created `e` @@ -7124,10 +9786,93 @@ impl ResolvedModel { Some((self.b.unit_of_elem(e.0), span)) } + /// Replace element ids: every element whose current id is a key of + /// `map` takes the mapped id, and every reference to it follows. The + /// entry point for **explicit ids** — a document loaded from another + /// producer keeps the ids it came with instead of this toolkit's + /// graph-derived ones (IDS.md). Returns the entries actually applied + /// — `(derived id, given id, the element's metaclass)` — so a caller + /// can retire entries whose element no longer exists. Indexes keyed + /// by id are rebuilt lazily. + pub fn override_ids(&mut self, map: &HashMap) -> Vec<(Uuid, Uuid, &'static str)> { + if map.is_empty() { + return Vec::new(); + } + let mut applied: Vec<(Uuid, Uuid, &'static str)> = Vec::new(); + let mut remap: HashMap = HashMap::new(); + let n = self.b.elements.len(); + for i in 0..n { + let old = self.b.elements[i].id; + if let Some(&new) = map.get(&old) { + if new != old { + self.b.elements[i].id = new; + remap.insert(old, new); + applied.push((old, new, self.b.elements[i].ty)); + } + } + } + if applied.is_empty() { + return applied; + } + for i in 0..n { + for atom in self.b.elements[i].props.values_mut() { + atom.remap(&remap); + } + } + self.by_id_built_for = usize::MAX; + self.b.id_index = None; + applied + } + + /// Bind references spelled as a bare id — a `{"@ref": ""}` + /// placeholder left by a reference to an element that has no name + /// (the textual notation cannot spell it, so the lift carried the + /// id as a quoted name) — to that id: a reference to an element of + /// this model, or a dangling reference to an id outside it (a library + /// element when no library is loaded), which the emitters carry as + /// spelled. Returns the ids bound. Binding sets the property; the + /// resolver's semantic tables (typing, specialization, reference + /// sites) do not learn the link. + pub fn bind_id_spelled_references(&mut self) -> HashSet { + let mut bound: HashSet = HashSet::new(); + let n = self.b.elements.len(); + for i in self.b.lib_boundary..n { + for atom in self.b.elements[i].props.values_mut() { + bind_atom(atom, &mut bound); + } + } + if !bound.is_empty() { + let spellings: HashSet = bound.iter().map(|u| u.to_string()).collect(); + self.b.unresolved.retain(|(_, qn)| { + !(qn.segments.len() == 1 && spellings.contains(&qn.segments[0].value)) + }); + } + bound + } + + /// Every element of the model, library elements first, in creation + /// order. The implied relationships the derivation layer materializes + /// are reached through [`Self::implied_relationships`] and the + /// relationship families of [`Self::derived`], not listed here. + pub fn elements(&self) -> impl Iterator + '_ { + (0..self.b.explicit_len()).map(ElementRef) + } + /// Every element built from the user units (libraries excluded), in - /// creation (document) order. + /// creation (document) order; implied relationships excluded as in + /// [`Self::elements`]. pub fn user_elements(&self) -> impl Iterator + '_ { - (self.b.lib_boundary..self.b.elements.len()).map(ElementRef) + (self.b.lib_boundary..self.b.explicit_len()).map(ElementRef) + } + + /// The element's owned (non-derived) properties as the compact form + /// spells them: `declaredName`, `isAbstract`, a relationship's ends + /// (`subclassifier`, `superclassifier`, …) as `{"@id"}` references, + /// an unresolved reference as its `{"@ref"}` spelling. Structure + /// (`ownedRelationship`, `owningRelationship`, `ownedRelatedElement`) + /// is not among them — read it with the navigation accessors. + pub fn element_properties(&self, e: ElementRef) -> Map { + self.b.elements[e.0].props.to_json() } /// The element's interchange `@id` (deterministic UUIDv5 — ownership @@ -7272,12 +10017,17 @@ impl ResolvedModel { /// feature-value evaluation (unbound stays honestly undecided). pub fn satisfactions(&mut self) -> Vec { self.ensure_by_id(); - let claims = self.b.satisfy_by.clone(); + // Only user claims are evaluated; the library rows stay untouched + // behind their shared prefix. + let claims: Vec<_> = self + .b + .satisfy_by + .iter() + .filter(|(sat, _, _)| *sat >= self.b.lib_boundary) + .cloned() + .collect(); let mut out = Vec::new(); for (sat, scope, by) in claims { - if sat < self.b.lib_boundary { - continue; - } let Some(req) = self.rel_prop_target(sat, "ReferenceSubsetting", "referencedFeature") else { continue; @@ -7516,7 +10266,7 @@ impl ResolvedModel { #[allow(missing_docs)] pub fn body_flow_members(&mut self, e: ElementRef) -> Vec { self.ensure_by_id(); - let rels: Vec = self.b.elements[e.0].owned_relationships.clone(); + let rels: Vec = self.b.elements[e.0].owned_relationships.to_vec(); // Owned elements per relationship, one scan. let mut owned: std::collections::HashMap> = std::collections::HashMap::new(); @@ -7563,14 +10313,16 @@ impl ResolvedModel { return Vec::new(); }; let mut out = Vec::new(); + // `emitted` keeps the order-preserving `out` free of duplicates + // without a linear scan per candidate (a `::**` exposure over a + // large model visits every element). + let mut emitted = std::collections::HashSet::new(); let mut seen = std::collections::HashSet::new(); // Membership exposes (`expose P::name;`, and the target itself of // `expose P::**`) contribute their resolved element directly. for entry in self.b.scopes[scope].member_imports.clone() { if let Some(elem) = self.b.resolve(scope, &entry.target, 0) { - if self.b.filters_admit(scope, &entry.filters, elem, 0) - && !out.contains(&ElementRef(elem)) - { + if self.b.filters_admit(scope, &entry.filters, elem, 0) && emitted.insert(elem) { out.push(ElementRef(elem)); } } @@ -7582,12 +10334,14 @@ impl ResolvedModel { entry.recursive, &entry.filters, &mut seen, + &mut emitted, &mut out, ); } out } + #[allow(clippy::too_many_arguments)] fn collect_exposed( &mut self, view_scope: usize, @@ -7595,6 +10349,7 @@ impl ResolvedModel { recursive: bool, fids: &[usize], seen: &mut std::collections::HashSet, + emitted: &mut std::collections::HashSet, out: &mut Vec, ) { // The seen-set breaks scope cycles (each scope enumerates once). @@ -7608,12 +10363,12 @@ impl ResolvedModel { if !self.b.filters_admit(view_scope, fids, m, 0) { continue; } - if !out.contains(&ElementRef(m)) { + if emitted.insert(m) { out.push(ElementRef(m)); } if recursive { if let Some(&msc) = self.b.elem_scope.get(&m) { - self.collect_exposed(view_scope, msc, true, fids, seen, out); + self.collect_exposed(view_scope, msc, true, fids, seen, emitted, out); } } } @@ -7628,7 +10383,37 @@ impl ResolvedModel { .members_under(view.0, "ViewRenderingMembership") .into_iter() .next()?; - let target = self.rel_prop_target(m, "ReferenceSubsetting", "referencedFeature")?; + let target = match self.rel_prop_target(m, "ReferenceSubsetting", "referencedFeature") { + Some(t) => t, + // A library rendering (`render asElementTable;`, the standard + // `Views` package) is never serialized, so the reference holds + // its spelling as written: resolve that from the view's scope. + None => { + let rel = *self.b.elements[m] + .owned_relationships + .iter() + .find(|&&r| self.b.elements[r].ty == "ReferenceSubsetting")?; + let spelling = self.b.elements[rel] + .props + .get("referencedFeature")? + .get("@ref")? + .as_str()? + .to_string(); + let scope = *self.b.elem_scope.get(&view.0)?; + let qn = QualifiedName { + is_global: false, + segments: split_qualified(&spelling) + .into_iter() + .map(|value| Name { + value, + span: sysmlv2_syntax::span::Span::default(), + }) + .collect(), + span: sysmlv2_syntax::span::Span::default(), + }; + self.b.resolve(scope, &qn, 0)? + } + }; self.b.elements[target] .props .get("declaredName") @@ -7665,7 +10450,8 @@ impl ResolvedModel { /// [`Self::resolve_in`] with `exclude` shielded from capture — the /// resolution mode a feature's own specialization targets and value - /// expression run under (see [`RefSite::exclude`]). + /// expression run under (see [`RefSite::exclude`]). A verification + /// probe: an import it walks is not recorded as used. pub fn resolve_in_excluding( &mut self, scope: ScopeRef, @@ -7673,9 +10459,11 @@ impl ResolvedModel { exclude: Option, ) -> Option { let saved = self.b.exclude; + let used_imports = self.b.used_imports.clone(); self.b.exclude = exclude.map(|e| e.0); let out = self.b.resolve(scope.0, qn, 0); self.b.exclude = saved; + self.b.used_imports = used_imports; out.map(ElementRef) } @@ -7693,6 +10481,24 @@ impl ResolvedModel { Some((ElementRef(hit), sub.map(ScopeRef))) } + /// Whether `e` is a directed parameter or a member of the + /// ParameterMembership family (including subjects and actors). + pub fn is_parameter(&self, e: ElementRef) -> bool { + self.b.is_parameter(e.0) + } + + /// Whether a featured, unvalued feature stands for a referenced instance. + /// Package-owned usages are excluded even when noncomposite. + pub fn is_reference_feature(&self, e: ElementRef) -> bool { + self.b.is_reference_feature(e.0) + } + + /// Whether `e` declares its own non-default value expression. The + /// expression is fixed; its result may still depend on unknown inputs. + pub fn has_own_fixed_value(&self, e: ElementRef) -> bool { + self.b.has_own_fixed_value(e.0) + } + /// `e`'s explicit Redefinition targets (`:>> x`), resolved — the /// one-hop borrow the semantic checks use for characteristics an /// untyped/undeclared redefining feature inherits from its target. @@ -7704,6 +10510,29 @@ impl ResolvedModel { .collect() } + /// The user features whose explicit Redefinition targets include + /// `e` (the reverse of [`Self::redefinition_targets`], one hop), in + /// document order — the features that borrow `e`'s declared types + /// when they declare none of their own. Library features are not + /// indexed. Built lazily once per resolved model. + pub fn redefiners(&mut self, e: ElementRef) -> Vec { + if self.redefiner_index.is_none() { + let mut index: HashMap> = HashMap::new(); + let users: Vec = (self.b.lib_boundary..self.b.elements.len()).collect(); + for r in users { + for t in self.b.redefinition_target_elems(r) { + index.entry(t).or_default().push(r); + } + } + self.redefiner_index = Some(index); + } + self.redefiner_index + .as_ref() + .and_then(|ix| ix.get(&e.0)) + .map(|v| v.iter().map(|&r| ElementRef(r)).collect()) + .unwrap_or_default() + } + /// The element's bound feature-value expression, with the scope the /// expression's references resolve from (its writing scope — chain-step /// consumers substitute their featuring context). @@ -7718,6 +10547,9 @@ impl ResolvedModel { /// or — the `return x = expr;` spelling — its return parameter's /// bound value (the evaluator's exact lookup, for solver inlining). pub fn calc_body(&self, e: ElementRef) -> Option<(ScopeRef, Expr)> { + if self.b.calculation_requires_execution(e.0) { + return None; + } if let Some((_, s, expr)) = self.b.result_exprs.iter().find(|(o, _, _)| *o == e.0) { return Some((ScopeRef(*s), expr.clone())); } @@ -7811,13 +10643,13 @@ impl ResolvedModel { pub fn dependency_ends(&mut self, e: ElementRef) -> (Vec, Vec) { self.ensure_by_id(); let side = |r: &Self, key: &str| -> Vec { - let Some(Value::Array(items)) = r.b.elements[e.0].props.get(key) else { + let Some(crate::properties::Atom::Array(items)) = r.b.elements[e.0].props.get(key) + else { return Vec::new(); }; items .iter() - .filter_map(|v| v.get("@id")?.as_str()) - .filter_map(|s| Uuid::parse_str(s).ok()) + .filter_map(|v| v.as_reference()) .filter_map(|id| r.by_id.get(&id).copied()) .map(ElementRef) .collect() @@ -7950,13 +10782,11 @@ impl ResolvedModel { /// metaclass (`ActorMembership`, `SubjectMembership`, /// `ObjectiveMembership`, …), in declaration order. pub fn members_via(&self, e: ElementRef, rel_ty: &str) -> Vec { - let rels: Vec = self.b.elements[e.0] + self.b.elements[e.0] .owned_relationships .iter() .copied() .filter(|&r| self.b.elements[r].ty == rel_ty) - .collect(); - rels.into_iter() .filter_map(|r| self.rel_children(r).first().copied()) .map(ElementRef) .collect() @@ -7977,13 +10807,11 @@ impl ResolvedModel { /// element. Unresolved targets are omitted. pub fn annotated_elements(&mut self, e: ElementRef) -> Vec { self.ensure_by_id(); - let rels: Vec = self.b.elements[e.0] + self.b.elements[e.0] .owned_relationships .iter() .copied() .filter(|&r| self.b.elements[r].ty == "Annotation") - .collect(); - rels.into_iter() .filter_map(|r| self.prop_target(r, "annotatedElement")) .map(ElementRef) .collect() @@ -8209,7 +11037,8 @@ impl ResolvedModel { } fn ensure_by_id(&mut self) { - if self.by_id.len() != self.b.elements.len() { + if self.by_id_built_for != self.b.elements.len() { + self.by_id_built_for = self.b.elements.len(); self.by_id = self .b .elements @@ -8223,13 +11052,7 @@ impl ResolvedModel { /// Elements owned *by relationship* `rel` (its `ownedRelatedElement` /// children), in creation order. fn rel_children(&self, rel: usize) -> Vec { - self.b - .elements - .iter() - .enumerate() - .filter(|(_, el)| el.owning_relationship == Some(rel)) - .map(|(i, _)| i) - .collect() + self.b.elements[rel].children.to_vec() } /// The element an `@id`-valued property of one of `e`'s owned @@ -8244,13 +11067,8 @@ impl ResolvedModel { } fn prop_target(&self, e: usize, key: &str) -> Option { - self.b.elements[e] - .props - .get(key)? - .get("@id")? - .as_str() - .and_then(|s| Uuid::parse_str(s).ok()) - .and_then(|id| self.by_id.get(&id).copied()) + let id = self.b.elements[e].props.get(key)?.as_reference()?; + self.by_id.get(&id).copied() } /// Expand a `ReferenceSubsetting` target into its written feature @@ -8356,13 +11174,11 @@ impl ResolvedModel { /// feature chain per relationship, links first→last. pub fn referenced_features(&mut self, e: ElementRef) -> Vec> { self.ensure_by_id(); - let rels: Vec = self.b.elements[e.0] + self.b.elements[e.0] .owned_relationships .iter() .copied() .filter(|&r| self.b.elements[r].ty == "ReferenceSubsetting") - .collect(); - rels.into_iter() .filter_map(|r| self.prop_target(r, "referencedFeature")) .map(|t| self.expand_chain(t)) .collect() @@ -8410,6 +11226,21 @@ impl ResolvedModel { } "OwningMembership" => { if let Some(succ) = self.rel_children(rel).first().copied() { + // A chain source (`first a.b`): the membership owns + // the synthesized chain feature and names it. + if parts.source.is_none() + && self.b.elements[succ].ty == "Feature" + && self.b.elements[succ] + .owned_relationships + .iter() + .any(|&r| self.b.elements[r].ty == "FeatureChaining") + { + parts.source = self + .prop_target(rel, "memberElement") + .map(ElementRef) + .or(Some(ElementRef(succ))); + continue; + } if self.b.elements[succ].ty.starts_with("Succession") { parts.target = self .connector_end_targets(ElementRef(succ)) @@ -8429,13 +11260,11 @@ impl ResolvedModel { /// A state's entry/do/exit subactions in declaration order: /// (`"entry"` | `"do"` | `"exit"`, the action element). pub fn state_subactions(&mut self, e: ElementRef) -> Vec<(String, ElementRef)> { - let rels: Vec = self.b.elements[e.0] + self.b.elements[e.0] .owned_relationships .iter() .copied() .filter(|&r| self.b.elements[r].ty == "StateSubactionMembership") - .collect(); - rels.into_iter() .filter_map(|rel| { let kind = self.b.elements[rel] .props @@ -8508,34 +11337,237 @@ pub fn doc_display_text(body: &str) -> String { lines.join("\n").trim().to_string() } -/// Split `A::'two words'::b` into unquoted segments. +/// Split `A::'two words'::b` into raw (unescaped) segments: the +/// inverse of `escape_name` per segment, so a name that spells as +/// `'a\\nb'` (a newline) resolves to the element the spelling came +/// from. Empty segments are dropped. fn split_qualified(name: &str) -> Vec { - let mut out = Vec::new(); - let mut cur = String::new(); - let mut chars = name.chars().peekable(); - while let Some(c) = chars.next() { - match c { - '\'' => { - while let Some(c) = chars.next() { - match c { - '\\' => { - if let Some(e) = chars.next() { - cur.push(e); - } - } - '\'' => break, - c => cur.push(c), - } - } - } - ':' if chars.peek() == Some(&':') => { - chars.next(); - out.push(std::mem::take(&mut cur)); - } - c => cur.push(c), - } - } - out.push(cur); + let mut out = sysmlv2_syntax::name::split_canonical(name); out.retain(|s| !s.is_empty()); out } + +#[cfg(test)] +mod split_qualified_tests { + use super::split_qualified; + + #[test] + fn decodes_control_escapes_like_escape_name_spells_them() { + let raw = "APS M3 to APS-TMT Interface Point\nAlignment Error Analysis"; + let spelled = format!("P::{}", sysmlv2_syntax::ast::escape_name(raw)); + assert_eq!( + spelled, + "P::'APS M3 to APS-TMT Interface Point\\nAlignment Error Analysis'" + ); + assert_eq!( + split_qualified(&spelled), + vec!["P".to_string(), raw.to_string()] + ); + for raw in [ + "a\tb", + "a\rb", + "a\u{0008}b", + "a\u{000C}b", + "it's", + "back\\slash", + "a::b", + ] { + let spelled = sysmlv2_syntax::ast::escape_name(raw); + assert_eq!( + split_qualified(&spelled), + vec![raw.to_string()], + "{spelled}" + ); + } + } + + #[test] + fn spelled_qualified_name_resolves_back_to_its_element() { + let mut model = crate::model::Model::new(); + let unit = model.add_source( + "t.sysml".to_string(), + "package P { part def 'APS M3 to APS-TMT Interface Point\\nAlignment Error Analysis'; }", + ); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + let mut r = super::ResolvedModel::build(&model); + let pkg = r.resolve_qualified("P").unwrap(); + let def = r.owned_members(pkg)[0]; + let spelled = r.element_qualified_name(def).unwrap(); + assert_eq!( + spelled, + "P::'APS M3 to APS-TMT Interface Point\\nAlignment Error Analysis'" + ); + assert_eq!(r.resolve_qualified(&spelled), Some(def)); + } + + #[test] + fn keeps_bare_and_plain_quoted_segments() { + assert_eq!( + split_qualified("A::'two words'::b"), + vec!["A".to_string(), "two words".to_string(), "b".to_string()] + ); + assert_eq!(split_qualified("::A::"), vec!["A".to_string()]); + } +} + +#[cfg(test)] +mod unused_imports_tests; + +/// Persist element headers and their variable-length lists as separate tables. +/// A decoded library shares each table's contiguous backing storage. +mod element_table { + use super::*; + use crate::{ + flat::{self, Row}, + layered::LayeredVec, + properties::{Atom, Key, Properties}, + }; + use serde::{Deserialize, Deserializer, Serialize, Serializer, ser::SerializeTuple}; + #[derive(Serialize)] + struct HeaderRef<'a> { + ty: &'a str, + id: Uuid, + path: &'a str, + present: u64, + flags: u64, + owner: Option, + } + #[derive(Deserialize)] + struct Header { + ty: Kind, + id: Uuid, + path: String, + present: u64, + flags: u64, + owner: Option, + } + struct Kind(&'static str); + impl<'de> Deserialize<'de> for Kind { + fn deserialize>(d: D) -> Result { + struct Visitor; + impl serde::de::Visitor<'_> for Visitor { + type Value = Kind; + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("a known metaclass") + } + fn visit_str(self, s: &str) -> Result { + crate::metaclass::canonical_name(s) + .map(Kind) + .ok_or_else(|| E::custom("unknown element metaclass")) + } + } + d.deserialize_str(Visitor) + } + } + pub fn serialize(elements: &LayeredVec, s: S) -> Result { + struct Headers<'a>(&'a LayeredVec); + impl Serialize for Headers<'_> { + fn serialize(&self, s: S) -> Result { + s.collect_seq(self.0.iter().map(|e| HeaderRef { + ty: e.ty, + id: e.id, + path: &e.path, + present: e.props.present, + flags: e.props.flags, + owner: e.owning_relationship, + })) + } + } + let mut tuple = s.serialize_tuple(4)?; + tuple.serialize_element(&Headers(elements))?; + tuple.serialize_element(&flat::Slices( + elements.iter().map(|e| &*e.props.entries).collect(), + ))?; + tuple.serialize_element(&flat::Slices( + elements.iter().map(|e| &*e.owned_relationships).collect(), + ))?; + tuple.serialize_element(&flat::Slices( + elements.iter().map(|e| &*e.children).collect(), + ))?; + tuple.end() + } + pub fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { + #[derive(Deserialize)] + struct Wire { + headers: Vec
, + #[serde(with = "flat::table")] + props: Vec>, + #[serde(with = "flat::table")] + owned: Vec>, + #[serde(with = "flat::table")] + children: Vec>, + } + let wire = Wire::deserialize(d)?; + let n = wire.headers.len(); + if wire.props.len() != n + || wire.owned.len() != n + || wire.children.len() != n + || wire + .props + .iter() + .any(|r| r.windows(2).any(|p| p[0].0 >= p[1].0)) + { + return Err(serde::de::Error::custom("invalid element table")); + } + Ok(wire + .headers + .into_iter() + .zip(wire.props) + .zip(wire.owned) + .zip(wire.children) + .map(|(((h, entries), owned_relationships), children)| Elem { + ty: h.ty.0, + id: h.id, + path: h.path, + props: Properties { + present: h.present, + flags: h.flags, + entries, + }, + owned_relationships, + children, + owning_relationship: h.owner, + }) + .collect()) + } +} + +#[cfg(test)] +mod element_table_tests { + use super::*; + use serde::{Deserialize, Serialize}; + #[derive(Serialize, Deserialize)] + struct Table(#[serde(with = "super::element_table")] crate::layered::LayeredVec); + #[test] + fn malformed_headers_and_unsorted_properties_are_rejected() { + let mut model = crate::model::Model::new(); + model.add_library_source("l.sysml", "package L { attribute x = 1; }"); + let mut b = Builder::default(); + b.build_model(&model); + let clean = Table(b.elements); + let bytes = crate::cache_codec::encode(&clean).unwrap(); + assert!(crate::cache_codec::decode::
(&bytes).is_ok()); + let mut bad = Table(clean.0.clone()); + bad.0[0].ty = "UnknownMetaclass"; + assert!( + crate::cache_codec::decode::
(&crate::cache_codec::encode(&bad).unwrap()) + .is_err() + ); + let mut bad = Table(clean.0.clone()); + let row = (0..bad.0.len()) + .find(|&i| bad.0[i].props.entries.len() > 1) + .unwrap(); + bad.0[row].props.entries.make_mut().reverse(); + assert!( + crate::cache_codec::decode::
(&crate::cache_codec::encode(&bad).unwrap()) + .is_err() + ); + let mut bad = Table(clean.0); + let duplicate = bad.0[row].props.entries[0].clone(); + bad.0[row].props.entries.make_mut().insert(0, duplicate); + assert!( + crate::cache_codec::decode::
(&crate::cache_codec::encode(&bad).unwrap()) + .is_err() + ); + } +} diff --git a/crates/sysmlv2-model/src/json/behavior.rs b/crates/sysmlv2-model/src/json/behavior.rs new file mode 100644 index 0000000..9425e83 --- /dev/null +++ b/crates/sysmlv2-model/src/json/behavior.rs @@ -0,0 +1,586 @@ +//! Behavior and expression structure over the resolved model: the derived +//! properties of states, transitions, the control and communication +//! action kinds, expressions and functions, multiplicity ranges, filter +//! memberships and the membership-side identity strings. Each function +//! documents the specification rule it implements (KerML/SysML clause +//! 8.3, `spec-refs/derived-properties.json`); the dispatch is in +//! `derived.rs`. +//! +//! Parameters. `ActionUsage::inputParameter(i)` reads `inputParameters()` +//! `= input->select(f | f.owner = self)`, the owned parameters whose +//! direction is `in` or `inout`. A parameter's direction is constrained +//! to `ParameterMembership::parameterDirection()` — `in` by default, +//! `out` for a ReturnParameterMembership (KerML +//! `checkParameterMembershipDirection`) — so an owned member parameter +//! with no spelled direction takes that default here +//! ([`ResolvedModel::effective_direction`], which the `input`/`output`/ +//! `directedFeature`/`parameter` families read too), as the pilot's +//! lowering of the action kinds relies on (a node's expression and body +//! parameters carry no direction on the wire). `argument(i)` is +//! `inputParameter(i)`'s `FeatureValue.value`. One lowering shape is +//! compensated for rather than read literally: an accept action's +//! trigger (`accept x at t`) is lowered as a TriggerInvocationExpression +//! that is itself a parameter member, where the pilot's grammar makes it +//! the payload parameter's value (API-GAPS issue 20) — it is not counted +//! as an input parameter, and an accept's `payloadArgument` falls back to +//! it. + +use super::derived::{Reference, dangling_id}; +use super::{ElementRef, ResolvedModel}; +use crate::metaclass::conforms; + +impl ResolvedModel { + // ---- states and transitions ---- + + /// `StateUsage::entryAction` / `doAction` / `exitAction` (and on + /// StateDefinition): the owned member of the StateSubactionMembership + /// with the given `kind`. + pub(super) fn d_state_subaction(&mut self, e: ElementRef, kind: &str) -> Option { + let rels = self.owned_relationships_of_kind(e, "StateSubactionMembership"); + rels.into_iter() + .find(|&r| self.prop_str(r.0, "kind") == Some(kind)) + .and_then(|r| self.d_owned_member_element(r)) + } + + /// `TransitionUsage::triggerAction` / `guardExpression` / + /// `effectAction`: the transition features of the owned + /// TransitionFeatureMemberships with the given `kind`, of the given + /// metaclass (`AcceptActionUsage`, `Expression`, `ActionUsage`). + pub(super) fn d_transition_features( + &mut self, + e: ElementRef, + kind: &str, + cast: &str, + ) -> Vec { + let rels = self.owned_relationships_of_kind(e, "TransitionFeatureMembership"); + rels.into_iter() + .filter(|&r| self.prop_str(r.0, "kind") == Some(kind)) + .filter_map(|r| self.d_owned_member_element(r)) + .filter(|&f| self.is_kind(f, cast)) + .collect() + } + + /// `TransitionUsage::succession = ownedMember->selectByKind(Succession)->at(1)`. + pub(super) fn d_succession(&mut self, e: ElementRef) -> Option { + self.d_owned_members(e) + .into_iter() + .find(|&m| self.is_kind(m, "Succession")) + } + + /// `TransitionUsage::source = sourceFeature().featureTarget` as an + /// ActionUsage, where `sourceFeature()` is the first Feature among the + /// members of the non-feature memberships whose feature target is an + /// ActionUsage — the `first S` membership, or the owning membership of + /// a synthesized chain feature (`first a.b`). + pub(super) fn d_transition_source(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + let memberships: Vec = self + .d_owned_memberships(e) + .into_iter() + .filter(|&m| !self.is_kind(m, "FeatureMembership")) + .collect(); + for m in memberships { + let Some(member) = self.d_member_element(m) else { + continue; + }; + let target = match member { + Reference::Element(f) if self.is_kind(f, "Feature") => self.d_feature_target(f), + Reference::Element(_) => continue, + outside => outside, + }; + if let Some(t) = self.cast(target, "ActionUsage") { + return Some(t); + } + } + None + } + + /// `TransitionUsage::target = succession.targetFeature->first().featureTarget` + /// as an ActionUsage. The succession's target end is its second + /// connector end: the grammar leaves the transition succession's + /// source end unspelled (the source is the transition's own), so + /// `targetFeature` — the related features past the first — reads the + /// target end by position rather than through `relatedFeature`, which + /// an unspelled end does not enter. + pub(super) fn d_transition_target(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + let succession = self.d_succession(e)?; + let end = self + .d_ends(self.d_owned_features(succession)) + .into_iter() + .nth(1)?; + let target = self.d_referenced_feature_target(end)?; + self.cast(target, "ActionUsage") + } + + // ---- parameters and arguments ---- + + /// The feature's direction as the specification constrains it: the + /// spelled `direction`, else the default of its owning + /// ParameterMembership (`in`; `out` for a ReturnParameterMembership), + /// else none. A TriggerInvocationExpression owned as a parameter + /// member is an accept action's trigger value, not a parameter (see + /// the module documentation), and has none. + pub(super) fn effective_direction(&self, f: ElementRef) -> Option<&str> { + if let Some(d) = self.prop_str(f.0, "direction") { + return Some(d); + } + if self.b.elements[f.0].ty == "TriggerInvocationExpression" { + return None; + } + let m = self.b.elements[f.0].owning_relationship?; + let ty = self.b.elements[m].ty; + if conforms(ty, "ReturnParameterMembership") { + Some("out") + } else if conforms(ty, "ParameterMembership") { + Some("in") + } else { + None + } + } + + /// `inputParameters() = input->select(f | f.owner = self)`: the owned + /// features whose effective direction is `in` or `inout`, in feature + /// order. + pub(super) fn d_input_parameters(&self, e: ElementRef) -> Vec { + self.d_owned_features(e) + .into_iter() + .filter(|&f| matches!(self.effective_direction(f), Some("in" | "inout"))) + .collect() + } + + /// `inputParameter(i)` (1-based). + pub(super) fn d_input_parameter(&self, e: ElementRef, i: usize) -> Option { + self.d_input_parameters(e) + .into_iter() + .nth(i.checked_sub(1)?) + } + + /// `argument(i)`: the value expression of `inputParameter(i)`'s + /// FeatureValue. + pub(super) fn d_argument(&self, e: ElementRef, i: usize) -> Option { + let p = self.d_input_parameter(e, i)?; + self.d_argument_of(p) + } + + /// The argument an input parameter carries: its FeatureValue's value + /// — or, for a trigger invocation's argument, which this lowering owns + /// as the parameter itself without the Feature-and-FeatureValue + /// wrapper (API-GAPS issue 20), the expression that is the parameter. + fn d_argument_of(&self, p: ElementRef) -> Option { + self.d_feature_value_of(p).or_else(|| { + let owner = self.b.elements[p.0] + .owning_relationship + .and_then(|m| self.d_owning_related_element_ro(m))?; + (self.is_kind(p, "Expression") + && self.b.elements[owner].ty == "TriggerInvocationExpression") + .then_some(p) + }) + } + + /// The owner of a relationship, read without building the owner map: + /// the element whose owned relationships list it. + fn d_owning_related_element_ro(&self, rel: usize) -> Option { + self.b.elements[rel] + .props + .get("owningRelatedElement") + .and_then(|v| v.as_reference()) + .and_then(|id| self.by_id.get(&id).copied()) + } + + /// `AcceptActionUsage::payloadArgument = argument(1)`: the payload + /// parameter's value, else the trigger this lowering owns beside the + /// payload (the pilot's grammar makes the trigger the payload's value; + /// API-GAPS issue 20). + pub(super) fn d_accept_payload_argument(&self, e: ElementRef) -> Option { + self.d_argument(e, 1).or_else(|| { + self.d_owned_features(e) + .into_iter() + .find(|&f| self.b.elements[f.0].ty == "TriggerInvocationExpression") + }) + } + + /// The value expression of the feature's owned FeatureValue. + fn d_feature_value_of(&self, f: ElementRef) -> Option { + self.owned_relationships_of_kind(f, "FeatureValue") + .into_iter() + .next() + .and_then(|fv| self.d_owned_member_element(fv)) + } + + /// `inputParameter(i)` cast to `kind`. An expression-valued parameter + /// (`ifArgument`, `whileArgument`, `untilArgument`) is, in the + /// grammar's lowering, a reference feature whose FeatureValue owns the + /// expression rather than the expression itself; the rule's + /// `oclAsType(Expression)` is read through that value. + pub(super) fn d_parameter_as(&self, e: ElementRef, i: usize, kind: &str) -> Option { + let p = self.d_input_parameter(e, i)?; + if self.is_kind(p, kind) { + return Some(p); + } + if kind == "Expression" { + return self + .d_feature_value_of(p) + .filter(|&v| self.is_kind(v, kind)); + } + None + } + + /// `ForLoopActionUsage::loopVariable = ownedFeature->first()` as a + /// ReferenceUsage. + pub(super) fn d_loop_variable(&self, e: ElementRef) -> Option { + self.d_owned_features(e) + .into_iter() + .next() + .filter(|&f| self.is_kind(f, "ReferenceUsage")) + } + + // ---- references through subsetting ---- + + /// `referencedFeatureTarget() = ownedReferenceSubsetting.referencedFeature.featureTarget`. + pub(super) fn d_referenced_feature_target(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + let sub = self + .owned_relationships_of_kind(e, "ReferenceSubsetting") + .into_iter() + .next()?; + let atom = self.b.elements[sub.0] + .props + .get("referencedFeature")? + .clone(); + Some(match self.reference_of(&atom)? { + Reference::Element(f) => self.d_feature_target(f), + outside => outside, + }) + } + + /// `EventOccurrenceUsage::eventOccurrence` and its narrowings + /// (`performedAction`, `exhibitedState`, `useCaseIncluded`, + /// `assertedConstraint`, `satisfiedRequirement`): `referencedFeatureTarget()` + /// cast to `kind`, or the element itself when it references nothing. + pub(super) fn d_referenced_or_self(&mut self, e: ElementRef, kind: &str) -> Option { + match self.d_referenced_feature_target(e) { + Some(target) => self.cast(target, kind), + None => Some(Reference::Element(e)), + } + } + + /// `UseCaseUsage::includedUseCase = ownedUseCase->selectByKind(IncludeUseCaseUsage).useCaseIncluded`. + pub(super) fn d_included_use_cases(&mut self, e: ElementRef) -> Vec { + let includes: Vec = self + .d_owned_features(e) + .into_iter() + .filter(|&f| self.is_kind(f, "IncludeUseCaseUsage")) + .collect(); + includes + .into_iter() + .filter_map(|i| self.d_referenced_or_self(i, "UseCaseUsage")) + .collect() + } + + // ---- expressions and functions ---- + + /// `Expression::result` / `Function::result`: the owned member + /// parameter of the first ReturnParameterMembership (the inherited + /// result waits for the closure policy). + pub(super) fn d_result(&mut self, e: ElementRef) -> Option { + self.d_feature_memberships(e) + .into_iter() + .find(|&m| self.is_kind(m, "ReturnParameterMembership")) + .and_then(|m| self.d_owned_member_element(m)) + } + + /// The types of `e` of the given kind: `Expression::function`, + /// `BooleanExpression::predicate`, `Connector::association`, + /// `Flow::interaction`, `MetadataFeature::metaclass` — each + /// `type->selectByKind(Kind)`. + pub(super) fn d_types_of_kind(&mut self, e: ElementRef, kind: &str) -> Vec { + let types = self.d_types(e); + types + .into_iter() + .filter_map(|t| self.cast(t, kind)) + .collect() + } + + /// `InstantiationExpression::instantiatedType`: for an + /// OperatorExpression, `resolveGlobal` of the operator's function in + /// `BaseFunctions`, `DataFunctions` or `ControlFunctions` — an element + /// when the library is loaded, an external id through a library name + /// table, else null; for an invocation or constructor, the member of + /// the expression's first non-feature membership (the `fn`/`type` + /// member the lowering writes), a Type. + pub(super) fn d_instantiated_type(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + if self.is_kind(e, "OperatorExpression") { + let operator = self.prop_str(e.0, "operator")?.to_string(); + let candidates: Vec<(String, String)> = + ["BaseFunctions", "DataFunctions", "ControlFunctions"] + .iter() + .map(|ns| (format!("{ns}::'{operator}'"), format!("{ns}::{operator}"))) + .collect(); + return self.library_element_named(&candidates); + } + if self.b.elements[e.0].ty == "TriggerInvocationExpression" { + // SysML `TriggerInvocationExpression::instantiatedType()`: + // `resolveGlobal('Triggers::TriggerWhen' | 'TriggerAt' | 'TriggerAfter')` by kind. + let name = match self.prop_str(e.0, "kind") { + Some("when") => "TriggerWhen", + Some("at") => "TriggerAt", + _ => "TriggerAfter", + }; + let qn = format!("Triggers::{name}"); + return self.library_element_named(&[(qn.clone(), qn)]); + } + let memberships: Vec = self + .d_owned_memberships(e) + .into_iter() + .filter(|&m| !self.is_kind(m, "FeatureMembership")) + .collect(); + let members: Vec = memberships + .into_iter() + .filter_map(|m| self.d_member_element(m)) + .collect(); + members.into_iter().find_map(|t| self.cast(t, "Type")) + } + + /// A library element by qualified name — `(quoted spelling, raw + /// spelling)` candidates in order: an element of a loaded library, or + /// an external id through the library name table + /// ([`Self::set_library_names`]); a user element of the same name is + /// not it (`resolveGlobal` names the library). + pub(super) fn library_element_named( + &mut self, + candidates: &[(String, String)], + ) -> Option { + for (quoted, raw) in candidates { + if let Some(f) = self + .resolve_qualified(quoted) + .filter(|&f| self.is_library_element(f)) + { + return Some(Reference::Element(f)); + } + if let Some(&id) = self.external_by_name.get(raw) { + return Some(Reference::External(id)); + } + } + None + } + + /// `InvocationExpression::argument` / `ConstructorExpression::argument`: + /// for each input parameter of the instantiated type (each feature, + /// for a constructor) in order, the value of the owned parameter that + /// redefines it — explicitly, or positionally (the lowering's implied + /// parameter redefinition). When the instantiated type is outside the + /// model, or its parameters are not visible at the passthrough level + /// (inherited), the owned parameters' values in order — the positional + /// reading. + pub(super) fn d_arguments(&mut self, e: ElementRef) -> Vec { + self.ensure_by_id(); + let params = self.d_input_parameters(e); + let callee = self.d_instantiated_type(e); + let targets: Vec = match callee { + Some(Reference::Element(callee)) if self.is_kind(e, "ConstructorExpression") => { + self.d_features(callee) + } + Some(Reference::Element(callee)) => { + // The callee's inputs — its inherited ones too under the + // closure policy. + let features = self.d_features(callee); + self.d_directed(features, Some(true)) + } + _ => Vec::new(), + }; + if targets.is_empty() { + return params + .into_iter() + .filter_map(|p| self.d_argument_of(p)) + .map(Reference::Element) + .collect(); + } + let inputs = targets; + // Explicit redefinition targets per owned parameter; the + // positional ones take the inputs left in order. + let redefined: Vec> = params + .iter() + .map(|&p| { + self.owned_relationships_of_kind(p, "Redefinition") + .into_iter() + .find_map(|r| self.prop_target(r.0, "redefinedFeature")) + }) + .collect(); + let mut positional = params + .iter() + .zip(&redefined) + .filter(|(_, r)| r.is_none()) + .map(|(&p, _)| p); + let mut out = Vec::new(); + for inp in inputs { + let explicit = params + .iter() + .zip(&redefined) + .find(|(_, r)| **r == Some(inp.0)) + .map(|(&p, _)| p); + let p = match explicit.or_else(|| positional.next()) { + Some(p) => p, + None => break, + }; + if let Some(v) = self.d_argument_of(p) { + out.push(Reference::Element(v)); + } + } + out + } + + /// `FeatureReferenceExpression::referent`: the member of the first + /// non-parameter membership, a Feature. + pub(super) fn d_referent(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + let m = self + .d_owned_memberships(e) + .into_iter() + .find(|&m| !self.is_kind(m, "ParameterMembership"))?; + let member = self.d_member_element(m)?; + self.cast(member, "Feature") + } + + /// `AssignmentActionUsage::referent` and + /// `MetadataAccessExpression::referencedElement`: the first member of + /// the non-feature memberships (a Feature for the assignment). + pub(super) fn d_unowned_member(&mut self, e: ElementRef, kind: &str) -> Option { + self.ensure_by_id(); + let memberships: Vec = self + .d_owned_memberships(e) + .into_iter() + .filter(|&m| !self.is_kind(m, "FeatureMembership")) + .collect(); + let members: Vec = memberships + .into_iter() + .filter_map(|m| self.d_member_element(m)) + .collect(); + members.into_iter().find_map(|t| self.cast(t, kind)) + } + + /// `Function::expression = step->selectByKind(Expression)`, over the + /// (passthrough) steps. + pub(super) fn d_function_expressions(&mut self, e: ElementRef) -> Vec { + self.d_features(e) + .into_iter() + .filter(|&f| self.is_kind(f, "Expression")) + .collect() + } + + // ---- multiplicity and filters ---- + + /// `MultiplicityRange::bound`: the owned member Expressions, in order + /// (one: the upper bound; two: lower then upper). + pub(super) fn d_bounds(&self, e: ElementRef) -> Vec { + self.d_owned_members(e) + .into_iter() + .filter(|&m| self.is_kind(m, "Expression")) + .collect() + } + + /// `Package::filterCondition` / `ViewUsage::viewCondition`: + /// `ownedMembership->selectByKind(ElementFilterMembership).condition`. + pub(super) fn d_filter_conditions(&self, e: ElementRef) -> Vec { + self.owned_relationships_of_kind(e, "ElementFilterMembership") + .into_iter() + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + // ---- memberships ---- + + /// `Membership::memberElementId = memberElement.elementId` (and the + /// OwningMembership redefinition): the id as the interchange spells + /// it — an unresolved spelling by its deterministic dangling id. + pub(super) fn d_member_element_id(&mut self, m: ElementRef) -> Option { + Some(match self.d_member_element(m)? { + Reference::Element(e) => self.element_id(e).to_string(), + Reference::External(id) => id.to_string(), + Reference::Unresolved(spelling) => dangling_id(&spelling), + }) + } + + /// `OwningMembership::ownedMemberName = ownedMemberElement.name` and + /// `ownedMemberShortName = ownedMemberElement.shortName`. + pub(super) fn d_owned_member_name(&mut self, m: ElementRef, short: bool) -> Option { + let member = self.d_owned_member_element(m)?; + if short { + self.element_short_name(member) + } else { + self.element_effective_name(member) + } + } + + // ---- typing residue ---- + + /// `OccurrenceUsage::individualDefinition`: the first occurrence + /// definition with `isIndividual` — a property test, which a target + /// outside the model cannot pass. + pub(super) fn d_individual_definition(&mut self, e: ElementRef) -> Option { + let types = self.d_types(e); + types + .into_iter() + .filter_map(|t| t.element()) + .find(|&t| { + self.is_kind(t, "OccurrenceDefinition") && self.prop_bool(t.0, "isIndividual") + }) + .map(Reference::Element) + } + + /// `Flow::payloadFeature = ownedFeature->selectByKind(PayloadFeature)->first()`. + pub(super) fn d_payload_feature(&self, e: ElementRef) -> Option { + self.d_owned_features(e) + .into_iter() + .find(|&f| self.is_kind(f, "PayloadFeature")) + } + + /// `Flow::payloadType = payloadFeature.type`. + pub(super) fn d_payload_type(&mut self, e: ElementRef) -> Vec { + match self.d_payload_feature(e) { + Some(p) => self.d_types(p), + None => Vec::new(), + } + } + + /// `PortDefinition::conjugatedPortDefinition`: the owned member that + /// is a ConjugatedPortDefinition; `PortConjugation::conjugatedPortDefinition`: + /// the owning type. + pub(super) fn d_conjugated_port_definition(&mut self, e: ElementRef) -> Option { + if self.is_kind(e, "PortConjugation") { + return self + .d_owning_type_any(e) + .filter(|&o| self.is_kind(o, "ConjugatedPortDefinition")); + } + self.d_owned_members(e) + .into_iter() + .find(|&m| self.is_kind(m, "ConjugatedPortDefinition")) + } + + // ---- helpers ---- + + /// A kind test on a reference: an element of the model passes when + /// its metaclass conforms; a target outside the model is reported as + /// it is — the model cannot classify it, and a reference the model + /// holds is not dropped for that (a well-formed model's typing + /// constraints make the test hold wherever the reference resolved). + pub(super) fn cast(&self, r: Reference, kind: &str) -> Option { + match r { + Reference::Element(e) => self.is_kind(e, kind).then_some(Reference::Element(e)), + outside => Some(outside), + } + } + + pub(super) fn prop_str(&self, e: usize, key: &str) -> Option<&str> { + self.b.elements[e].props.get(key).and_then(|v| v.as_str()) + } + + pub(super) fn prop_bool(&self, e: usize, key: &str) -> bool { + self.b.elements[e] + .props + .get(key) + .and_then(|v| v.as_bool()) + .unwrap_or(false) + } +} diff --git a/crates/sysmlv2-model/src/json/cases.rs b/crates/sysmlv2-model/src/json/cases.rs new file mode 100644 index 0000000..7872513 --- /dev/null +++ b/crates/sysmlv2-model/src/json/cases.rs @@ -0,0 +1,133 @@ +//! Requirement, case and view structure over the resolved model: the +//! subject, actor, stakeholder and objective parameters, the required and +//! assumed constraints, framed concerns, verified and satisfied +//! requirements, view renderings, conditions and exposed elements. Each +//! function documents the specification rule it implements; the dispatch +//! is in `derived.rs`. Most of these read `featureMembership`, whose +//! specification unions the inherited memberships, and are answered at +//! the passthrough level (the owned side) until the closure policy is on; +//! `requiredConstraint`/`assumedConstraint` read `ownedFeatureMembership` +//! and are exact. + +use super::derived::Reference; +use super::{ElementRef, ResolvedModel}; + +impl ResolvedModel { + /// The owned members of the feature memberships of `kind`, in order + /// (`featureMembership->selectByKind(Kind).ownedMemberX`) — the owned + /// memberships at the passthrough level, the inherited ones too under + /// the closure policy. + pub(super) fn d_members_via(&mut self, e: ElementRef, kind: &str) -> Vec { + self.d_feature_memberships(e) + .into_iter() + .filter(|&m| self.is_kind(m, kind)) + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + /// `requiredConstraint` / `assumedConstraint`: + /// `ownedFeatureMembership->selectByKind(RequirementConstraintMembership)->select(kind = K).ownedConstraint`. + pub(super) fn d_requirement_constraints(&self, e: ElementRef, kind: &str) -> Vec { + self.owned_relationships_of_kind(e, "RequirementConstraintMembership") + .into_iter() + .filter(|&m| self.prop_str(m.0, "kind") == Some(kind)) + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + /// `RequirementConstraintMembership::referencedConstraint` (and its + /// narrowings `referencedConcern`, `verifiedRequirement`, + /// `ViewRenderingMembership::referencedRendering`): the owned member's + /// `referencedFeatureTarget()`, else the owned member itself, cast to + /// `kind`. + pub(super) fn d_referenced_member(&mut self, m: ElementRef, kind: &str) -> Option { + let owned = self.d_owned_member_element(m)?; + self.d_referenced_or_self(owned, kind) + } + + /// `VerificationCaseUsage::verifiedRequirement` (and on the + /// definition): the verified requirements of the objective + /// requirement's RequirementVerificationMemberships. + pub(super) fn d_verified_requirements(&mut self, e: ElementRef) -> Vec { + let Some(objective) = self + .d_members_via(e, "ObjectiveMembership") + .into_iter() + .next() + else { + return Vec::new(); + }; + let memberships: Vec = self + .d_feature_memberships(objective) + .into_iter() + .filter(|&m| self.is_kind(m, "RequirementVerificationMembership")) + .collect(); + // `->asOrderedSet()`: each requirement once, in first-mention order. + let mut out: Vec = Vec::new(); + for m in memberships { + if let Some(r) = self.d_referenced_member(m, "RequirementUsage") { + if !out.contains(&r) { + out.push(r); + } + } + } + out + } + + /// `SatisfyRequirementUsage::satisfyingFeature`: the feature bound to + /// the subject parameter — in the lowering the pilot and this toolkit + /// share, the subject parameter's FeatureValue is a + /// FeatureReferenceExpression whose referent is that feature. + pub(super) fn d_satisfying_feature(&mut self, e: ElementRef) -> Option { + let subject = self + .d_members_via(e, "SubjectMembership") + .into_iter() + .next()?; + let value = self + .owned_relationships_of_kind(subject, "FeatureValue") + .into_iter() + .next() + .and_then(|fv| self.d_owned_member_element(fv))?; + if !self.is_kind(value, "FeatureReferenceExpression") { + return None; + } + let referent = self.d_referent(value)?; + Some(match referent { + Reference::Element(f) => self.d_feature_target(f), + outside => outside, + }) + } + + /// `ViewUsage::viewRendering` (and on the definition): the referenced + /// rendering of the first ViewRenderingMembership. + pub(super) fn d_view_rendering(&mut self, e: ElementRef) -> Option { + let m = self + .d_feature_memberships(e) + .into_iter() + .find(|&m| self.is_kind(m, "ViewRenderingMembership"))?; + self.d_referenced_member(m, "RenderingUsage") + } + + /// `satisfiedViewpoint = ownedRequirement->selectByKind(ViewpointUsage)->select(isComposite)`. + pub(super) fn d_satisfied_viewpoints(&self, e: ElementRef) -> Vec { + self.d_owned_features(e) + .into_iter() + .filter(|&f| self.is_kind(f, "ViewpointUsage") && self.prop_bool(f.0, "isComposite")) + .collect() + } + + /// `viewpointStakeholder = framedConcern.featureMembership->selectByKind(StakeholderMembership).ownedStakeholderParameter`. + pub(super) fn d_viewpoint_stakeholders(&mut self, e: ElementRef) -> Vec { + let concerns = self.d_members_via(e, "FramedConcernMembership"); + concerns + .into_iter() + .flat_map(|c| self.d_members_via(c, "StakeholderMembership")) + .collect() + } + + /// `ViewUsage::exposedElement`: the members visible through the + /// view's expose imports that its conditions admit + /// ([`Self::view_exposed_elements`], in discovery order). + pub(super) fn d_exposed_elements(&mut self, e: ElementRef) -> Vec { + self.view_exposed_elements(e) + } +} diff --git a/crates/sysmlv2-model/src/json/closures.rs b/crates/sysmlv2-model/src/json/closures.rs new file mode 100644 index 0000000..ac67584 --- /dev/null +++ b/crates/sysmlv2-model/src/json/closures.rs @@ -0,0 +1,215 @@ +//! The closures and the inheritance-aware switch (plan §33h): the four +//! closure names — `inheritedMembership`, `inheritedFeature`, +//! `importedMembership`, `featuringType` — over the resolver's own +//! inheritance and import walks, and the *closure policy* under which the +//! inheritance-aware families (`feature`, `featureMembership`, +//! `membership`, `member` and everything defined over them) switch from +//! the passthrough level — the owned side — to their specification +//! definition, which unions the inherited and imported memberships. +//! +//! The read API answers the closure names whatever the policy: a consumer +//! asking for `inheritedMembership` wants the walk. The policy governs the +//! *families* (so that `feature` on a part lists what it inherits) and, +//! in the full-form emitter, whether the closure names are written at all +//! — the payload grows with the closures materialized per element, which +//! is why the passthrough level exists (INTEROP.md). +//! +//! The walk stops at a fixed heritage depth ([`super::MAX_RESOLUTION_DEPTH`]) +//! and reports it ([`ResolvedModel::closure_truncated`]) rather than +//! presenting a cut enumeration as the closure; the emitter refuses to +//! write one. + +use super::{ElementRef, InheritedBindings, LookupAccess, ResolvedModel}; +use crate::metaclass::conforms; +use std::collections::HashSet; + +/// How the inheritance-aware families are answered. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub enum ClosurePolicy { + /// The owned side only — the passthrough level, the default. + #[default] + Passthrough, + /// The specification's definition over the inheritance and import + /// closures; `include_implied` extends the heritage over the implied + /// library bases (every part inherits `Parts::Part`'s members). + Closure { include_implied: bool }, +} + +impl ClosurePolicy { + /// Whether the closures are in force, and with the implied heritage. + pub fn include_implied(self) -> Option { + match self { + Self::Passthrough => None, + Self::Closure { include_implied } => Some(include_implied), + } + } +} + +/// The four closure names: answered by the walks, written by the emitter +/// only under the closure policy. +pub const CLOSURE_NAMES: &[&str] = &[ + "featuringType", + "importedMembership", + "inheritedFeature", + "inheritedMembership", +]; + +impl ResolvedModel { + /// The closure policy in force for [`Self::derived`]. + pub fn closure_policy(&self) -> ClosurePolicy { + self.closure_policy + } + + /// Set the closure policy for [`Self::derived`]: under + /// [`ClosurePolicy::Closure`] the inheritance-aware families answer + /// their specification definition over the inherited and imported + /// memberships (with or without the implied library heritage); under + /// [`ClosurePolicy::Passthrough`] the owned side only. The four closure + /// names are answered either way (with the policy's implied flag, or + /// without the implied heritage under passthrough). + pub fn set_closure_policy(&mut self, policy: ClosurePolicy) { + self.closure_policy = policy; + } + + fn include_implied(&self) -> bool { + self.closure_policy.include_implied().unwrap_or(false) + } + + /// Whether the inheritance or import walk behind the closures of `e` + /// hit the resolver's depth budget, so a closure of `e` would be + /// incomplete. A closure the emitter is asked to write for such an + /// element is refused, not truncated. + pub fn closure_truncated(&mut self, e: ElementRef) -> bool { + let include_implied = self.include_implied(); + if self.inheritance_walk_truncated(e, include_implied) { + return true; + } + let Some(&s) = self.b.elem_scope.get(&e.0) else { + return false; + }; + if let Some(&t) = self.import_truncated.get(&(s, include_implied)) { + return t; + } + let mut out = InheritedBindings::default(); + self.b + .imported_bindings(s, include_implied, LookupAccess::All, &mut out); + self.import_truncated + .insert((s, include_implied), out.truncated); + out.truncated + } + + // ---- the closure names ---- + + /// `Type::inheritedMembership`: the Membership relationships `e` + /// inherits, per the resolver's walk ([`Self::inherited_memberships`]). + pub(super) fn d_inherited_memberships(&mut self, e: ElementRef) -> Vec { + let include_implied = self.include_implied(); + self.inherited_memberships(e, include_implied) + } + + /// `Type::inheritedFeature = inheritedMembership->selectByKind(FeatureMembership).memberFeature` + /// — selected by the *membership* kind (a package-owned feature + /// arriving through an imported membership is not one), unlike the + /// navigation accessor [`Self::inherited_features`]. + pub(super) fn d_inherited_features(&mut self, e: ElementRef) -> Vec { + self.d_inherited_memberships(e) + .into_iter() + .filter(|&m| conforms(self.b.elements[m.0].ty, "FeatureMembership")) + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + /// `Namespace::importedMembership = ownedImport.importedMemberships(…)`: + /// the Memberships the namespace's imports bring in — every owned + /// import, whatever its visibility (a private import imports for its + /// owner; it is the *re-export* through heritage that private + /// excludes) — each imported member's owning membership, and the + /// imported alias memberships, admitted by the imports' filter + /// conditions, in discovery order (per import, declaration order). + /// Two deviations from the normative operation: a `import Q::alias;` + /// contributes the aliased element's owning membership rather than + /// the alias Membership itself, and a mutual public-import cycle + /// lists a namespace's own memberships under its imports (the + /// operation's `excluded->including(self)` seed), which `membership` + /// deduplicates. + pub fn imported_memberships(&mut self, e: ElementRef) -> Vec { + let Some(&s) = self.b.elem_scope.get(&e.0) else { + return Vec::new(); + }; + let include_implied = self.include_implied(); + let mut bindings = InheritedBindings::default(); + self.b + .imported_bindings(s, include_implied, LookupAccess::All, &mut bindings); + let mut out: Vec = Vec::new(); + let mut seen: HashSet = HashSet::new(); + for &(elem, _) in &bindings.members { + if let Some(r) = self.b.elements[elem].owning_relationship { + if seen.insert(r) { + out.push(ElementRef(r)); + } + } + } + for &r in &bindings.alias_rels { + if seen.insert(r) { + out.push(ElementRef(r)); + } + } + out + } + + // ---- the inheritance-aware bases ---- + + /// `Type::feature = featureMembership.ownedMemberFeature` under the + /// policy: the owned features, then the inherited feature + /// memberships' features (shadowing applied on the membership side); + /// the owned features alone at the passthrough level. + pub(super) fn d_features(&mut self, e: ElementRef) -> Vec { + if self.closure_policy == ClosurePolicy::Passthrough { + return self.d_owned_features(e); + } + let mut out: Vec = Vec::new(); + for m in self.d_feature_memberships(e) { + if let Some(f) = self.d_owned_member_element(m) { + if !out.contains(&f) { + out.push(f); + } + } + } + out + } + + /// `Type::featureMembership` under the policy: the owned feature + /// memberships, then the inherited memberships that are + /// FeatureMemberships. + pub(super) fn d_feature_memberships(&mut self, e: ElementRef) -> Vec { + let mut out = self.d_owned_feature_memberships(e); + if self.closure_policy != ClosurePolicy::Passthrough { + let inherited = self.d_inherited_memberships(e); + for m in inherited { + if conforms(self.b.elements[m.0].ty, "FeatureMembership") && !out.contains(&m) { + out.push(m); + } + } + } + out + } + + /// `Namespace::membership = ownedMembership ∪ importedMembership`, and + /// `Type::membership` adds `inheritedMembership`, under the policy; + /// the owned memberships alone at the passthrough level. + pub(super) fn d_memberships(&mut self, e: ElementRef) -> Vec { + let mut out = self.d_owned_memberships(e); + if self.closure_policy != ClosurePolicy::Passthrough { + let mut extra = self.imported_memberships(e); + if self.is_kind(e, "Type") { + extra.extend(self.d_inherited_memberships(e)); + } + for m in extra { + if !out.contains(&m) { + out.push(m); + } + } + } + out + } +} diff --git a/crates/sysmlv2-model/src/json/derived.rs b/crates/sysmlv2-model/src/json/derived.rs new file mode 100644 index 0000000..c08989d --- /dev/null +++ b/crates/sysmlv2-model/src/json/derived.rs @@ -0,0 +1,1883 @@ +//! Derived properties over the resolved model — the read API for the +//! abstract syntax's `isDerived` properties, answered per element from the +//! model rather than from an emitted payload. +//! +//! One function per property family computes the value the specification +//! defines (KerML/SysML clause 8.3, the `derive…` OCL rules recorded in +//! `spec-refs/derived-properties.json`); [`ResolvedModel::derived`] is the +//! single spec-name entry point over them. The answer is a tri-state so a +//! consumer can tell "not a property of this metaclass" from "a property +//! this toolkit does not compute" from a value — an empty list is only +//! meaningful in the third case. +//! +//! Fidelity is static: [`derives`] says, per metaclass and name, whether a +//! value is exact, a *passthrough* approximation, or not computed at all. A +//! passthrough name is one whose specification reads the inheritance or +//! import closures (`feature = featureMembership.ownedMemberFeature` where +//! `featureMembership` unions `inheritedMembership`); until the closure +//! policy is on, the value covers the owned side only, exactly as the +//! full-form emitter's passthrough conformance level does. +//! +//! Implied relationships (the library specializations every part and +//! action gets from SysML Tables 31/32) are not elements of the model; +//! they are synthesized on demand by the families that list relationships, +//! which this module does not reach yet. + +use super::derived_compositions::COMPOSITIONS; +use super::{ElementRef, ResolvedModel}; +use crate::metaclass::conforms; +use crate::properties::Atom; +use std::sync::Arc; +use uuid::Uuid; + +/// One target of a reference-typed derived property. A property whose +/// type is a reference to an arbitrary element (`type`, `annotatedElement`, +/// `importedElement`, `featureTarget`, a relationship's ends — anything +/// not composed under `ownedElement`/`ownedRelationship`) may point +/// outside the model: at a library element when no library is loaded, at +/// a foreign id, or at a spelling that never resolved. The layer reports +/// such a target rather than dropping it, so a consumer can tell "no +/// value" from "a value it has no element for". The full form spells an +/// `External` id as it is and an `Unresolved` spelling as the dangling id +/// the unresolved-reference policy derives from it. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum Reference { + /// An element of the model. + Element(ElementRef), + /// An element outside the model, by its interchange id. + External(Uuid), + /// A reference that did not resolve, by its written spelling. + Unresolved(String), +} + +impl Reference { + /// The model element, if the reference is one. + pub fn element(&self) -> Option { + match self { + Self::Element(e) => Some(*e), + _ => None, + } + } +} + +/// A derived property's value. The shape is fixed per property name: a +/// property composed under the ownership tree (`ownedFeature`, `owner`, +/// `ownedSpecialization`, …) answers `Element`/`Elements`, whose targets +/// are always model elements; a reference-typed property answers +/// `Reference`/`References` (see [`Reference`]). Non-exhaustive. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum DerivedValue { + /// The property is single-valued and has no value here (`null`). + Null, + Bool(bool), + Str(String), + /// A single-valued composition. + Element(ElementRef), + /// A multi-valued composition, in the specification's order. + Elements(Vec), + /// A single-valued reference, possibly outside the model. + Reference(Reference), + /// A multi-valued reference, in the specification's order, targets + /// outside the model included. + References(Vec), + /// A multi-valued string property — the requirement/concern `text`. + Strings(Vec), +} + +impl DerivedValue { + /// The single model element of a single-valued value, composition or + /// reference; `None` for `Null`, a target outside the model, or a + /// multi-valued value. + pub fn element(&self) -> Option { + match self { + Self::Element(e) => Some(*e), + Self::Reference(r) => r.element(), + _ => None, + } + } + + /// The model elements of a multi-valued value, composition or + /// reference, in order — targets outside the model are *omitted* + /// (match [`Self::References`] to see them). Empty for anything else. + pub fn elements(&self) -> Vec { + match self { + Self::Elements(es) => es.clone(), + Self::References(rs) => rs.iter().filter_map(Reference::element).collect(), + _ => Vec::new(), + } + } +} + +/// The tri-state answer of [`ResolvedModel::derived`]. +#[derive(Clone, Debug, PartialEq, Eq)] +pub enum Derived { + /// The metaclass does not declare the property (or it is owned, not + /// derived — read it with the property accessors instead). + NotDeclared, + /// Declared, but this toolkit does not compute it yet; the full form + /// emits the catalog's type-correct empty default for it. + NotComputed, + Value(DerivedValue), +} + +/// What [`ResolvedModel::derived`] can answer for one (metaclass, name), +/// decided statically. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Derives { + /// The metaclass does not declare the name as a derived property. + NotDeclared, + /// Declared and not computed. + NotComputed, + /// Computed under the passthrough level: the specification reads an + /// inheritance or import closure, and the value covers the owned side + /// only until the closure policy is on. + Passthrough, + /// Computed as specified. + Exact, +} + +/// The names this module computes exactly (sorted; binary-searched). +const EXACT: &[&str] = &[ + "annotatedElement", + "annotatingElement", + "annotation", + "assertedConstraint", + "association", + "assumedConstraint", + "bodyAction", + "bound", + "chainingFeature", + "conjugatedPortDefinition", + "crossFeature", + "crossingFeature", + "definition", + "differencingType", + "doAction", + "documentedElement", + "effectAction", + "elseAction", + "endOwningType", + "entryAction", + "enumeratedValue", + "eventOccurrence", + "exhibitedState", + "exitAction", + "featureChained", + "featureTarget", + "featureWithValue", + "filterCondition", + "function", + "guardExpression", + "ifArgument", + "importOwningNamespace", + "importedElement", + "includedUseCase", + "individualDefinition", + "instantiatedType", + "interaction", + "intersectingType", + "isConjugated", + "isLibraryElement", + "isReference", + "loopVariable", + "lowerBound", + "memberElementId", + "membershipOwningNamespace", + "metaclass", + "multiplicity", + "name", + "originalPortDefinition", + "ownedAnnotatingElement", + "ownedAnnotatingRelationship", + "ownedAnnotation", + "ownedConjugator", + "ownedCrossSubsetting", + "ownedElement", + "ownedEndFeature", + "ownedFeature", + "ownedFeatureInverting", + "ownedFeatureMembership", + "ownedImport", + "ownedMember", + "ownedMemberElement", + "ownedMemberElementId", + "ownedMemberFeature", + "ownedMemberName", + "ownedMemberShortName", + "ownedMembership", + "ownedPortConjugator", + "ownedReferenceSubsetting", + "ownedSpecialization", + "ownedTypeFeaturing", + "owner", + "owningAnnotatedElement", + "owningAnnotatingElement", + "owningAnnotatingRelationship", + "owningClassifier", + "owningDefinition", + "owningFeature", + "owningFeatureMembership", + "owningFeatureOfType", + "owningMembership", + "owningNamespace", + "owningType", + "owningUsage", + "payloadArgument", + "payloadFeature", + "payloadType", + "performedAction", + "predicate", + "qualifiedName", + "receiverArgument", + "referencedConcern", + "referencedConstraint", + "referencedElement", + "referencedRendering", + "referencingFeature", + "referent", + "relatedElement", + "representedElement", + "requiredConstraint", + "satisfiedRequirement", + "satisfiedViewpoint", + "senderArgument", + "seqArgument", + "shortName", + "source", + "succession", + "target", + "targetArgument", + "terminatedOccurrenceArgument", + "text", + "thenAction", + "triggerAction", + "type", + "typeDifferenced", + "typeIntersected", + "typeUnioned", + "unioningType", + "untilArgument", + "upperBound", + "useCaseIncluded", + "valueExpression", + "variant", + "viewCondition", + "whileArgument", +]; + +/// The names this module computes at the passthrough level (owned side +/// only; their specification unions the inheritance/import closures). +/// Sorted; binary-searched. +const PASSTHROUGH: &[&str] = &[ + "actorParameter", + "argument", + "associationEnd", + "connectionEnd", + "connectorEnd", + "defaultFeaturingType", + "directedFeature", + "endFeature", + "exposedElement", + "expression", + "feature", + "featureMembership", + "featuringType", + "framedConcern", + "importedMembership", + "inheritedFeature", + "inheritedMembership", + "input", + "interfaceEnd", + "isModelLevelEvaluable", + "member", + "membership", + "objectiveRequirement", + "output", + "parameter", + "payloadParameter", + "relatedFeature", + "relatedType", + "result", + "resultExpression", + "satisfyingFeature", + "sourceFeature", + "sourceOutputFeature", + "sourceType", + "stakeholderParameter", + "subjectParameter", + "targetFeature", + "targetInputFeature", + "targetType", + "verifiedRequirement", + "viewRendering", + "viewpointStakeholder", +]; + +/// Hand-written names that are a *different* property on another +/// metaclass carrying the same name (`Connector::targetFeature` is the +/// related features past the source; `FeatureChainExpression::targetFeature` +/// the accessed feature; `RequirementVerificationMembership::verifiedRequirement` +/// one referenced requirement, a verification case's the list its +/// objective verifies): computed, with the listed fidelity, only where +/// the metaclass conforms to a listed kind. +const HAND_WRITTEN_ON: &[(&str, &str, Derives)] = &[ + ("targetFeature", "Connector", Derives::Passthrough), + ("targetFeature", "FeatureChainExpression", Derives::Exact), + ( + "verifiedRequirement", + "RequirementVerificationMembership", + Derives::Exact, + ), + ( + "verifiedRequirement", + "VerificationCaseUsage", + Derives::Passthrough, + ), + ( + "verifiedRequirement", + "VerificationCaseDefinition", + Derives::Passthrough, + ), +]; + +/// Membership-side single references that redefine the owned member +/// under the membership kind's own name (`ownedMemberParameter`, +/// `ownedSubjectParameter`, `ownedConstraint` on a +/// RequirementConstraintMembership, `action` on a +/// StateSubactionMembership, …): exact wherever the element conforms to +/// the listed membership kind, whatever the same name means elsewhere (a +/// composition on the owner, say). +const MEMBER_SIDE: &[(&str, &str)] = &[ + ("action", "StateSubactionMembership"), + ("condition", "ElementFilterMembership"), + ("ownedActorParameter", "ActorMembership"), + ("ownedConcern", "FramedConcernMembership"), + ("ownedConstraint", "RequirementConstraintMembership"), + ("ownedMemberParameter", "ParameterMembership"), + ("ownedObjectiveRequirement", "ObjectiveMembership"), + ("ownedRendering", "ViewRenderingMembership"), + ("ownedRequirement", "RequirementVerificationMembership"), + ("ownedResultExpression", "ResultExpressionMembership"), + ("ownedStakeholderParameter", "StakeholderMembership"), + ("ownedSubjectParameter", "SubjectMembership"), + ("ownedVariantUsage", "VariantMembership"), + ("transitionFeature", "TransitionFeatureMembership"), + ("value", "FeatureValue"), +]; + +/// The membership kind under which `name` is a member-side reference on +/// `metaclass`, if any. +fn member_side(metaclass: &str, name: &str) -> Option<&'static str> { + MEMBER_SIDE + .iter() + .find(|(n, kind)| *n == name && conforms(metaclass, kind)) + .map(|(_, kind)| *kind) +} + +/// Whether the concrete metaclass `metaclass` conforms to (is, or +/// specializes) the abstract-syntax metaclass `general` (`"PartUsage"` +/// conforms to `"Usage"`, `"Feature"`, `"Element"`). The generator hook's +/// companion: which declaring metaclass a catalog row's metaclass falls +/// under. +pub fn metaclass_conforms(metaclass: &str, general: &str) -> bool { + conforms(metaclass, general) +} + +/// The shape the interchange schema gives a property (the catalog's +/// default when a value is absent). +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum PropertyShape { + /// A list (`[]` when empty). + Array, + /// A boolean (`false` by default). + Boolean, + /// A nullable single value (`null` by default). + Nullable, + /// A string or number the emitter computes. + Scalar, + /// An enumeration literal the emitter computes. + Enumeration, + /// A required single reference (the emitter's self-reference + /// placeholder when it has no value). + RequiredReference, +} + +/// One row of the property catalog: a concrete metaclass, a property the +/// schema declares on it, and the property's shape. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct CatalogEntry { + pub metaclass: &'static str, + pub property: &'static str, + pub shape: PropertyShape, + /// Whether the abstract syntax owns the property there (the compact + /// form may spell it) or derives it (`derived` answers it, at the + /// fidelity [`derives`] reports). + pub owned: bool, +} + +/// Every (concrete metaclass, property) pair the interchange schema +/// declares, metaclasses and properties sorted — the generator hook: an +/// SDK generator walks this with [`derives`]/[`derives_under`] for the +/// fidelity of each derived row and the value shape of +/// [`DerivedValue`] for its type. +pub fn property_catalog() -> impl Iterator { + use crate::derived_names::ABSTRACT_METACLASSES; + crate::schema_props::METACLASS_PROPS + .iter() + // The schema carries a few abstract metaclasses; no element has + // one. + .filter(|(metaclass, _)| ABSTRACT_METACLASSES.binary_search(metaclass).is_err()) + .flat_map(|(metaclass, props)| { + props.iter().map(move |(property, code)| CatalogEntry { + metaclass, + property, + // The catalog spells booleans as nullable (`N`); the `B` + // and `E` codes are defined but unused by this schema. + shape: match code { + b'A' => PropertyShape::Array, + b'B' => PropertyShape::Boolean, + b'N' => PropertyShape::Nullable, + b'S' => PropertyShape::Scalar, + b'E' => PropertyShape::Enumeration, + b'R' => PropertyShape::RequiredReference, + other => unreachable!("catalog shape code {other}"), + }, + owned: !declared(metaclass, property), + }) + }) +} + +/// The deterministic dangling id of an unresolved reference spelling — +/// what the full form spells for a reference that never resolved +/// (`Reference::Unresolved` in the read API), so a consumer can +/// correlate the two. +pub fn dangling_id(spelling: &str) -> String { + Uuid::new_v5( + &Uuid::NAMESPACE_OID, + format!("unresolved:{spelling}").as_bytes(), + ) + .to_string() +} + +/// Owned properties a generated composition may build on: not derived, +/// so never answered by [`ResolvedModel::derived`] themselves, but exact +/// bases (`ownedDisjoining = ownedRelationship->selectByKind(Disjoining)`). +const OWNED_BASES: &[&str] = &["ownedRelationship"]; + +fn is_exact(name: &str) -> bool { + EXACT.binary_search(&name).is_ok() +} + +fn is_passthrough(name: &str) -> bool { + PASSTHROUGH.binary_search(&name).is_ok() +} + +fn is_hand_written(name: &str) -> bool { + is_exact(name) || is_passthrough(name) +} + +/// The generated kind-filtered composition for `name`, if any. +fn composition(name: &str) -> Option<(&'static str, &'static str, bool)> { + COMPOSITIONS + .binary_search_by(|(n, _, _, _)| n.cmp(&name)) + .ok() + .map(|i| (COMPOSITIONS[i].1, COMPOSITIONS[i].2, COMPOSITIONS[i].3)) +} + +/// Whether `metaclass` carries the property `name` at all (owned or +/// derived), per the schema catalog. +fn carries(metaclass: &str, name: &str) -> bool { + use crate::schema_props::METACLASS_PROPS; + // The catalog and each property list are sorted (pinned by + // `tests::catalog_is_sorted`), so this is a few string compares per + // call — it sits on the SDK's per-property hot path. + METACLASS_PROPS + .binary_search_by(|(m, _)| m.cmp(&metaclass)) + .ok() + .is_some_and(|i| { + METACLASS_PROPS[i] + .1 + .binary_search_by(|(p, _)| p.cmp(&name)) + .is_ok() + }) +} + +/// Whether `name` is a *derived* property of `metaclass` (a concrete +/// metaclass name), per the schema catalog and the XMI's derived-name +/// table. +fn declared(metaclass: &str, name: &str) -> bool { + use crate::derived_names::{DERIVED_NAMES, OWNED_ON}; + carries(metaclass, name) + && DERIVED_NAMES.binary_search(&name).is_ok() + && !OWNED_ON + .iter() + .any(|(n, classes)| *n == name && classes.contains(&metaclass)) +} + +/// The fidelity of a declared `name` on `metaclass`: hand-written names +/// by their list; a composition by its base's fidelity *on the same +/// metaclass* — the same name is a different property on a metaclass +/// that does not carry the base (`action` on StateSubactionMembership is +/// a single required reference, not `usage->selectByKind(ActionUsage)`), +/// and is not computed there. A composition over a passthrough base is +/// passthrough; over an owned base ([`OWNED_BASES`]) exact. +fn fidelity(metaclass: &str, name: &str, depth: usize) -> Derives { + if member_side(metaclass, name).is_some() { + return Derives::Exact; + } + let gated: Vec<&(&str, &str, Derives)> = HAND_WRITTEN_ON + .iter() + .filter(|(n, _, _)| *n == name) + .collect(); + if !gated.is_empty() { + return gated + .iter() + .find(|(_, kind, _)| conforms(metaclass, kind)) + .map_or(Derives::NotComputed, |(_, _, f)| *f); + } + if is_exact(name) { + Derives::Exact + } else if is_passthrough(name) { + Derives::Passthrough + } else if let Some((base, _, _)) = composition(name) { + if depth > 8 { + return Derives::NotComputed; + } + if OWNED_BASES.contains(&base) { + return if carries(metaclass, base) { + Derives::Exact + } else { + Derives::NotComputed + }; + } + if !declared(metaclass, base) { + return Derives::NotComputed; + } + match fidelity(metaclass, base, depth + 1) { + Derives::NotDeclared | Derives::NotComputed => Derives::NotComputed, + f => f, + } + } else { + Derives::NotComputed + } +} + +/// Whether the abstract syntax declares `name` on `metaclass` as an +/// *owned* (non-derived) property — one the compact form may spell and +/// the property accessors read, which [`ResolvedModel::derived`] never +/// answers (`declaredName`, `isAbstract`, a relationship's `source` and +/// `target`, …). `metaclass` is a concrete metaclass name. +pub fn is_owned_property(metaclass: &str, name: &str) -> bool { + carries(metaclass, name) && !declared(metaclass, name) +} + +/// What [`ResolvedModel::derived`] answers for `name` on an element of +/// `metaclass`, decided without a model, at the passthrough level. +/// `metaclass` is a concrete abstract-syntax metaclass name +/// (`"PartUsage"`). See [`derives_under`] for the closure policy. +pub fn derives(metaclass: &str, name: &str) -> Derives { + derives_under(metaclass, name, super::ClosurePolicy::Passthrough) +} + +/// Passthrough names whose approximation is not the closure and that +/// no policy makes exact: `isModelLevelEvaluable` (the library-function +/// over-approximation), `exposedElement` (the exposed namespaces' own +/// members, not their imported and inherited memberships) and +/// `defaultFeaturingType` (the omitted `specializes` clauses). +const APPROXIMATE: &[&str] = &[ + "defaultFeaturingType", + "exposedElement", + "isModelLevelEvaluable", +]; + +/// [`derives`] under a closure policy: with the closures in force *and +/// the implied heritage included* ([`super::ClosurePolicy::Closure`] with +/// `include_implied: true` — the specification's `inheritedMemberships` +/// does not exclude the implied heritage) every passthrough name but +/// `defaultFeaturingType`, `exposedElement` and `isModelLevelEvaluable` +/// is computed as specified and answers +/// `Exact`; the written-heritage tier (`include_implied: false`) is a +/// documented deviation and stays `Passthrough`. +pub fn derives_under(metaclass: &str, name: &str, policy: super::ClosurePolicy) -> Derives { + if !declared(metaclass, name) { + return Derives::NotDeclared; + } + match fidelity(metaclass, name, 0) { + Derives::Passthrough + if policy.include_implied() == Some(true) && !APPROXIMATE.contains(&name) => + { + Derives::Exact + } + f => f, + } +} + +/// Every derived name this module can answer on some metaclass: the +/// hand-written families and every generated composition (each name +/// once). Whether a given metaclass gets a value is [`derives`]'s call. +pub fn computed_names() -> impl Iterator { + EXACT + .iter() + .chain(PASSTHROUGH) + .copied() + .chain( + COMPOSITIONS + .iter() + .map(|(n, _, _, _)| *n) + .filter(|n| !is_hand_written(n)), + ) + .chain( + MEMBER_SIDE + .iter() + .map(|(n, _)| *n) + .filter(|n| !is_hand_written(n) && composition(n).is_none()), + ) +} + +impl ResolvedModel { + /// The derived property `name` of `e`, by its specification name + /// (`"ownedFeature"`, `"owningNamespace"`, …). See [`Derived`] for the + /// three answers and [`derives`] for the static fidelity of a name. + pub fn derived(&mut self, e: ElementRef, name: &str) -> Derived { + let ty = self.b.elements[e.0].ty; + match self.derives_memo(ty, name) { + Derives::NotDeclared => return Derived::NotDeclared, + Derives::NotComputed => return Derived::NotComputed, + Derives::Passthrough | Derives::Exact => {} + } + self.derived_computable(e, name) + } + + /// [`derives`] for `ty`, memoized per metaclass: the static answer + /// for every derived name of the catalog is computed once per + /// metaclass the model exhibits, so a projection that asks for every + /// name on every element (the full-form emitter) pays the catalog + /// search once per metaclass rather than once per element — on a + /// large model that search was the larger part of the emission. + fn derives_memo(&mut self, ty: &'static str, name: &str) -> Derives { + use crate::derived_names::DERIVED_NAMES; + // A name outside the derived catalog is declared nowhere. + let Ok(idx) = DERIVED_NAMES.binary_search(&name) else { + return Derives::NotDeclared; + }; + self.derives_memo + .entry(ty) + .or_insert_with(|| DERIVED_NAMES.iter().map(|n| derives(ty, n)).collect())[idx] + } + + /// The names [`Self::derived`] answers with a value on an element of + /// `metaclass`: [`computed_names`] filtered by [`derives`] (a + /// passthrough or exact answer), in the order `computed_names` yields + /// them, memoized per metaclass; empty for a metaclass outside the + /// schema catalog. The per-metaclass companion of `computed_names` for + /// a caller that projects every computed name of an element. + pub fn computable_names(&mut self, metaclass: &str) -> Arc<[&'static str]> { + use crate::schema_props::METACLASS_PROPS; + // The memo is keyed by the catalog's own spelling of the metaclass. + let Ok(i) = METACLASS_PROPS.binary_search_by(|(m, _)| m.cmp(&metaclass)) else { + return Arc::from(Vec::new()); + }; + let ty: &'static str = METACLASS_PROPS[i].0; + if let Some(plan) = self.plan_memo.get(ty) { + return Arc::clone(plan); + } + let plan: Arc<[&'static str]> = computed_names() + .filter(|n| { + matches!( + self.derives_memo(ty, n), + Derives::Passthrough | Derives::Exact + ) + }) + .collect(); + self.plan_memo.insert(ty, Arc::clone(&plan)); + plan + } + + /// [`Self::derived`] for a `name` the static gate has already admitted + /// on `e`'s metaclass (one of [`Self::computable_names`]); the gate is + /// not repeated. For a name the gate would refuse this may answer a + /// value the metaclass does not declare, or panic on a name with no + /// arm, so callers hold the invariant. + pub(crate) fn derived_computable(&mut self, e: ElementRef, name: &str) -> Derived { + let ty = self.b.elements[e.0].ty; + use DerivedValue as V; + // A membership-side reference: the owned member. + if member_side(ty, name).is_some() { + return Derived::Value(opt(self.d_owned_member_element(e))); + } + // A generated composition — unless the name is hand-written, which + // wins (`ownedMembership` is spelled as a composition over the + // owned relationships but computed directly): the base's list + // filtered by kind. + if let Some((base, kind, single)) = composition(name).filter(|_| !is_hand_written(name)) { + // A composition keeps its base's shape; over a reference-typed + // base, a target outside the model passes the kind filter as + // it is (see [`ResolvedModel::cast`]). + let (items, by_reference): (Vec, bool) = if OWNED_BASES.contains(&base) { + // The only owned base today is `ownedRelationship`, implied + // relationships included. + let rels = self.d_owned_relationships(e); + (rels.into_iter().map(Reference::Element).collect(), false) + } else { + match self.derived(e, base) { + Derived::Value(V::Elements(items)) => { + (items.into_iter().map(Reference::Element).collect(), false) + } + Derived::Value(V::Element(x)) => (vec![Reference::Element(x)], false), + Derived::Value(V::References(items)) => (items, true), + Derived::Value(V::Reference(r)) => (vec![r], true), + Derived::Value(V::Null) => (Vec::new(), by_reference_base(base)), + _ => return Derived::NotComputed, + } + }; + let mut kept = items.into_iter().filter_map(|r| self.cast(r, kind)); + return Derived::Value(match (single, by_reference) { + (true, false) => opt(kept.next().and_then(|r| r.element())), + (true, true) => opt_ref(kept.next()), + (false, false) => V::Elements(kept.filter_map(|r| r.element()).collect()), + (false, true) => V::References(kept.collect()), + }); + } + let v = match name { + "owner" => opt(self.d_owner(e)), + "owningMembership" => opt(self.d_owning_membership(e)), + "owningNamespace" => opt(self.d_owning_namespace(e)), + "ownedElement" => V::Elements(self.d_owned_elements(e)), + "isLibraryElement" => V::Bool(self.d_is_library_element(e)), + "ownedMembership" => V::Elements(self.d_owned_memberships(e)), + "membership" => V::Elements(self.d_memberships(e)), + "ownedMember" => V::Elements(self.d_owned_members(e)), + "member" => V::References(self.d_members(e)), + "ownedImport" => V::Elements(self.d_owned_imports(e)), + "ownedFeatureMembership" => V::Elements(self.d_owned_feature_memberships(e)), + "featureMembership" => V::Elements(self.d_feature_memberships(e)), + "ownedFeature" => V::Elements(self.d_owned_features(e)), + "feature" => V::Elements(self.d_features(e)), + // ---- the closures (`json/closures.rs`) ---- + "inheritedMembership" => V::Elements(self.d_inherited_memberships(e)), + "inheritedFeature" => V::Elements(self.d_inherited_features(e)), + "importedMembership" => V::Elements(self.imported_memberships(e)), + "featuringType" => V::Elements(self.d_featuring_types(e)), + "owningType" => opt(self.d_owning_type_any(e)), + "owningClassifier" => opt(self + .d_relationship_owning_type(e) + .filter(|&o| self.is_kind(o, "Classifier"))), + "owningFeature" => opt(self + .d_relationship_owning_type(e) + .filter(|&o| self.is_kind(o, "Feature"))), + "owningFeatureOfType" => opt(self + .d_relationship_owning_type(e) + .filter(|&o| self.is_kind(o, "Feature"))), + "owningFeatureMembership" => opt(self.d_owning_feature_membership(e)), + "endOwningType" => opt(self.d_end_owning_type(e)), + "owningDefinition" => opt(self + .d_owning_type(e) + .filter(|&o| self.is_kind(o, "Definition"))), + "owningUsage" => opt(self.d_owning_type(e).filter(|&o| self.is_kind(o, "Usage"))), + "membershipOwningNamespace" | "importOwningNamespace" => { + opt(self.d_owning_related_element(e)) + } + "ownedMemberElement" | "ownedMemberFeature" => opt(self.d_owned_member_element(e)), + "importedElement" => opt_ref(self.d_imported_element(e)), + "isReference" => self.d_is_reference(e).map_or(V::Null, V::Bool), + "name" => self.element_effective_name(e).map_or(V::Null, V::Str), + "shortName" => self.element_short_name(e).map_or(V::Null, V::Str), + "qualifiedName" => self.element_qualified_name(e).map_or(V::Null, V::Str), + "text" => V::Strings(self.d_text(e)), + "multiplicity" => opt(self.d_multiplicity(e)), + "ownedConjugator" => opt(self + .owned_relationships_of_kind(e, "Conjugation") + .into_iter() + .next()), + "annotation" => V::Elements(self.d_annotations(e)), + "ownedAnnotatingRelationship" => V::Elements(self.d_owned_annotations(e, false)), + "ownedAnnotation" => V::Elements(self.d_owned_annotations(e, true)), + // `annotatedElement` is owned on Annotation itself; derived + // only on the annotating element. + "annotatedElement" => V::References(self.d_annotating_targets(e)), + "documentedElement" | "representedElement" => { + opt_ref(self.d_annotating_targets(e).into_iter().next()) + } + "annotatingElement" => opt(self.d_annotating_element(e)), + "ownedAnnotatingElement" => opt(self.d_owned_annotating_element(e)), + "owningAnnotatingElement" => opt(self + .d_owning_related_element(e) + .filter(|_| self.d_owned_annotating_element(e).is_none()) + .filter(|&o| self.is_kind(o, "AnnotatingElement"))), + // `owningAnnotatedElement subsets annotatedElement`: the owner + // only when it *is* the annotated element. + "owningAnnotatedElement" => { + let owner = self.d_owning_related_element(e); + opt(owner.filter(|&o| self.d_annotated_element(e) == Some(Reference::Element(o)))) + } + "owningAnnotatingRelationship" => opt(self.b.elements[e.0] + .owning_relationship + .map(ElementRef) + .filter(|&r| self.b.elements[r.0].ty == "Annotation")), + "type" => V::References(self.d_types(e)), + "definition" => V::References(self.d_types_of_kind(e, "Classifier")), + // ---- states, transitions, actions (`json/behavior.rs`) ---- + "entryAction" => opt(self.d_state_subaction(e, "entry")), + "doAction" => opt(self.d_state_subaction(e, "do")), + "exitAction" => opt(self.d_state_subaction(e, "exit")), + "triggerAction" => { + V::Elements(self.d_transition_features(e, "trigger", "AcceptActionUsage")) + } + "guardExpression" => V::Elements(self.d_transition_features(e, "guard", "Expression")), + "effectAction" => V::Elements(self.d_transition_features(e, "effect", "ActionUsage")), + "succession" => opt(self.d_succession(e)), + "source" => opt_ref(self.d_transition_source(e)), + "target" => opt_ref(self.d_transition_target(e)), + "loopVariable" => opt(self.d_loop_variable(e)), + "ifArgument" | "whileArgument" => opt(self.d_parameter_as(e, 1, "Expression")), + "thenAction" | "bodyAction" => opt(self.d_parameter_as(e, 2, "ActionUsage")), + "elseAction" => opt(self.d_parameter_as(e, 3, "ActionUsage")), + "untilArgument" => opt(self.d_parameter_as(e, 3, "Expression")), + "payloadArgument" if ty == "AcceptActionUsage" => { + opt(self.d_accept_payload_argument(e)) + } + "seqArgument" + | "targetArgument" + | "terminatedOccurrenceArgument" + | "payloadArgument" => opt(self.d_argument(e, 1)), + "valueExpression" | "senderArgument" => opt(self.d_argument(e, 2)), + "receiverArgument" => { + let position = if ty == "SendActionUsage" { 3 } else { 2 }; + opt(self.d_argument(e, position)) + } + "payloadParameter" => { + let features = self.d_features(e); + opt(self.d_directed(features, None).into_iter().next()) + } + "eventOccurrence" => opt_ref(self.d_referenced_or_self(e, "OccurrenceUsage")), + "performedAction" => opt_ref(self.d_referenced_or_self(e, "ActionUsage")), + "exhibitedState" => opt_ref(self.d_referenced_or_self(e, "StateUsage")), + "useCaseIncluded" => opt_ref(self.d_referenced_or_self(e, "UseCaseUsage")), + "assertedConstraint" => opt_ref(self.d_referenced_or_self(e, "ConstraintUsage")), + "satisfiedRequirement" => opt_ref(self.d_referenced_or_self(e, "RequirementUsage")), + "includedUseCase" => V::References(self.d_included_use_cases(e)), + // ---- expressions and functions ---- + "result" => opt(self.d_result(e)), + "function" => opt_ref(self.d_types_of_kind(e, "Function").into_iter().next()), + "predicate" => opt_ref(self.d_types_of_kind(e, "Predicate").into_iter().next()), + "metaclass" => opt_ref(self.d_types_of_kind(e, "Metaclass").into_iter().next()), + "association" => V::References(self.d_types_of_kind(e, "Association")), + "interaction" => V::References(self.d_types_of_kind(e, "Interaction")), + "payloadFeature" => opt(self.d_payload_feature(e)), + "payloadType" => V::References(self.d_payload_type(e)), + "individualDefinition" => opt_ref(self.d_individual_definition(e)), + "instantiatedType" => opt_ref(self.d_instantiated_type(e)), + "argument" => V::References(self.d_arguments(e)), + "referent" if ty == "AssignmentActionUsage" => { + opt_ref(self.d_unowned_member(e, "Feature")) + } + "referent" => opt_ref(self.d_referent(e)), + "targetFeature" if ty == "FeatureChainExpression" => opt_ref(self.d_referent(e)), + "referencedElement" => opt_ref(self.d_unowned_member(e, "Element")), + "expression" => V::Elements(self.d_function_expressions(e)), + "featureWithValue" => opt(self.d_owning_related_element(e)), + "bound" => V::Elements(self.d_bounds(e)), + "lowerBound" => { + let bounds = self.d_bounds(e); + opt((bounds.len() >= 2).then(|| bounds[0])) + } + "upperBound" => opt(self.d_bounds(e).into_iter().last()), + "filterCondition" | "viewCondition" => V::Elements(self.d_filter_conditions(e)), + "memberElementId" | "ownedMemberElementId" => { + self.d_member_element_id(e).map_or(V::Null, V::Str) + } + "ownedMemberName" => self.d_owned_member_name(e, false).map_or(V::Null, V::Str), + "ownedMemberShortName" => self.d_owned_member_name(e, true).map_or(V::Null, V::Str), + "enumeratedValue" => V::Elements(self.d_variants(e)), + "isConjugated" => V::Bool( + !self + .owned_relationships_of_kind(e, "Conjugation") + .is_empty(), + ), + "conjugatedPortDefinition" => opt(self.d_conjugated_port_definition(e)), + "ownedPortConjugator" => opt(self + .owned_relationships_of_kind(e, "PortConjugation") + .into_iter() + .next()), + "parameter" => { + let features = self.d_features(e); + V::Elements(self.d_directed(features, None)) + } + "associationEnd" | "connectionEnd" | "interfaceEnd" => { + let features = self.d_features(e); + V::Elements(self.d_ends(features)) + } + // ---- requirements, cases, views (`json/cases.rs`) ---- + "subjectParameter" => opt(self + .d_members_via(e, "SubjectMembership") + .into_iter() + .next()), + "actorParameter" => V::Elements(self.d_members_via(e, "ActorMembership")), + "stakeholderParameter" => V::Elements(self.d_members_via(e, "StakeholderMembership")), + "objectiveRequirement" => opt(self + .d_members_via(e, "ObjectiveMembership") + .into_iter() + .next()), + "framedConcern" => V::Elements(self.d_members_via(e, "FramedConcernMembership")), + "resultExpression" => opt(self + .d_members_via(e, "ResultExpressionMembership") + .into_iter() + .next()), + "requiredConstraint" => V::Elements(self.d_requirement_constraints(e, "requirement")), + "assumedConstraint" => V::Elements(self.d_requirement_constraints(e, "assumption")), + "referencedConstraint" => opt_ref(self.d_referenced_member(e, "ConstraintUsage")), + "referencedConcern" => opt_ref(self.d_referenced_member(e, "ConcernUsage")), + "verifiedRequirement" if ty == "RequirementVerificationMembership" => { + opt_ref(self.d_referenced_member(e, "RequirementUsage")) + } + "verifiedRequirement" => V::References(self.d_verified_requirements(e)), + "referencedRendering" => opt_ref(self.d_referenced_member(e, "RenderingUsage")), + "viewRendering" => opt_ref(self.d_view_rendering(e)), + "satisfyingFeature" => opt_ref(self.d_satisfying_feature(e)), + "satisfiedViewpoint" => V::Elements(self.d_satisfied_viewpoints(e)), + "viewpointStakeholder" => V::Elements(self.d_viewpoint_stakeholders(e)), + "exposedElement" => V::Elements(self.d_exposed_elements(e)), + "featureTarget" => V::Reference(self.d_feature_target(e)), + "chainingFeature" => V::References(self.d_chaining_features(e)), + "crossFeature" => opt_ref(self.d_cross_feature(e)), + "featureChained" | "referencingFeature" | "crossingFeature" | "typeUnioned" + | "typeIntersected" | "typeDifferenced" => opt(self.d_owning_related_element(e)), + // ---- type operations and evaluability (`json/typeops.rs`) ---- + "unioningType" => V::References(self.d_operation_types(e, "Unioning", "unioningType")), + "intersectingType" => { + V::References(self.d_operation_types(e, "Intersecting", "intersectingType")) + } + "differencingType" => { + V::References(self.d_operation_types(e, "Differencing", "differencingType")) + } + "relatedType" => V::References(self.d_related_types(e)), + "sourceType" => opt_ref(self.d_related_types(e).into_iter().next()), + "targetType" => V::References(self.d_target_types(e)), + "defaultFeaturingType" => opt(self.d_default_featuring_type(e)), + "isModelLevelEvaluable" if self.is_kind(e, "Function") => { + V::Bool(self.function_is_model_level_evaluable(&Reference::Element(e))) + } + "isModelLevelEvaluable" => V::Bool(self.d_is_model_level_evaluable(e)), + "ownedSpecialization" => V::Elements(self.d_owned_specializations(e, "Specialization")), + "ownedFeatureInverting" => { + V::Elements(self.d_owned_specializations(e, "FeatureInverting")) + } + "ownedTypeFeaturing" => V::Elements(self.d_owned_specializations(e, "TypeFeaturing")), + "ownedReferenceSubsetting" => opt(self + .d_owned_specializations(e, "ReferenceSubsetting") + .into_iter() + .next()), + "ownedCrossSubsetting" => opt(self + .d_owned_specializations(e, "CrossSubsetting") + .into_iter() + .next()), + "relatedElement" => { + let (mut source, target) = self.relationship_ends(e); + source.extend(target); + V::References(source) + } + "ownedEndFeature" => V::Elements(self.d_ends(self.d_owned_features(e))), + "endFeature" | "connectorEnd" => { + let features = self.d_features(e); + V::Elements(self.d_ends(features)) + } + "relatedFeature" => V::References(self.d_related_features(e)), + "sourceFeature" => opt_ref(self.d_related_features(e).into_iter().next()), + "targetFeature" => { + V::References(self.d_related_features(e).into_iter().skip(1).collect()) + } + "sourceOutputFeature" => opt(self.d_flow_end_feature(e, 0)), + "targetInputFeature" => opt(self.d_flow_end_feature(e, 1)), + "directedFeature" => { + let features = self.d_features(e); + V::Elements(self.d_directed(features, None)) + } + "input" => { + let features = self.d_features(e); + V::Elements(self.d_directed(features, Some(true))) + } + "output" => { + let features = self.d_features(e); + V::Elements(self.d_directed(features, Some(false))) + } + "variant" => V::Elements(self.d_variants(e)), + "originalPortDefinition" => opt(self + .d_owning_namespace(e) + .filter(|&n| self.is_kind(n, "PortDefinition"))), + _ => unreachable!("{name} is listed as computed but has no arm"), + }; + Derived::Value(v) + } + + pub(super) fn is_kind(&self, e: ElementRef, general: &str) -> bool { + conforms(self.b.elements[e.0].ty, general) + } + + // ---- Element ---- + + /// `Element::isLibraryElement = libraryNamespace() <> null`: an + /// element is a library element when a library package owns it, + /// directly or transitively — whichever unit it was read from. + /// (Compare [`Self::is_library_element`], which answers whether the + /// element came from a library *unit*.) + fn d_is_library_element(&mut self, e: ElementRef) -> bool { + self.ensure_rel_owner(); + let mut at = Some(e.0); + let mut steps = 0usize; + while let Some(i) = at { + if self.b.elements[i].ty == "LibraryPackage" { + return true; + } + steps += 1; + if steps > 2 * self.b.elements.len() { + return false; // malformed ownership cycle + } + // Up one step, through relationship nodes: a relationship's + // carrier (`owningRelatedElement`), else its own owning + // relationship, as `Relationship::libraryNamespace()` walks. + at = self.rel_owner[i].or(self.b.elements[i].owning_relationship); + } + false + } + + /// `Element::owner = owningRelationship.owningRelatedElement`. A + /// relationship owned directly by its related element has no owning + /// relationship and therefore no owner (its carrier is + /// `owningRelatedElement`); the navigation accessor + /// [`Self::owner`] answers the carrier instead. + fn d_owner(&mut self, e: ElementRef) -> Option { + let rel = self.b.elements[e.0].owning_relationship?; + self.d_owning_related_element(ElementRef(rel)) + } + + /// `Relationship::owningRelatedElement` — the element whose + /// `ownedRelationship` list carries `rel`. + pub(super) fn d_owning_related_element(&mut self, rel: ElementRef) -> Option { + self.ensure_rel_owner(); + self.rel_owner[rel.0].map(ElementRef) + } + + /// `Element::owningMembership` — the owning relationship when it is a + /// Membership (in a well-formed model always an OwningMembership; the + /// looser filter keeps a foreign payload's shape visible). + fn d_owning_membership(&self, e: ElementRef) -> Option { + let rel = self.b.elements[e.0].owning_relationship?; + conforms(self.b.elements[rel].ty, "Membership").then_some(ElementRef(rel)) + } + + /// `Element::owningNamespace = owningMembership.membershipOwningNamespace`. + fn d_owning_namespace(&mut self, e: ElementRef) -> Option { + let m = self.d_owning_membership(e)?; + self.d_owning_related_element(m) + } + + /// `Element::ownedElement = ownedRelationship.ownedRelatedElement`, in + /// relationship order then related-element order. + fn d_owned_elements(&self, e: ElementRef) -> Vec { + self.b.elements[e.0] + .owned_relationships + .iter() + .flat_map(|&r| self.b.elements[r].children.iter().copied()) + .map(ElementRef) + .collect() + } + + // ---- Namespace ---- + + pub(super) fn owned_relationships_of_kind( + &self, + e: ElementRef, + general: &str, + ) -> Vec { + self.b.elements[e.0] + .owned_relationships + .iter() + .copied() + .filter(|&r| conforms(self.b.elements[r].ty, general)) + .map(ElementRef) + .collect() + } + + /// `Namespace::ownedMembership = ownedRelationship->selectByKind(Membership)`. + pub(super) fn d_owned_memberships(&self, e: ElementRef) -> Vec { + self.owned_relationships_of_kind(e, "Membership") + } + + /// `Namespace::ownedMember = ownedMembership->selectByKind(OwningMembership).ownedMemberElement`. + pub(super) fn d_owned_members(&self, e: ElementRef) -> Vec { + self.d_owned_memberships(e) + .into_iter() + .filter(|&m| conforms(self.b.elements[m.0].ty, "OwningMembership")) + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + /// `Namespace::member = membership.memberElement` at the passthrough + /// level: the owned memberships' members — owned member elements, and + /// the targets of alias and other non-owning memberships, outside the + /// model included. + fn d_members(&mut self, e: ElementRef) -> Vec { + let memberships = self.d_memberships(e); + self.ensure_by_id(); + memberships + .into_iter() + .filter_map(|m| self.d_member_element(m)) + .collect() + } + + /// `Membership::memberElement`: the owned member, else the spelled + /// target (a reference, resolved or not). + pub(super) fn d_member_element(&mut self, m: ElementRef) -> Option { + if let Some(k) = self.d_owned_member_element(m) { + return Some(Reference::Element(k)); + } + let atom = self.b.elements[m.0].props.get("memberElement")?.clone(); + self.reference_of(&atom) + } + + /// A reference-typed property value as a [`Reference`]: an id the + /// model holds is its element, another id is external, and an + /// unresolved `@ref` spelling is unresolved — unless the spelling is + /// itself an id (the lift spells a target it cannot name that way), + /// which is looked up like any id. + pub(super) fn reference_of(&self, atom: &Atom) -> Option { + let by_id = |id: Uuid| match self.by_id.get(&id) { + Some(&i) => Reference::Element(ElementRef(i)), + None => Reference::External(id), + }; + if let Some(id) = atom.as_reference() { + return Some(by_id(id)); + } + let spelling = atom.get("@ref")?.as_str()?; + Some(match Uuid::parse_str(spelling.trim_matches('\'')) { + Ok(id) => by_id(id), + Err(_) => Reference::Unresolved(spelling.to_string()), + }) + } + + /// `Namespace::ownedImport = ownedRelationship->selectByKind(Import)`. + fn d_owned_imports(&self, e: ElementRef) -> Vec { + self.owned_relationships_of_kind(e, "Import") + } + + // ---- Type ---- + + /// `Type::ownedFeatureMembership = ownedRelationship->selectByKind(FeatureMembership)`. + pub(super) fn d_owned_feature_memberships(&self, e: ElementRef) -> Vec { + self.owned_relationships_of_kind(e, "FeatureMembership") + } + + /// `Type::ownedFeature = ownedFeatureMembership.ownedMemberFeature`. + pub(super) fn d_owned_features(&self, e: ElementRef) -> Vec { + self.d_owned_feature_memberships(e) + .into_iter() + .filter_map(|m| self.d_owned_member_element(m)) + .collect() + } + + // ---- Feature / Usage ---- + + /// `owningType` for whichever kind of element declares it: a + /// FeatureMembership's `membershipOwningNamespace`; a Feature's + /// `owningFeatureMembership.owningType`; the specific side of a + /// Specialization, Conjugation or Disjoining that owns it. + pub(super) fn d_owning_type_any(&mut self, e: ElementRef) -> Option { + let ty = self.b.elements[e.0].ty; + if conforms(ty, "FeatureMembership") { + self.d_owning_related_element(e) + } else if conforms(ty, "Feature") { + self.d_owning_type(e) + } else { + self.d_relationship_owning_type(e) + } + } + + /// `Type::ownedSpecialization` and its kin (`ownedFeatureInverting`, + /// `ownedTypeFeaturing`, the single-valued `ownedReferenceSubsetting` + /// / `ownedCrossSubsetting`): the owned relationships of `kind`, + /// implied ones included, for which the owner is the source end + /// (every one written on its specific side is; a foreign payload may + /// spell another source). + pub(super) fn d_owned_specializations(&mut self, e: ElementRef, kind: &str) -> Vec { + let rels: Vec = self + .d_owned_relationships(e) + .into_iter() + .filter(|&r| self.is_kind(r, kind)) + .collect(); + let mut out = Vec::with_capacity(rels.len()); + for r in rels { + if self.d_relationship_source(r).is_none_or(|s| s == e) { + out.push(r); + } + } + out + } + + /// `Relationship::source` and `target` — the ends each relationship + /// kind spells (a membership's owner and member, an import's owner + /// and imported namespace or membership, a specialization's specific + /// and general, an annotation's annotating and annotated elements, a + /// dependency's clients and suppliers, …), a relationship written on + /// its source side taking the owner as its source. Both are *owned* + /// properties of Relationship in the abstract syntax (derived only on + /// `TransitionUsage`), so [`Self::derived`] does not answer them; + /// this is their navigation accessor, and the derived + /// `relatedElement` is their union. A target outside the model is + /// reported as such; empty for an element that is no relationship. + pub fn relationship_ends(&mut self, e: ElementRef) -> (Vec, Vec) { + self.ensure_by_id(); + let t = self.b.elements[e.0].ty; + let owner = self.d_owning_related_element(e).map(Reference::Element); + let get = |this: &Self, key: &str| -> Option { + this.b.elements[e.0] + .props + .get(key) + .and_then(|atom| this.reference_of(atom)) + }; + let first = |this: &Self, keys: &[&str]| keys.iter().find_map(|k| get(this, k)); + let owned_first = |this: &Self| { + this.b.elements[e.0] + .children + .first() + .map(|&k| Reference::Element(ElementRef(k))) + }; + let list = |this: &Self, key: &str| -> Vec { + this.b.elements[e.0] + .props + .get(key) + .and_then(|v| v.as_array()) + .map(|a| a.iter().filter_map(|x| this.reference_of(x)).collect()) + .unwrap_or_default() + }; + let (source, target): (Option, Option) = if conforms(t, "Membership") + { + ( + owner.clone(), + get(self, "memberElement").or_else(|| owned_first(self)), + ) + } else if conforms(t, "Import") { + ( + owner.clone(), + first(self, &["importedNamespace", "importedMembership"]), + ) + } else { + match t { + "Subclassification" | "Specialization" => ( + first(self, &["subclassifier", "specific"]), + first(self, &["superclassifier", "general"]), + ), + "FeatureTyping" | "ConjugatedPortTyping" => { + (get(self, "typedFeature"), get(self, "type")) + } + "Subsetting" | "Redefinition" | "ReferenceSubsetting" | "CrossSubsetting" => ( + first( + self, + &[ + "subsettingFeature", + "redefiningFeature", + "referencingFeature", + "crossingFeature", + ], + ) + .or_else(|| owner.clone()), + first( + self, + &[ + "subsettedFeature", + "redefinedFeature", + "referencedFeature", + "crossedFeature", + ], + ), + ), + "Dependency" => return (list(self, "client"), list(self, "supplier")), + "Annotation" => ( + self.d_annotating_element(e).map(Reference::Element), + self.d_annotated_element(e), + ), + "Conjugation" | "PortConjugation" => ( + get(self, "conjugatedType").or_else(|| owner.clone()), + get(self, "originalType"), + ), + "Disjoining" => ( + get(self, "typeDisjoined").or_else(|| owner.clone()), + get(self, "disjoiningType"), + ), + "FeatureInverting" => ( + get(self, "featureInverted").or_else(|| owner.clone()), + get(self, "invertingFeature"), + ), + "TypeFeaturing" => ( + get(self, "featureOfType").or_else(|| owner.clone()), + get(self, "featuringType"), + ), + "Unioning" | "Intersecting" | "Differencing" | "FeatureChaining" + | "FeatureValue" => ( + owner.clone(), + first( + self, + &[ + "unioningType", + "intersectingType", + "differencingType", + "chainingFeature", + ], + ) + .or_else(|| owned_first(self)), + ), + _ => (None, None), + } + }; + (source.into_iter().collect(), target.into_iter().collect()) + } + + /// The Type that owns a Specialization, Conjugation, Disjoining, + /// FeatureInverting or TypeFeaturing *and* is its source end — a + /// relationship written on its specific side (`part def B :> A`) + /// rather than standalone (`specialization Sub subclassifier B …`, + /// which rides a membership and has no owning related element). + fn d_relationship_owning_type(&mut self, e: ElementRef) -> Option { + if self.b.elements[e.0].owning_relationship.is_some() { + return None; + } + let owner = self.d_owning_related_element(e)?; + if !self.is_kind(owner, "Type") { + return None; + } + match self.d_relationship_source(e) { + Some(src) if src != owner => None, + _ => Some(owner), + } + } + + /// The source end a relationship spells, by its metaclass's source + /// property (`subclassifier`, `subsettingFeature`, `conjugatedType`, + /// …). `None` when unspelled or unresolved — in which case + /// [`Self::d_relationship_owning_type`] takes the owning related + /// element as the source, which the grammars guarantee for every + /// relationship written on its specific side. Each carrier stores + /// only its own key, so no wrong key can match. + fn d_relationship_source(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + const SOURCES: &[&str] = &[ + "subclassifier", + "subsettingFeature", + "redefiningFeature", + "referencingFeature", + "crossingFeature", + "typedFeature", + "specific", + "conjugatedType", + "typeDisjoined", + "featureInverted", + "featureOfType", + ]; + SOURCES + .iter() + .find_map(|k| self.prop_target(e.0, k)) + .map(ElementRef) + } + + /// `Feature::owningFeatureMembership` — the owning relationship when it + /// is a FeatureMembership. + fn d_owning_feature_membership(&self, e: ElementRef) -> Option { + let rel = self.b.elements[e.0].owning_relationship?; + conforms(self.b.elements[rel].ty, "FeatureMembership").then_some(ElementRef(rel)) + } + + /// `Feature::owningType = owningFeatureMembership.owningType`. + pub(super) fn d_owning_type(&mut self, e: ElementRef) -> Option { + let m = self.d_owning_feature_membership(e)?; + self.d_owning_related_element(m) + .filter(|&o| self.is_kind(o, "Type")) + } + + /// `Feature::endOwningType` — the owning type through an + /// EndFeatureMembership. + fn d_end_owning_type(&mut self, e: ElementRef) -> Option { + let m = self.d_owning_feature_membership(e)?; + if self.b.elements[m.0].ty != "EndFeatureMembership" { + return None; + } + self.d_owning_type(e) + } + + // ---- Names, annotations and per-element structure ---- + + /// `Usage::isReference = not isComposite`; `None` where the metaclass + /// spells no compositeness. + fn d_is_reference(&self, e: ElementRef) -> Option { + self.b.elements[e.0] + .props + .get("isComposite") + .and_then(|v| v.as_bool()) + .map(|c| !c) + } + + /// `RequirementDefinition::text = documentation.body` — the bodies of + /// the element's owned Documentation, in declaration order. + fn d_text(&self, e: ElementRef) -> Vec { + self.d_owned_elements(e) + .into_iter() + .filter(|&k| self.b.elements[k.0].ty == "Documentation") + .filter_map(|k| { + self.b.elements[k.0] + .props + .get("body") + .and_then(|v| v.as_str()) + .map(str::to_string) + }) + .collect() + } + + /// `Type::multiplicity` — the owned member that is a Multiplicity (a + /// `[n..m]` MultiplicityRange, or a KerML `multiplicity` member). A + /// Type owns at most one. KerML's derive rule adds a fallback to the + /// general Type's multiplicity through an owned Specialization; that + /// contradicts the property's `subsets ownedMember`, and the property + /// definition wins here, as it does in the emitter. + fn d_multiplicity(&self, e: ElementRef) -> Option { + self.d_owned_members(e) + .into_iter() + .find(|&m| self.is_kind(m, "Multiplicity")) + } + + /// The Annotation relationships `e` owns that annotate `e` itself + /// (`annotates`) or another element (the `about` shape). An Annotation + /// that owns its annotating element annotates its owner. + fn d_owned_annotations(&mut self, e: ElementRef, annotates_self: bool) -> Vec { + let owned = self.owned_relationships_of_kind(e, "Annotation"); + if owned.is_empty() { + return owned; + } + self.ensure_by_id(); + owned + .into_iter() + .filter(|&r| { + let annotates = match self.prop_target(r.0, "annotatedElement") { + Some(t) => t == e.0, + // Unspelled: an Annotation that owns its annotating + // element annotates its owner (the prefix shape). + None => self.d_owned_annotating_element(r).is_some(), + }; + annotates == annotates_self + }) + .collect() + } + + /// `AnnotatingElement::annotation` — the owning Annotation (the + /// prefix shape) followed by the owned ones that annotate another. + fn d_annotations(&mut self, e: ElementRef) -> Vec { + let owning = self.b.elements[e.0] + .owning_relationship + .map(ElementRef) + .filter(|&r| self.b.elements[r.0].ty == "Annotation"); + let mut out: Vec = owning.into_iter().collect(); + out.extend(self.d_owned_annotations(e, false)); + out + } + + /// `AnnotatingElement::annotatedElement = if annotation->notEmpty() + /// then annotation.annotatedElement else Sequence{owningNamespace}` — + /// the owner stands in only when the element carries no annotation at + /// all. A target outside the model is reported as such. + fn d_annotating_targets(&mut self, e: ElementRef) -> Vec { + let annotations = self.d_annotations(e); + if annotations.is_empty() { + return self + .d_owner(e) + .map(Reference::Element) + .into_iter() + .collect(); + } + let mut out = Vec::new(); + for a in annotations { + if let Some(t) = self.d_annotated_element(a) { + out.push(t); + } + } + out + } + + /// `Annotation::annotatedElement` — spelled, else the owner in the + /// shape where the Annotation owns its annotating element. + fn d_annotated_element(&mut self, a: ElementRef) -> Option { + self.ensure_by_id(); + if let Some(atom) = self.b.elements[a.0].props.get("annotatedElement").cloned() { + if let Some(r) = self.reference_of(&atom) { + return Some(r); + } + } + self.d_owned_annotating_element(a) + .and(self.d_owning_related_element(a)) + .map(Reference::Element) + } + + /// `Annotation::ownedAnnotatingElement` — the prefix-annotation + /// shape. Defensive: no model built from text carries it, and the + /// payload loader normalizes it away on load (the emitter reads it + /// from a raw array — `full_json.rs::prefix_annotation_shape_derives_from_compact`), + /// so this branch is reached only by a hand-built model. + fn d_owned_annotating_element(&self, a: ElementRef) -> Option { + self.b.elements[a.0] + .children + .iter() + .copied() + .map(ElementRef) + .find(|&k| self.is_kind(k, "AnnotatingElement")) + } + + /// `Annotation::annotatingElement` — the owned annotating element, + /// else the owner (the `about` shape this toolkit emits). + fn d_annotating_element(&mut self, a: ElementRef) -> Option { + if let Some(k) = self.d_owned_annotating_element(a) { + return Some(k); + } + self.d_owning_related_element(a) + .filter(|&o| self.is_kind(o, "AnnotatingElement")) + } + + // ---- Typing and structure bases ---- + + /// `Feature::type`: the targets of the feature's own typings + /// (`FeatureTyping`, `ConjugatedPortTyping`) and, transitively, of its + /// typing features — the features it subsets, redefines or references + /// through an owned Subsetting kind, and the last link of an owned + /// feature chain (KerML `Feature::typingFeatures`, closed). A typing + /// target outside the model (a library type when no library is + /// loaded) is reported as such; the walk through typing features stays + /// inside the model (library features included when loaded) and + /// guards cycles. + pub(super) fn d_types(&mut self, e: ElementRef) -> Vec { + self.ensure_by_id(); + let mut out: Vec = Vec::new(); + let mut visited: std::collections::HashSet = std::collections::HashSet::new(); + let mut stack = vec![e.0]; + while let Some(f) = stack.pop() { + if !visited.insert(f) { + continue; + } + // The explicit relationships and the implied *typings* (a + // variant's typing by its variation definition). The implied + // library subsettings are deliberately not followed: they + // would append the library chain (`Part`, `Item`, `Occurrence`, + // `Anything`) to every usage's types, a growth that belongs + // with the inheritance closure policy and its measurement. + let mut rels: Vec = self.b.elements[f].owned_relationships.to_vec(); + rels.extend( + self.implied_relationships(ElementRef(f)) + .into_iter() + .map(|r| r.0) + .filter(|&r| self.b.elements[r].ty == "FeatureTyping"), + ); + let mut last_chain: Option = None; + for r in rels { + let ty = self.b.elements[r].ty; + if matches!(ty, "FeatureTyping" | "ConjugatedPortTyping") { + if let Some(t) = self.b.elements[r] + .props + .get("type") + .and_then(|atom| self.reference_of(atom)) + { + if !out.contains(&t) { + out.push(t); + } + } + } else if conforms(ty, "Subsetting") { + let key = match ty { + "Redefinition" => "redefinedFeature", + "ReferenceSubsetting" => "referencedFeature", + "CrossSubsetting" => "crossedFeature", + _ => "subsettedFeature", + }; + if let Some(t) = self.prop_target(r, key) { + stack.push(t); + } + } else if ty == "FeatureChaining" { + last_chain = self.prop_target(r, "chainingFeature"); + } + } + if let Some(t) = last_chain { + stack.push(t); + } + } + out + } + + /// `Feature::chainingFeature = ownedFeatureChaining.chainingFeature`, + /// in chaining order; a link outside the model is reported as such. + pub(super) fn d_chaining_features(&mut self, e: ElementRef) -> Vec { + self.ensure_by_id(); + self.b.elements[e.0] + .owned_relationships + .iter() + .copied() + .filter(|&r| self.b.elements[r].ty == "FeatureChaining") + .filter_map(|r| { + self.b.elements[r] + .props + .get("chainingFeature") + .and_then(|atom| self.reference_of(atom)) + }) + .collect() + } + + /// `Feature::featureTarget = if chainingFeature->isEmpty() then self + /// else chainingFeature->last()`. + pub(super) fn d_feature_target(&mut self, e: ElementRef) -> Reference { + self.d_chaining_features(e) + .pop() + .unwrap_or(Reference::Element(e)) + } + + /// `Feature::crossFeature` — the second chaining feature of the + /// crossed feature of the owned CrossSubsetting, if any; `None` when + /// the crossed feature is outside the model (its chain is not + /// visible). + fn d_cross_feature(&mut self, e: ElementRef) -> Option { + self.ensure_by_id(); + let cross = self + .owned_relationships_of_kind(e, "CrossSubsetting") + .into_iter() + .next()?; + let crossed = ElementRef(self.prop_target(cross.0, "crossedFeature")?); + self.d_chaining_features(crossed).into_iter().nth(1) + } + + /// `Connector::relatedFeature` — the referenced features of the + /// connector ends (`connectorEnd.ownedReferenceSubsetting.referencedFeature`), + /// in end order; an end without a reference subsetting contributes + /// nothing, a target outside the model is reported as such. + /// `sourceFeature` is the first, `targetFeature` the rest. + pub(super) fn d_related_features(&mut self, e: ElementRef) -> Vec { + self.ensure_by_id(); + let features = self.d_features(e); + let ends = self.d_ends(features); + ends.into_iter() + .filter_map(|end| { + self.owned_relationships_of_kind(end, "ReferenceSubsetting") + .into_iter() + .next() + }) + .filter_map(|r| { + self.b.elements[r.0] + .props + .get("referencedFeature") + .and_then(|atom| self.reference_of(atom)) + }) + .collect() + } + + /// `Flow::sourceOutputFeature` / `targetInputFeature`: the first + /// owned feature of the first / second flow end (`from a.out` lowers + /// to a flow end owning a feature that redefines `out`). + fn d_flow_end_feature(&mut self, e: ElementRef, position: usize) -> Option { + let features = self.d_features(e); + let end = self + .d_ends(features) + .into_iter() + .filter(|&f| self.b.elements[f.0].ty == "FlowEnd") + .nth(position)?; + self.d_owned_features(end).into_iter().next() + } + + /// `Type::endFeature = feature->select(isEnd)` over the given features. + pub(super) fn d_ends(&self, features: Vec) -> Vec { + features + .into_iter() + .filter(|&f| { + self.b.elements[f.0] + .props + .get("isEnd") + .and_then(|v| v.as_bool()) + .unwrap_or(false) + }) + .collect() + } + + /// The direction-filtered features in feature order, per the OCL + /// (`feature->select(f | directionOf(f) = in or inout)`): every + /// directed one (`None`), the inputs (`Some(true)`: `in` and `inout`) + /// or the outputs (`Some(false)`: `out` and `inout`). The direction is + /// the effective one ([`Self::effective_direction`]: a parameter + /// membership's default stands in for an unspelled direction). + pub(super) fn d_directed( + &self, + features: Vec, + input: Option, + ) -> Vec { + let dir = |f: ElementRef| -> Option<&str> { self.effective_direction(f) }; + let one_way = match input { + None => return features.into_iter().filter(|&f| dir(f).is_some()).collect(), + Some(true) => "in", + Some(false) => "out", + }; + features + .into_iter() + .filter(|&f| matches!(dir(f), Some(d) if d == one_way || d == "inout")) + .collect() + } + + /// `variant = variantMembership.ownedVariantUsage`. + pub(super) fn d_variants(&self, e: ElementRef) -> Vec { + self.b.elements[e.0] + .owned_relationships + .iter() + .copied() + .filter(|&r| self.b.elements[r].ty == "VariantMembership") + .flat_map(|r| self.b.elements[r].children.iter().copied()) + .map(ElementRef) + .collect() + } + + // ---- Membership / Import side ---- + + /// `OwningMembership::ownedMemberElement` — the element the membership + /// owns (its `ownedRelatedElement`). + pub(super) fn d_owned_member_element(&self, m: ElementRef) -> Option { + self.b.elements[m.0] + .children + .first() + .copied() + .map(ElementRef) + } + + /// `Import::importedElement`: the imported namespace of a + /// NamespaceImport, the imported membership's member for a + /// MembershipImport. A target outside the model is reported as such — + /// an external membership cannot be dereferenced, so it stands for + /// its member. + fn d_imported_element(&mut self, imp: ElementRef) -> Option { + self.ensure_by_id(); + if let Some(atom) = self.b.elements[imp.0] + .props + .get("importedNamespace") + .cloned() + { + return self.reference_of(&atom); + } + let atom = self.b.elements[imp.0] + .props + .get("importedMembership")? + .clone(); + match self.reference_of(&atom)? { + Reference::Element(m) if conforms(self.b.elements[m.0].ty, "Membership") => { + self.d_member_element(m) + } + // A foreign payload may reference the element directly. + other => Some(other), + } + } +} + +/// Whether a composition base answers by reference (so an empty base +/// yields an empty `References` rather than `Elements`). +fn by_reference_base(base: &str) -> bool { + matches!( + base, + "type" + | "definition" + | "member" + | "annotatedElement" + | "importedElement" + | "featureTarget" + | "function" + | "instantiatedType" + | "referent" + ) || composition(base).is_some_and(|(b, _, _)| by_reference_base(b)) +} + +fn opt(e: Option) -> DerivedValue { + match e { + Some(e) => DerivedValue::Element(e), + None => DerivedValue::Null, + } +} + +fn opt_ref(r: Option) -> DerivedValue { + match r { + Some(r) => DerivedValue::Reference(r), + None => DerivedValue::Null, + } +} + +#[cfg(test)] +mod tests { + /// `declared` binary-searches the schema catalog: the metaclass entries + /// and every property list must stay sorted. + #[test] + fn catalog_is_sorted() { + use crate::schema_props::METACLASS_PROPS; + assert!(METACLASS_PROPS.windows(2).all(|w| w[0].0 < w[1].0)); + for (m, props) in METACLASS_PROPS { + assert!( + props.windows(2).all(|w| w[0].0 < w[1].0), + "{m}'s property list is not sorted" + ); + } + assert!( + crate::derived_names::DERIVED_NAMES + .windows(2) + .all(|w| w[0] < w[1]) + ); + } + + #[test] + fn hand_written_tables_are_sorted() { + assert!(super::EXACT.windows(2).all(|w| w[0] < w[1])); + assert!(super::PASSTHROUGH.windows(2).all(|w| w[0] < w[1])); + let mut seen = std::collections::HashSet::new(); + for n in super::computed_names() { + assert!(seen.insert(n), "{n} listed twice"); + } + } + + /// `derives` and `derived` agree by construction: a composition is + /// computed on a metaclass only where its whole base chain is + /// declared there. + #[test] + fn composition_fidelity_follows_the_declared_base_chain() { + use super::{Derives, OWNED_BASES, carries, composition, declared, derives, member_side}; + for (m, _) in crate::schema_props::METACLASS_PROPS { + for name in super::computed_names() { + if !matches!(derives(m, name), Derives::Exact | Derives::Passthrough) { + continue; + } + // A membership-side name is the owned member there, not the + // composition of the same name on the owner. + if member_side(m, name).is_some() { + continue; + } + let mut at = name; + while let Some((base, _, _)) = + composition(at).filter(|_| !super::is_hand_written(at)) + { + if OWNED_BASES.contains(&base) { + assert!( + carries(m, base), + "{m}.{name}: owned base {base} not carried" + ); + break; + } + assert!(declared(m, base), "{m}.{name}: base {base} not declared"); + at = base; + } + } + } + } + + #[test] + fn computed_names_are_declared_somewhere() { + for name in super::computed_names() { + assert!( + crate::derived_names::DERIVED_NAMES + .binary_search(&name) + .is_ok(), + "{name} is not a derived name" + ); + } + } +} diff --git a/crates/sysmlv2-model/src/json/derived_compositions.rs b/crates/sysmlv2-model/src/json/derived_compositions.rs new file mode 100644 index 0000000..e14c20e --- /dev/null +++ b/crates/sysmlv2-model/src/json/derived_compositions.rs @@ -0,0 +1,243 @@ +//! Generated from `spec-refs/{KerML,SysML}.xmi` (normative metamodel +//! 20250201) by `tools/derived_census.py` — do not edit. +//! +//! Kind-filtered compositions among the derived properties: `name = +//! base->selectByKind(kind)` per the OCL derivation rules, and the +//! rule-less `*Definition` back-references, which the normative +//! documentation defines as the usage's `definition`s of the +//! property's declared type. `single` marks an upper bound of 1 (the +//! first match, else null). A composition is computable exactly when +//! its base is. + +/// `(name, base, kind, single)`, sorted by name. +pub(crate) static COMPOSITIONS: &[(&str, &str, &str, bool)] = &[ + ("action", "usage", "ActionUsage", false), + ("actionDefinition", "definition", "Behavior", false), + ("allocation", "usage", "AllocationUsage", false), + ( + "allocationDefinition", + "definition", + "AllocationDefinition", + false, + ), + ( + "analysisCaseDefinition", + "definition", + "AnalysisCaseDefinition", + true, + ), + ("attributeDefinition", "definition", "DataType", false), + ("behavior", "type", "Behavior", false), + ("calculation", "action", "CalculationUsage", false), + ("calculationDefinition", "definition", "Function", true), + ("caseDefinition", "definition", "CaseDefinition", true), + ("concernDefinition", "definition", "ConcernDefinition", true), + ( + "connectionDefinition", + "definition", + "AssociationStructure", + false, + ), + ("constraintDefinition", "definition", "Predicate", true), + ("directedUsage", "directedFeature", "Usage", false), + ("documentation", "ownedElement", "Documentation", false), + ( + "enumerationDefinition", + "definition", + "EnumerationDefinition", + true, + ), + ("flowDefinition", "definition", "Interaction", false), + ("flowEnd", "connectorEnd", "FlowEnd", false), + ( + "interfaceDefinition", + "definition", + "InterfaceDefinition", + false, + ), + ("itemDefinition", "occurrenceDefinition", "Structure", false), + ("metadataDefinition", "definition", "Metaclass", true), + ("nestedAction", "nestedUsage", "ActionUsage", false), + ("nestedAllocation", "nestedUsage", "AllocationUsage", false), + ( + "nestedAnalysisCase", + "nestedUsage", + "AnalysisCaseUsage", + false, + ), + ("nestedAttribute", "nestedUsage", "AttributeUsage", false), + ( + "nestedCalculation", + "nestedUsage", + "CalculationUsage", + false, + ), + ("nestedCase", "nestedUsage", "CaseUsage", false), + ("nestedConcern", "nestedUsage", "ConcernUsage", false), + ("nestedConnection", "nestedUsage", "ConnectorAsUsage", false), + ("nestedConstraint", "nestedUsage", "ConstraintUsage", false), + ( + "nestedEnumeration", + "nestedUsage", + "EnumerationUsage", + false, + ), + ("nestedFlow", "nestedUsage", "FlowConnectionUsage", false), + ("nestedInterface", "nestedUsage", "ReferenceUsage", false), + ("nestedItem", "nestedUsage", "ItemUsage", false), + ("nestedMetadata", "nestedUsage", "MetadataUsage", false), + ("nestedOccurrence", "nestedUsage", "OccurrenceUsage", false), + ("nestedPart", "nestedUsage", "PartUsage", false), + ("nestedPort", "nestedUsage", "PortUsage", false), + ("nestedReference", "nestedUsage", "ReferenceUsage", false), + ("nestedRendering", "nestedUsage", "RenderingUsage", false), + ( + "nestedRequirement", + "nestedUsage", + "RequirementUsage", + false, + ), + ("nestedState", "nestedUsage", "StateUsage", false), + ("nestedTransition", "nestedUsage", "TransitionUsage", false), + ("nestedUsage", "ownedFeature", "Usage", false), + ("nestedUseCase", "nestedUsage", "UseCaseUsage", false), + ( + "nestedVerificationCase", + "nestedUsage", + "VerificationCaseUsage", + false, + ), + ("nestedView", "nestedUsage", "ViewUsage", false), + ("nestedViewpoint", "nestedUsage", "ViewpointUsage", false), + ("occurrenceDefinition", "definition", "Class", false), + ("ownedAction", "ownedUsage", "ActionUsage", false), + ("ownedAllocation", "ownedUsage", "AllocationUsage", false), + ( + "ownedAnalysisCase", + "ownedUsage", + "AnalysisCaseUsage", + false, + ), + ("ownedAttribute", "ownedUsage", "AttributeUsage", false), + ("ownedCalculation", "ownedUsage", "CalculationUsage", false), + ("ownedCase", "ownedUsage", "CaseUsage", false), + ("ownedConcern", "ownedUsage", "ConcernUsage", false), + ("ownedConnection", "ownedUsage", "ConnectorAsUsage", false), + ("ownedConstraint", "ownedUsage", "ConstraintUsage", false), + ( + "ownedDifferencing", + "ownedRelationship", + "Differencing", + false, + ), + ("ownedDisjoining", "ownedRelationship", "Disjoining", false), + ("ownedEnumeration", "ownedUsage", "EnumerationUsage", false), + ( + "ownedFeatureChaining", + "ownedRelationship", + "FeatureChaining", + false, + ), + ( + "ownedFeatureMembership", + "ownedRelationship", + "FeatureMembership", + false, + ), + ("ownedFlow", "ownedUsage", "FlowConnectionUsage", false), + ("ownedImport", "ownedRelationship", "Import", false), + ("ownedInterface", "ownedUsage", "ReferenceUsage", false), + ( + "ownedIntersecting", + "ownedRelationship", + "Intersecting", + false, + ), + ("ownedItem", "ownedUsage", "ItemUsage", false), + ("ownedMembership", "ownedRelationship", "Membership", false), + ("ownedMetadata", "ownedUsage", "MetadataUsage", false), + ("ownedOccurrence", "ownedUsage", "OccurrenceUsage", false), + ("ownedPart", "ownedUsage", "PartUsage", false), + ("ownedPort", "ownedUsage", "PortUsage", false), + ( + "ownedRedefinition", + "ownedSubsetting", + "Redefinition", + false, + ), + ("ownedReference", "ownedUsage", "ReferenceUsage", false), + ("ownedRendering", "ownedUsage", "RenderingUsage", false), + ("ownedRequirement", "ownedUsage", "RequirementUsage", false), + ("ownedState", "ownedUsage", "StateUsage", false), + ( + "ownedSubclassification", + "ownedSpecialization", + "Subclassification", + false, + ), + ( + "ownedSubsetting", + "ownedSpecialization", + "Subsetting", + false, + ), + ("ownedTransition", "ownedUsage", "TransitionUsage", false), + ("ownedTyping", "ownedSpecialization", "FeatureTyping", false), + ("ownedUnioning", "ownedRelationship", "Unioning", false), + ("ownedUsage", "ownedFeature", "Usage", false), + ("ownedUseCase", "ownedUsage", "UseCaseUsage", false), + ( + "ownedVerificationCase", + "ownedUsage", + "VerificationCaseUsage", + false, + ), + ("ownedView", "ownedUsage", "ViewUsage", false), + ("ownedViewpoint", "ownedUsage", "ViewpointUsage", false), + ("partDefinition", "itemDefinition", "PartDefinition", false), + ("portDefinition", "definition", "PortDefinition", false), + ("rendering", "usage", "RenderingUsage", false), + ( + "renderingDefinition", + "definition", + "RenderingDefinition", + true, + ), + ( + "requirementDefinition", + "definition", + "RequirementDefinition", + true, + ), + ("state", "action", "StateUsage", false), + ("stateDefinition", "definition", "Behavior", false), + ("step", "feature", "Step", false), + ( + "textualRepresentation", + "ownedElement", + "TextualRepresentation", + false, + ), + ("usage", "feature", "Usage", false), + ("useCaseDefinition", "definition", "UseCaseDefinition", true), + ( + "variantMembership", + "ownedMembership", + "VariantMembership", + false, + ), + ( + "verificationCaseDefinition", + "definition", + "VerificationCaseDefinition", + true, + ), + ("view", "usage", "ViewUsage", false), + ("viewDefinition", "definition", "ViewDefinition", true), + ( + "viewpointDefinition", + "definition", + "ViewpointDefinition", + true, + ), +]; diff --git a/crates/sysmlv2-model/src/json/implied.rs b/crates/sysmlv2-model/src/json/implied.rs new file mode 100644 index 0000000..bccb0e7 --- /dev/null +++ b/crates/sysmlv2-model/src/json/implied.rs @@ -0,0 +1,258 @@ +//! Implied relationships, materialized lazily in the resolved model. +//! +//! SysML 8.4.2 Tables 31/32 give every definition and usage kind a library +//! base it implicitly specializes (`part def` → `Parts::Part`, `part` → +//! `Parts::parts`, …) unless an explicit specialization of the covering +//! kind is written, and a variant usage implicitly specializes the +//! variation it is a variant of (SysML `checkUsageVariationDefinition- +//! Specialization` / `-UsageSpecialization`: a FeatureTyping to the +//! owning variation definition — an enumeration literal's typing — or a +//! Subsetting to the owning variation usage). These relationships are +//! part of the abstract syntax (`isImplied = true`, listed under the +//! specific element's `ownedRelationship` when `isImpliedIncluded`), but +//! the builder never creates them: the lowering keeps the element graph +//! at what the text says, and name resolution reads the same tables as +//! implied heritage instead ([`super::implicit_def_bases`]). +//! +//! The derivation layer materializes them on first demand for the whole +//! model — when the library bases are known, from a loaded library or a +//! name table ([`ResolvedModel::set_library_names`]); a model with +//! neither gets none at all, the variant specializations included, so +//! that `isImpliedIncluded` (false without a library) never contradicts +//! a listed implied relationship (KerML: `ownedRelationship->exists(isImplied) +//! implies isImpliedIncluded`). One relationship element per implied +//! specialization, appended +//! to the element list past every explicit element (`Builder::implied_from` +//! marks the boundary, so the checks, lints and iteration over the model +//! keep to the explicit elements), owned by its specific side through a +//! side table rather than the owner's `ownedRelationship` row — the +//! resolver, the expression evaluator and the language server keep the +//! explicit graph they were built on. The relationship families read the +//! side table ([`ResolvedModel::implied_relationships`]); the full-form +//! emitter takes its implied relationships from here. +//! +//! Ids are the emitter's: `uuid5(OID, "{owner id}/implied{n}")` with `n` +//! the relationship's position among its owner's implied ones — the +//! library bases in table order, then the variant specialization. + +use super::{Elem, ElementRef, ResolvedModel, implicit_def_bases, implicit_usage_bases}; +use crate::lift::{def_kind_of, usage_kind_of}; +use crate::metaclass::conforms; +use serde_json::json; +use std::collections::HashMap; +use sysmlv2_syntax::ast::Dialect; +use uuid::Uuid; + +/// One kind's implied specializations: the library bases (qualified +/// names), the relationship metaclass, its source and target keys, and +/// the explicit metaclasses that cover them. +type ImpliedBases = ( + &'static [&'static str], + &'static str, + &'static str, + &'static str, + &'static [&'static str], +); + +/// The materialized implied relationships: their owners, and each +/// owner's list in order. +pub(super) struct ImpliedTable { + /// Index of the first implied relationship in the element list. + pub from: usize, + /// Owner of the implied relationship at `from + k`. + pub owner_of: Vec, + /// Owner → its implied relationships, in order. + pub by_owner: HashMap>, +} + +impl ResolvedModel { + /// Materialize the implied relationships on first demand. + pub(super) fn ensure_implied(&mut self) { + if self.implied.is_some() { + return; + } + self.ensure_by_id(); + self.ensure_rel_owner(); + let from = self.b.elements.len(); + let lib_by_name: HashMap = self + .b + .lib_qnames + .iter() + .map(|(id, segments)| (segments.join("::"), *id)) + .chain( + self.external_by_name + .iter() + .map(|(name, id)| (name.clone(), *id)), + ) + .collect(); + let mut owner_of: Vec = Vec::new(); + let mut by_owner: HashMap> = HashMap::new(); + // User elements only, as the emitter did: the library's own + // elements specialize explicitly. No bases known, nothing at all. + let range = if lib_by_name.is_empty() { + 0..0 + } else { + self.b.lib_boundary..from + }; + for i in range { + let plan = self.implied_plan(i, &lib_by_name); + if plan.is_empty() { + continue; + } + let owner_id = self.b.elements[i].id; + for (n, (rel_ty, src_key, tgt_key, target)) in plan.into_iter().enumerate() { + let id = Uuid::new_v5( + &Uuid::NAMESPACE_OID, + format!("{owner_id}/implied{n}").as_bytes(), + ); + let mut props = crate::properties::Properties::new(); + props.insert("isImplied", json!(true)); + props.insert(src_key, json!({ "@id": owner_id.to_string() })); + props.insert(tgt_key, json!({ "@id": target.to_string() })); + self.b.elements.push(Elem { + ty: rel_ty, + id, + path: String::new(), + props, + owned_relationships: Default::default(), + children: Default::default(), + owning_relationship: None, + }); + let idx = self.b.elements.len() - 1; + owner_of.push(i); + by_owner.entry(i).or_default().push(idx); + } + } + self.b.implied_from = Some(from); + self.implied = Some(ImpliedTable { + from, + owner_of, + by_owner, + }); + // The lazy maps are keyed on the element count: rebuild them so + // the new relationships have ids and owners. + self.ensure_by_id(); + self.rel_owner.clear(); + self.ensure_rel_owner(); + } + + /// The implied relationships element `i` gets: `(metaclass, source + /// key, target key, target id)`, in emission order. + fn implied_plan( + &self, + i: usize, + lib_by_name: &HashMap, + ) -> Vec<(&'static str, &'static str, &'static str, Uuid)> { + let t = self.b.elements[i].ty; + let mut plan = Vec::new(); + let explicit: Vec = self.b.elements[i].owned_relationships.to_vec(); + // Tables 31/32: the library bases of the element's kind, unless an + // explicit specialization of the covering kind is present + // (anti-redundancy, approximated as any explicit same-kind + // specialization — the emitter's rule). + let bases: Option = if let Some(kind) = def_kind_of(t) { + Some(( + implicit_def_bases(kind), + "Subclassification", + "subclassifier", + "superclassifier", + &["Subclassification", "Specialization"], + )) + } else { + usage_kind_of(t, Dialect::Sysml).map(|kind| { + ( + implicit_usage_bases(kind), + "Subsetting", + "subsettingFeature", + "subsettedFeature", + &["Subsetting", "Redefinition", "ReferenceSubsetting"] as &[&str], + ) + }) + }; + if let Some((bases, rel_ty, src, tgt, covering)) = bases { + let covered = explicit + .iter() + .any(|&r| covering.contains(&self.b.elements[r].ty)); + if !covered { + for base in bases { + if let Some(&id) = lib_by_name.get(*base) { + plan.push((rel_ty, src, tgt, id)); + } + } + } + } + // A variant specializes the variation it belongs to: a typing by + // the owning variation definition, a subsetting of the owning + // variation usage — unless written explicitly. The specification + // asks for a direct *or indirect* specialization; only a direct + // one is recognized here (`variant part small : Sub` with `Sub :> + // Box` still gets the implied typing by `Box`), the same + // approximation as the covering rule above. + if let Some(rel) = self.b.elements[i].owning_relationship { + if self.b.elements[rel].ty == "VariantMembership" { + if let Some(variation) = self.rel_owner[rel] { + let variation_id = self.b.elements[variation].id; + let targets = |kinds: &[&str], key: &str| -> bool { + explicit.iter().any(|&r| { + kinds.contains(&self.b.elements[r].ty) + && self.b.elements[r] + .props + .get(key) + .and_then(|v| v.as_reference()) + == Some(variation_id) + }) + }; + let vty = self.b.elements[variation].ty; + if conforms(vty, "Definition") { + if !targets(&["FeatureTyping", "ConjugatedPortTyping"], "type") { + plan.push(("FeatureTyping", "typedFeature", "type", variation_id)); + } + } else if conforms(vty, "Usage") + && !targets( + &["Subsetting", "Redefinition", "ReferenceSubsetting"], + "subsettedFeature", + ) + { + plan.push(( + "Subsetting", + "subsettingFeature", + "subsettedFeature", + variation_id, + )); + } + } + } + } + plan + } + + /// The implied relationships `e` owns — the library specializations + /// of its kind (SysML Tables 31/32) and a variant's specialization of + /// its variation — as relationship elements of the model, in + /// emission order. Materialized for the whole model on first call + /// (see the module documentation); empty for a library element, and + /// for every element of a model built without its library and + /// without a library name table ([`Self::set_library_names`]). + pub fn implied_relationships(&mut self, e: ElementRef) -> Vec { + self.ensure_implied(); + self.implied + .as_ref() + .and_then(|t| t.by_owner.get(&e.0)) + .map(|v| v.iter().copied().map(ElementRef).collect()) + .unwrap_or_default() + } + + /// `Element::ownedRelationship` with the implied relationships + /// included, as the specification lists them: the explicit ones in + /// declaration order, then the implied ones. + pub(super) fn d_owned_relationships(&mut self, e: ElementRef) -> Vec { + let mut out = self.owned_relationships(e); + out.extend(self.implied_relationships(e)); + out + } + + /// Whether `e` is a materialized implied relationship. + pub fn is_implied(&self, e: ElementRef) -> bool { + self.implied.as_ref().is_some_and(|t| e.0 >= t.from) + } +} diff --git a/crates/sysmlv2-model/src/json/naming.rs b/crates/sysmlv2-model/src/json/naming.rs new file mode 100644 index 0000000..771eed9 --- /dev/null +++ b/crates/sysmlv2-model/src/json/naming.rs @@ -0,0 +1,345 @@ +//! The specification's naming rule over the resolved model — KerML 8.2.3.5 +//! `Element::effectiveName()` / `effectiveShortName()` and the +//! `qualifiedName` derivation — as the derivation layer answers `name`, +//! `shortName` and `qualifiedName` and as the public name accessors +//! ([`ResolvedModel::element_effective_name`], +//! [`ResolvedModel::element_short_name`], +//! [`ResolvedModel::element_qualified_name`]) read them. +//! +//! A Feature with neither a declared name nor a declared short name takes +//! both names from its *naming feature* (KerML `Feature::effectiveName()` +//! / `effectiveShortName()`: `if declaredShortName <> null or declaredName +//! <> null then declaredName else namingFeature().effectiveName()` — a +//! feature that declares either name declares both): the feature +//! it explicitly redefines, else — for the memberships whose owned +//! feature implicitly redefines a library feature (a binary connector's +//! two ends, a flow's payload, a return parameter, a subject, an objective, +//! a view rendering, a transition's accepter, an invocation's positional +//! arguments) — the positional name the pilot implementation computes +//! from that implied redefinition, else the feature it references, else +//! the last link of its feature chain. The naming feature's name is +//! itself effective, so a chain of unnamed redefinitions resolves to the +//! first named ancestor. A naming feature outside the model (a library +//! feature when no library is loaded) is named through +//! [`ResolvedModel::set_library_names`] when the caller supplied a +//! library name table; otherwise the element stays unnamed, as it does +//! on the wire. +//! +//! These rules are the ones `full.rs` carried as `effective_name_of` / +//! `implied_member_name` / `qname_of`; the emitter now projects the +//! layer's values and keeps those only as the fallback for an element the +//! projection cannot find. + +use super::{ElementRef, ResolvedModel}; +use crate::metaclass::conforms; +use crate::properties::Atom; + +/// The feature that names an unnamed one, once found. +enum Naming { + /// A feature of the model. + Feature(usize), + /// A feature outside the model, already named through the library + /// name table. + Named(String), + /// A positional name the pilot computes from an implied redefinition. + Positional(String), +} + +impl ResolvedModel { + /// `Element::effectiveName()` for the element at `e`, memoized. + pub(super) fn effective_name_of(&mut self, e: usize) -> Option { + self.ensure_name_memo(); + if let Some(memo) = &self.name_memo[e] { + return memo.clone(); + } + let name = self.effective_name_walk(e, 0); + self.name_memo[e] = Some(name.clone()); + name + } + + /// `Element::effectiveShortName()` for the element at `e`: the + /// declared short name when the element declares either name, else + /// the naming feature's effective short name (an implied positional + /// name carries none). + pub(super) fn effective_short_name_of(&mut self, e: usize) -> Option { + self.effective_short_name_walk(e, 0) + } + + fn effective_short_name_walk(&mut self, e: usize, depth: usize) -> Option { + if depth > 32 { + return None; + } + if self.declares_a_name(e) { + return self.declared(e, "declaredShortName"); + } + match self.naming_feature(e)? { + Naming::Feature(t) => self.effective_short_name_walk(t, depth + 1), + Naming::Named(_) | Naming::Positional(_) => None, + } + } + + /// Whether the element declares a name or a short name — either one + /// makes both of its names the declared ones. + fn declares_a_name(&self, e: usize) -> bool { + let props = &self.b.elements[e].props; + props + .get("declaredName") + .is_some_and(|v| v.as_str().is_some()) + || props + .get("declaredShortName") + .is_some_and(|v| v.as_str().is_some()) + } + + fn ensure_name_memo(&mut self) { + let n = self.b.elements.len(); + if self.name_memo.len() != n { + self.name_memo = vec![None; n]; + } + } + + fn declared(&self, e: usize, key: &str) -> Option { + self.b.elements[e] + .props + .get(key) + .and_then(|v| v.as_str()) + .map(str::to_string) + } + + fn effective_name_walk(&mut self, e: usize, depth: usize) -> Option { + if depth > 32 { + return None; + } + if self.declares_a_name(e) { + return self.declared(e, "declaredName"); + } + match self.naming_feature(e)? { + Naming::Feature(t) => self.effective_name_walk(t, depth + 1), + Naming::Named(n) | Naming::Positional(n) => Some(n), + } + } + + /// The naming feature of an unnamed element, in the pilot's + /// precedence: the first explicitly redefined feature that resolved, + /// the implied positional redefinition, then — unless the + /// element is an actor or stakeholder parameter, whose reference + /// subsets the library collection and carries no name — the referenced + /// feature, then the chain's last link. Only explicit relationships + /// count; the implied library specializations name nothing. + fn naming_feature(&mut self, e: usize) -> Option { + self.ensure_by_id(); + let rels: Vec = self.b.elements[e].owned_relationships.to_vec(); + let mut reference: Option = None; + let mut last_chain: Option = None; + for r in rels { + match self.b.elements[r].ty { + "Redefinition" => { + if let Some(target) = self.b.elements[r].props.get("redefinedFeature").cloned() + { + if let Some(naming) = self.naming_target(&target) { + return Some(naming); + } + } + } + "ReferenceSubsetting" => { + if reference.is_none() { + reference = self.b.elements[r].props.get("referencedFeature").cloned(); + } + } + "FeatureChaining" => { + last_chain = self.b.elements[r].props.get("chainingFeature").cloned(); + } + _ => {} + } + } + if let Some(n) = self.implied_member_name(e) { + return Some(Naming::Positional(n)); + } + let owning_ty = self.b.elements[e] + .owning_relationship + .map(|r| self.b.elements[r].ty); + if matches!(owning_ty, Some("ActorMembership" | "StakeholderMembership")) { + return None; + } + if let Some(naming) = reference.and_then(|t| self.naming_target(&t)) { + return Some(naming); + } + last_chain.and_then(|t| self.naming_target(&t)) + } + + /// A resolved naming target: a model element (whatever its own names + /// — a naming feature with only a short name leaves `name` null and + /// gives `shortName`, so `qualifiedName` still forms), or an element + /// outside the model the library name table names. An unresolved + /// reference is no naming feature. + fn naming_target(&self, target: &Atom) -> Option { + let id = target.as_reference()?; + match self.by_id.get(&id).copied() { + Some(t) => Some(Naming::Feature(t)), + None => self.external_names.get(&id).cloned().map(Naming::Named), + } + } + + /// The positional name of a member that implicitly redefines a library + /// feature (the pilot's computed redefinitions are its naming + /// features): a flow's payload feature redefines `payload`, a + /// transition's accept action `accepter`, a return parameter `result`, + /// a subject `subj`, an objective `obj`, a view rendering + /// `viewRendering`; an invocation's positional argument redefines the + /// callee's `in` parameter at its position; the two ends of a binary + /// connector-family usage redefine the library binary ends (`source` / + /// `target`; successions `earlierOccurrence` / `laterOccurrence`; + /// bindings `thisThing` / `sameThing`). The implied Redefinition + /// elements themselves are not materialized — only the names they + /// would confer. + fn implied_member_name(&mut self, e: usize) -> Option { + let t = self.b.elements[e].ty; + let rel = self.b.elements[e].owning_relationship?; + let rel_ty = self.b.elements[rel].ty; + if t == "PayloadFeature" { + return Some("payload".to_string()); + } + if t == "AcceptActionUsage" && rel_ty == "TransitionFeatureMembership" { + return Some("accepter".to_string()); + } + let fixed = match rel_ty { + "ReturnParameterMembership" => Some("result"), + "SubjectMembership" => Some("subj"), + "ObjectiveMembership" => Some("obj"), + "ViewRenderingMembership" => Some("viewRendering"), + _ => None, + }; + if let Some(n) = fixed { + return Some(n.to_string()); + } + if rel_ty == "ParameterMembership" { + return self.invocation_arg_name(e, rel); + } + if rel_ty != "EndFeatureMembership" { + return None; + } + self.ensure_rel_owner(); + let owner = self.rel_owner[rel]?; + let names: [&str; 2] = match self.b.elements[owner].ty { + "SuccessionAsUsage" | "Succession" | "TransitionUsage" => { + ["earlierOccurrence", "laterOccurrence"] + } + "BindingConnectorAsUsage" | "BindingConnector" => ["thisThing", "sameThing"], + "ConnectionUsage" + | "AllocationUsage" + | "InterfaceUsage" + | "Connector" + | "FlowUsage" + | "SuccessionFlowUsage" + | "Flow" + | "SuccessionFlow" => ["source", "target"], + _ => return None, + }; + let ends: Vec = self.b.elements[owner] + .owned_relationships + .iter() + .copied() + .filter(|&r| self.b.elements[r].ty == "EndFeatureMembership") + .collect(); + if ends.len() != 2 { + return None; + } + let pos = ends.iter().position(|&r| r == rel)?; + Some(names[pos].to_string()) + } + + /// The positional name of an invocation or constructor argument: the + /// pilot implicitly redefines the callee's input parameters (`in` and + /// `inout`) in declaration order, so the argument at position *k* is + /// named after the *k*-th input parameter — an unnamed one names + /// nothing but still holds its position. An argument owning any + /// Redefinition is a named argument and keeps that name (even + /// unresolved). An accept action's reference parameters are its + /// payload and receiver. + fn invocation_arg_name(&mut self, e: usize, rel: usize) -> Option { + let has_redefinition = self.b.elements[e] + .owned_relationships + .iter() + .any(|&r| self.b.elements[r].ty == "Redefinition"); + if has_redefinition { + return None; + } + self.ensure_rel_owner(); + let owner = self.rel_owner[rel]?; + let owner_rels: Vec = self.b.elements[owner].owned_relationships.to_vec(); + let owner_ty = self.b.elements[owner].ty; + if owner_ty == "AcceptActionUsage" { + let ref_params: Vec = owner_rels + .iter() + .copied() + .filter(|&r| { + self.b.elements[r].ty == "ParameterMembership" + && self.b.elements[r].children.first().is_some_and(|&k| { + matches!(self.b.elements[k].ty, "ReferenceUsage" | "Feature") + }) + }) + .collect(); + let pos = ref_params.iter().position(|&r| r == rel)?; + return ["payload", "receiver"].get(pos).map(|n| n.to_string()); + } + if !matches!(owner_ty, "InvocationExpression" | "ConstructorExpression") { + return None; + } + // The callee: the invocation's fn/type Membership target (an + // OwningMembership when the callee is a feature chain, which + // spells no memberElement). + let callee_rel = owner_rels + .iter() + .copied() + .find(|&r| matches!(self.b.elements[r].ty, "Membership" | "OwningMembership"))?; + let callee = self.prop_target(callee_rel, "memberElement")?; + let params: Vec> = self.b.elements[callee] + .owned_relationships + .iter() + .filter_map(|&r| self.b.elements[r].children.first().copied()) + .filter(|&k| { + matches!( + self.b.elements[k] + .props + .get("direction") + .and_then(|v| v.as_str()), + Some("in" | "inout") + ) + }) + .map(|k| self.declared(k, "declaredName")) + .collect(); + let pos = owner_rels + .iter() + .filter(|&&r| self.b.elements[r].ty == "ParameterMembership") + .position(|&r| r == rel)?; + params.get(pos).cloned().flatten() + } + + /// The segments of the specification's `qualifiedName`: the + /// `escapedName()` of every element from the document root down — + /// the effective name, else the effective short name — reached + /// through memberships only (`qualifiedName` is null for an element + /// without an `owningNamespace`, or with an unnamed one). Raw + /// (unescaped), root first. + pub(super) fn qualified_name_segments(&mut self, e: ElementRef) -> Option> { + self.ensure_rel_owner(); + let mut segs: Vec = Vec::new(); + let mut cur = e.0; + // The document root namespace is unnamed; reaching it (or any + // unowned element) ends the walk. + while let Some(rel) = self.b.elements[cur].owning_relationship { + if !conforms(self.b.elements[rel].ty, "Membership") { + return None; + } + let seg = self + .effective_name_of(cur) + .or_else(|| self.effective_short_name_of(cur))?; + segs.push(seg); + cur = self.rel_owner[rel]?; + } + if segs.is_empty() { + return None; + } + segs.reverse(); + Some(segs) + } +} diff --git a/crates/sysmlv2-model/src/json/scope_table.rs b/crates/sysmlv2-model/src/json/scope_table.rs new file mode 100644 index 0000000..281094a --- /dev/null +++ b/crates/sysmlv2-model/src/json/scope_table.rs @@ -0,0 +1,260 @@ +//! Immutable scope lookup tables. Names are sorted string-table entries and +//! bindings are checked ranges into one shared vector. Only edited scopes +//! rebuild a hash map; lookup and candidate enumeration read the table directly. +use super::{Binding, Scope}; +use crate::{ + flat::{Row, Slices}, + layered::LayeredVec, +}; +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{collections::HashMap, sync::Arc}; + +#[derive(Clone)] +pub(super) enum Names { + Owned(HashMap>), + Table { + rows: Row, + bindings: Arc>, + }, +} +impl Default for Names { + fn default() -> Self { + Self::Owned(HashMap::new()) + } +} +#[derive(Clone, Serialize, Deserialize)] +pub(super) struct Name { + #[serde(deserialize_with = "crate::cache_codec::shared_string")] + text: Arc, + start: usize, + end: usize, +} +impl Names { + pub(super) fn get(&self, name: &str) -> Option<&[Binding]> { + match self { + Self::Owned(map) => map.get(name).map(Vec::as_slice), + Self::Table { rows, bindings } => { + let row = if rows.len() <= 8 { + rows.iter().find(|row| row.text.as_ref() == name)? + } else { + &rows[rows + .binary_search_by(|row| row.text.as_ref().cmp(name)) + .ok()?] + }; + Some(&bindings[row.start..row.end]) + } + } + } + pub(super) fn push(&mut self, name: String, binding: Binding) { + if matches!(self, Self::Table { .. }) { + *self = Self::Owned( + self.iter() + .map(|(n, b)| (n.to_owned(), b.to_vec())) + .collect(), + ); + } + if let Self::Owned(map) = self { + map.entry(name).or_default().push(binding); + } + } + pub(super) fn iter(&self) -> NamesIter<'_> { + match self { + Self::Owned(map) => NamesIter::Owned(map.iter()), + Self::Table { rows, bindings } => NamesIter::Table(rows.iter(), bindings), + } + } + pub(super) fn values(&self) -> impl Iterator { + self.iter().map(|(_, b)| b) + } +} +pub(super) enum NamesIter<'a> { + Owned(std::collections::hash_map::Iter<'a, String, Vec>), + Table(std::slice::Iter<'a, Name>, &'a [Binding]), +} +impl<'a> Iterator for NamesIter<'a> { + type Item = (&'a str, &'a [Binding]); + fn next(&mut self) -> Option { + match self { + Self::Owned(it) => it.next().map(|(n, b)| (n.as_str(), b.as_slice())), + Self::Table(it, bindings) => it + .next() + .map(|n| (n.text.as_ref(), &bindings[n.start..n.end])), + } + } +} + +pub(super) fn serialize( + scopes: &LayeredVec, + s: S, +) -> Result { + use serde::ser::SerializeTuple; + let mut bindings = Vec::new(); + let mut rows = Vec::new(); + for scope in scopes { + for names in [&scope.names, &scope.effective_names] { + let mut entries: Vec<_> = names.iter().collect(); + entries.sort_unstable_by_key(|&(name, _)| name); + let mut row = Vec::with_capacity(entries.len()); + for (text, values) in entries { + let start = bindings.len(); + bindings.extend_from_slice(values); + row.push(Name { + text: text.into(), + start, + end: bindings.len(), + }); + } + rows.push(row); + } + } + let mut out = s.serialize_tuple(3)?; + out.serialize_element(scopes)?; + out.serialize_element(&Slices(rows.iter().map(Vec::as_slice).collect()))?; + out.serialize_element(&bindings)?; + out.end() +} + +pub(super) fn deserialize<'de, D: Deserializer<'de>>(d: D) -> Result, D::Error> { + #[derive(Deserialize)] + struct Wire { + scopes: Vec, + #[serde(with = "crate::flat::table")] + names: Vec>, + bindings: Vec, + } + let Wire { + mut scopes, + names, + bindings, + } = Wire::deserialize(d)?; + if scopes.len().checked_mul(2) != Some(names.len()) { + return Err(serde::de::Error::custom("scope/name row count mismatch")); + } + let mut end = 0; + for row in &names { + if row.windows(2).any(|pair| pair[0].text >= pair[1].text) { + return Err(serde::de::Error::custom( + "unsorted or duplicate scope names", + )); + } + for name in row { + if name.start != end || name.end < name.start || name.end > bindings.len() { + return Err(serde::de::Error::custom("invalid scope binding range")); + } + end = name.end; + } + } + if end != bindings.len() { + return Err(serde::de::Error::custom("unused scope bindings")); + } + let bindings = Arc::new(bindings); + for (i, scope) in scopes.iter_mut().enumerate() { + scope.names = Names::Table { + rows: names[2 * i].clone(), + bindings: bindings.clone(), + }; + scope.effective_names = Names::Table { + rows: names[2 * i + 1].clone(), + bindings: bindings.clone(), + }; + } + Ok(scopes.into()) +} + +#[cfg(test)] +mod tests { + use super::super::LookupAccess; + use super::*; + use crate::cache_codec; + #[derive(Serialize, Deserialize)] + struct Table(#[serde(with = "super")] LayeredVec); + fn binding(elem: usize) -> Binding { + Binding { + elem, + sub_scope: None, + visibility: LookupAccess::Public, + } + } + #[test] + fn lookup_tables_share_storage_and_preserve_all_candidates_on_edit() { + let mut scope = Scope::default(); + scope.names.push("z".into(), binding(2)); + scope.names.push("a".into(), binding(0)); + scope.names.push("a".into(), binding(1)); + scope.effective_names.push("z".into(), binding(3)); + let encoded = cache_codec::encode(&Table(vec![scope.clone(), scope].into())).unwrap(); + let table: Table = cache_codec::decode(&encoded).unwrap(); + let ( + Names::Table { + rows: a, + bindings: ab, + }, + Names::Table { + rows: b, + bindings: bb, + }, + ) = (&table.0[0].names, &table.0[1].names) + else { + panic!("expected shared lookup table") + }; + assert!(Arc::ptr_eq(ab, bb)); + let (Row::Shared { values: av, .. }, Row::Shared { values: bv, .. }) = (a, b) else { + panic!("expected shared name rows") + }; + assert!(Arc::ptr_eq(av, bv)); + assert!(Arc::ptr_eq(&a[0].text, &b[0].text)); + assert_eq!( + table.0[0].names.get("a"), + Some([binding(0), binding(1)].as_slice()) + ); + assert!(table.0[0].names.get("missing").is_none()); + let mut changed = table.0[0].clone(); + changed.names.push("a".into(), binding(4)); + changed.names.push("b".into(), binding(5)); + assert_eq!(changed.names.get("a").unwrap().len(), 3); + assert_eq!(table.0[0].names.get("a").unwrap().len(), 2); + assert!(table.0[1].names.get("b").is_none()); + assert_eq!( + changed.effective_names.get("z"), + Some([binding(3)].as_slice()) + ); + let edited = Table(vec![changed].into()); + let replay: Table = cache_codec::decode(&cache_codec::encode(&edited).unwrap()).unwrap(); + assert_eq!(replay.0[0].names.get("a"), edited.0[0].names.get("a")); + } + #[test] + fn malformed_scope_tables_are_rejected_before_lookup() { + let name = |text: &str, start, end| Name { + text: text.into(), + start, + end, + }; + let cases = [ + (vec![vec![name("a", 0, 1)]], vec![binding(0)]), // wrong scope count + ( + vec![vec![name("a", 1, 2)], vec![]], + vec![binding(0), binding(1)], + ), + (vec![vec![name("a", 0, 2)], vec![]], vec![binding(0)]), + ( + vec![vec![name("a", 0, 1), name("a", 1, 2)], vec![]], + vec![binding(0), binding(1)], + ), + ( + vec![vec![name("b", 0, 1), name("a", 1, 2)], vec![]], + vec![binding(0), binding(1)], + ), + (vec![vec![name("a", 0, 0)], vec![]], vec![binding(0)]), + (vec![vec![name("a", 0, usize::MAX)], vec![]], vec![]), + ]; + for (rows, bindings) in cases { + let wire = ( + vec![Scope::default()], + Slices(rows.iter().map(Vec::as_slice).collect()), + bindings, + ); + let bytes = cache_codec::encode(&(wire,)).unwrap(); + assert!(cache_codec::decode::
(&bytes).is_err()); + } + } +} diff --git a/crates/sysmlv2-model/src/json/typeops.rs b/crates/sysmlv2-model/src/json/typeops.rs new file mode 100644 index 0000000..d274d0f --- /dev/null +++ b/crates/sysmlv2-model/src/json/typeops.rs @@ -0,0 +1,417 @@ +//! Type-operation results and the evaluability residue over the resolved +//! model: the unioning, intersecting and differencing types and their +//! relationship ends, an association's related types, a connector's +//! default featuring type, and `isModelLevelEvaluable`. Each function +//! documents the specification rule it implements; the dispatch is in +//! `derived.rs`. + +use super::derived::Reference; +use super::{ElementRef, ResolvedModel}; +use std::collections::HashSet; + +/// The library packages whose functions the KerML concrete syntax names +/// as model-level evaluable (clause 7.4.10). The clause lists a subset of +/// each package's functions; every function of the three packages counts +/// here, an over-approximation recorded in the API reference. +const EVALUABLE_FUNCTION_PACKAGES: &[&str] = + &["BaseFunctions", "DataFunctions", "ControlFunctions"]; + +impl ResolvedModel { + // ---- type operations ---- + + /// `Type::unioningType = ownedUnioning.unioningType` and its + /// intersecting/differencing twins: the targets of the owned + /// relationships of `kind`, under `key`. + pub(super) fn d_operation_types( + &mut self, + e: ElementRef, + kind: &str, + key: &str, + ) -> Vec { + self.ensure_by_id(); + self.owned_relationships_of_kind(e, kind) + .into_iter() + .filter_map(|r| { + self.b.elements[r.0] + .props + .get(key) + .and_then(|atom| self.reference_of(atom)) + }) + .collect() + } + + // ---- associations ---- + + /// `Association::relatedType = associationEnd.type`, in end order — a + /// sequence (`isUnique = false`: a binary association over one type + /// relates it twice), each end's types, targets outside the model + /// included. `sourceType` is its first, `targetType` the rest as an + /// ordered set. + pub(super) fn d_related_types(&mut self, e: ElementRef) -> Vec { + let features = self.d_features(e); + let ends = self.d_ends(features); + let mut out: Vec = Vec::new(); + for end in ends { + out.extend(self.d_types(end)); + } + out + } + + /// `Association::targetType = relatedType->subSequence(2, size)->asOrderedSet()`. + pub(super) fn d_target_types(&mut self, e: ElementRef) -> Vec { + let mut out: Vec = Vec::new(); + for t in self.d_related_types(e).into_iter().skip(1) { + if !out.contains(&t) { + out.push(t); + } + } + out + } + + // ---- featuring ---- + + /// `Feature::featuringType` at the passthrough level: the owning type, + /// the owned TypeFeaturings' targets, and — for a chained feature — + /// the first chaining feature's featuring types; elements of the model + /// only (a featuring type outside the model cannot enter a + /// specialization test). + pub(super) fn d_featuring_types(&mut self, f: ElementRef) -> Vec { + self.featuring_types_walk(f, 0) + } + + fn featuring_types_walk(&mut self, f: ElementRef, depth: usize) -> Vec { + self.ensure_by_id(); + let mut out: Vec = Vec::new(); + if let Some(o) = self.d_owning_type(f) { + out.push(o); + } + for tf in self.owned_relationships_of_kind(f, "TypeFeaturing") { + if let Some(t) = self.prop_target(tf.0, "featuringType") { + if !out.contains(&ElementRef(t)) { + out.push(ElementRef(t)); + } + } + } + if depth < 32 { + if let Some(Reference::Element(first)) = self.d_chaining_features(f).into_iter().next() + { + for t in self.featuring_types_walk(first, depth + 1) { + if !out.contains(&t) { + out.push(t); + } + } + } + } + out + } + + /// `closure(featuringType)` over a set of features and types: every + /// type featuring them directly or through the owning types of those + /// types' own features — the owning-type chain, in discovery order. + fn featuring_closure(&mut self, roots: &[ElementRef]) -> Vec { + let mut out: Vec = Vec::new(); + let mut frontier: Vec = roots.to_vec(); + let mut seen: HashSet = roots.iter().map(|r| r.0).collect(); + while let Some(x) = frontier.pop() { + let next: Vec = if self.is_kind(x, "Feature") { + self.d_featuring_types(x) + } else { + // A Type that is not a Feature is featured by nothing. + Vec::new() + }; + for t in next { + // A type reached for the first time is expanded; a root + // reached transitively (the OCL closure includes it then) + // joins the result without re-expansion. + if seen.insert(t.0) { + frontier.push(t); + } + if !out.contains(&t) { + out.push(t); + } + } + } + out + } + + /// Whether `t` specializes `general`, through the explicit + /// specializations of the model (`t` itself counts). Three clauses of + /// the normative `supertypes`/`specializes` are omitted, inert in + /// this lowering's featuring types: a Feature's `featureTarget` as a + /// supertype (a chain feature is never a featuring type here), a + /// conjugated type's `conjugator.originalType`, and + /// `Feature::isCompatibleWith`'s shared-redefinition clause. + pub(super) fn specializes(&mut self, t: ElementRef, general: ElementRef) -> bool { + let mut seen: HashSet = HashSet::new(); + let mut stack = vec![t]; + while let Some(x) = stack.pop() { + if x == general { + return true; + } + if !seen.insert(x.0) { + continue; + } + for r in self.d_owned_specializations(x, "Specialization") { + if let Some(Reference::Element(g)) = self.relationship_ends(r).1.into_iter().next() + { + stack.push(g); + } + } + } + false + } + + /// `Feature::isFeaturedWithin(type)` for a non-null type: every + /// featuring type of `f` is one `t` specializes; or `f` is variable and + /// `t` specializes its owning type; or `f` is a chain whose first link + /// is variable and `t` specializes that link's owning type. + fn is_featured_within(&mut self, f: ElementRef, t: ElementRef) -> bool { + let featuring = self.d_featuring_types(f); + if featuring.iter().all(|&ft| self.specializes(t, ft)) { + return true; + } + if self.prop_bool(f.0, "isVariable") { + if let Some(o) = self.d_owning_type(f) { + if self.specializes(t, o) { + return true; + } + } + } + if let Some(Reference::Element(first)) = self.d_chaining_features(f).into_iter().next() { + if self.prop_bool(first.0, "isVariable") { + if let Some(o) = self.d_owning_type(first) { + if self.specializes(t, o) { + return true; + } + } + } + } + false + } + + /// `Connector::defaultFeaturingType`: of the types featuring the related + /// features directly or indirectly, those every related feature is + /// featured within; of those, the innermost — one no other of them is + /// featured within — first. Null when a related feature is outside the + /// model (its featuring is not visible) or there are none. + pub(super) fn d_default_featuring_type(&mut self, e: ElementRef) -> Option { + let related: Vec = self + .d_related_features(e) + .into_iter() + .map(|r| r.element()) + .collect::>>()?; + if related.is_empty() { + return None; + } + let candidates = self.featuring_closure(&related); + let mut common: Vec = Vec::new(); + for t in candidates { + let mut all = true; + for &f in &related { + if !self.is_featured_within(f, t) { + all = false; + break; + } + } + if all { + common.push(t); + } + } + // Innermost: reject t1 when another common type's closure reaches it. + let mut nearest: Vec = Vec::new(); + for &t1 in &common { + let mut outer = false; + for &t2 in &common { + if t2 != t1 && self.featuring_closure(&[t2]).contains(&t1) { + outer = true; + break; + } + } + if !outer { + nearest.push(t1); + } + } + nearest.into_iter().next() + } + + // ---- model-level evaluability ---- + + /// `Expression::isModelLevelEvaluable = modelLevelEvaluable(Set{})`, + /// the KerML walk: literals, null and metadata-access expressions are + /// evaluable; an invocation when its arguments are and its function is + /// a model-level evaluable library function; a constructor when its + /// arguments are; a feature reference when its referent is + /// `Anything::self`, or — not yet visited — an evaluable expression, a + /// feature of a metaclass or metadata feature, or an unfeatured feature + /// whose value, if any, is evaluable; any other expression when it + /// specializes nothing explicitly and every owned feature is an input + /// (or its result) with no features and no value, or an evaluable + /// result expression. + pub(super) fn d_is_model_level_evaluable(&mut self, e: ElementRef) -> bool { + self.model_level_evaluable(e, &HashSet::new(), 0) + } + + /// `visited` is the set of referents on the path from the root + /// expression (`visited->including(referent)` in the rule) — a value + /// per branch, not shared across sibling arguments. + fn model_level_evaluable( + &mut self, + e: ElementRef, + visited: &HashSet, + depth: usize, + ) -> bool { + // The tree recursion is over owned arguments (acyclic; reference + // cycles are guarded by `visited`), so the bound only protects the + // stack: deeper than any expression the parser accepts. + if depth > 256 { + return false; + } + let ty = self.b.elements[e.0].ty; + // SysML redefines `modelLevelEvaluable` as false on calculation + // and constraint usages (and so on the requirement, concern and + // case usages under them). + if self.is_kind(e, "CalculationUsage") || self.is_kind(e, "ConstraintUsage") { + return false; + } + if matches!(ty, "NullExpression" | "MetadataAccessExpression") + || self.is_kind(e, "LiteralExpression") + { + return true; + } + if ty == "FeatureReferenceExpression" { + return self.reference_model_level_evaluable(e, visited, depth); + } + // A ConstructorExpression is an InstantiationExpression, not an + // InvocationExpression: evaluable when its arguments are. + if self.is_kind(e, "InstantiationExpression") { + let args: Vec = self + .d_arguments(e) + .into_iter() + .filter_map(|a| a.element()) + .collect(); + for a in args { + if !self.model_level_evaluable(a, visited, depth + 1) { + return false; + } + } + if self.is_kind(e, "ConstructorExpression") { + return true; + } + let function = self.d_instantiated_type(e); + return function.is_some_and(|f| self.function_is_model_level_evaluable(&f)); + } + // The general rule. + let explicit = self + .d_owned_specializations(e, "Specialization") + .into_iter() + .any(|r| !self.is_implied(r)); + if explicit { + return false; + } + let result = self.d_result(e); + let features = self.d_owned_features(e); + for f in features { + let input = matches!(self.effective_direction(f), Some("in")) || Some(f) == result; + let plain = input + && self.d_owned_features(f).is_empty() + && self + .owned_relationships_of_kind(f, "FeatureValue") + .is_empty(); + if plain { + continue; + } + let result_expression = self.b.elements[f.0] + .owning_relationship + .is_some_and(|m| self.b.elements[m].ty == "ResultExpressionMembership") + && self.is_kind(f, "Expression") + && self.model_level_evaluable(f, visited, depth + 1); + if !result_expression { + return false; + } + } + true + } + + fn reference_model_level_evaluable( + &mut self, + e: ElementRef, + visited: &HashSet, + depth: usize, + ) -> bool { + let Some(referent) = self.d_referent(e) else { + return false; + }; + // `referent.conformsTo('Anything::self')`: the library feature + // `Base::Anything::self` (the standard library package is `Base`), + // or a feature specializing it (`DataValue::self` redefines it). + let anything_self = self.library_element_named(&[( + "Base::Anything::self".to_string(), + "Base::Anything::self".to_string(), + )]); + let referent = match referent { + Reference::Element(referent) => referent, + // A referent outside the model is evaluable only as + // `Anything::self` itself, by id. + outside => { + return matches!( + (outside, anything_self), + (Reference::External(a), Some(Reference::External(b))) if a == b + ); + } + }; + if let Some(Reference::Element(anything_self)) = anything_self { + if self.specializes(referent, anything_self) { + return true; + } + } + if visited.contains(&referent.0) { + return false; + } + let mut visited = visited.clone(); + visited.insert(referent.0); + let visited = &visited; + if self.is_kind(referent, "Expression") { + return self.model_level_evaluable(referent, visited, depth + 1); + } + if let Some(owner) = self.d_owning_type(referent) { + if self.is_kind(owner, "Metaclass") || self.is_kind(owner, "MetadataFeature") { + return true; + } + } + if !self.d_featuring_types(referent).is_empty() { + return false; + } + match self + .owned_relationships_of_kind(referent, "FeatureValue") + .into_iter() + .next() + .and_then(|fv| self.d_owned_member_element(fv)) + { + None => true, + Some(value) => self.model_level_evaluable(value, visited, depth + 1), + } + } + + /// `Function::isModelLevelEvaluable` for the function an invocation + /// instantiates: a function of the Kernel Functions Library's + /// `BaseFunctions`, `DataFunctions` or `ControlFunctions` — an element + /// of a loaded library, or an external id the library name table names + /// in one of them. + pub(super) fn function_is_model_level_evaluable(&mut self, f: &Reference) -> bool { + match f { + Reference::Element(f) => { + self.is_library_element(*f) + && self.element_qualified_name(*f).is_some_and(|qn| { + qn.split("::") + .next() + .is_some_and(|p| EVALUABLE_FUNCTION_PACKAGES.contains(&p)) + }) + } + Reference::External(id) => self + .external_package + .get(id) + .is_some_and(|p| EVALUABLE_FUNCTION_PACKAGES.contains(&p.as_str())), + Reference::Unresolved(_) => false, + } + } +} diff --git a/crates/sysmlv2-model/src/json/unused_imports_tests.rs b/crates/sysmlv2-model/src/json/unused_imports_tests.rs new file mode 100644 index 0000000..a83d03e --- /dev/null +++ b/crates/sysmlv2-model/src/json/unused_imports_tests.rs @@ -0,0 +1,292 @@ +//! Differential oracle for the conservative import contract. +use super::*; +use crate::model::Model; +use std::{ + fmt::Write as _, + fs, + path::{Path, PathBuf}, +}; + +impl ResolvedModel { + fn namespace_member_names_legacy(&self, e: ElementRef) -> Vec { + let mut out = Vec::new(); + let mut frontier = vec![(e, 0usize)]; + while let Some((cur, depth)) = frontier.pop() { + let props = &self.b.elements[cur.0].props; + for key in ["declaredName", "declaredShortName"] { + if let Some(name) = props.get(key).and_then(|v| v.as_str()) { + out.push(name.to_string()); + } + } + if depth < 8 && out.len() < 4096 { + for m in self.owned_members(cur) { + frontier.push((m, depth + 1)); + } + } + } + out + } + + fn unused_private_imports_legacy(&mut self) -> Vec<(ElementRef, ElementRef, usize, Span)> { + let candidates: Vec<(usize, Span, usize)> = self + .b + .user_imports + .iter() + .filter(|imp| { + imp.visibility == Some(Visibility::Private) + && !self.b.used_imports.contains(&imp.rel) + }) + .map(|imp| (imp.rel, imp.span, self.b.unit_of_elem(imp.rel))) + .collect(); + let mut out = Vec::new(); + for (rel, span, unit) in candidates { + // The import's own target (recorded as a ref site inside the + // member span). An unresolved target already warns + // referentially — stay quiet here. + let Some(target) = self + .b + .ref_sites + .iter() + .find(|s| { + s.unit == unit + && s.span.start >= span.start + && s.span.end <= span.end + && (s.kind == "importedNamespace" || s.kind == "importedMembership") + }) + .map(|s| s.target) + else { + continue; + }; + let sites: Vec = self + .b + .ref_sites + .iter() + .filter(|s| { + s.unit == unit && !(s.span.start >= span.start && s.span.end <= span.end) + }) + .map(|s| s.target) + .collect(); + let mut feeds = false; + for site_target in sites { + if site_target == target { + feeds = true; + break; + } + let mut e = site_target; + for _ in 0..64 { + match self.owner(e) { + Some(o) if o == target => { + feeds = true; + break; + } + Some(o) => e = o, + None => break, + } + } + if feeds { + break; + } + } + if !feeds { + out.push((ElementRef(rel), target, unit, span)); + } + } + out + } +} + +fn files(root: &Path, out: &mut Vec) { + for entry in fs::read_dir(root).unwrap() { + let path = entry.unwrap().path(); + if path.is_dir() { + files(&path, out); + } else if path + .extension() + .is_some_and(|x| x == "sysml" || x == "kerml") + { + out.push(path); + } + } +} + +fn compare(model: &Model) { + let units: Vec<_> = model + .units() + .iter() + .enumerate() + .filter_map(|(i, u)| (!u.is_library).then_some(i)) + .collect(); + let mut resolved = ResolvedModel::build(model); + let expected = resolved.unused_private_imports_legacy(); + let targets: Vec<_> = expected.iter().map(|(_, t, _, _)| *t).collect(); + let names = resolved.namespace_member_names_many(&targets); + for t in targets { + assert_eq!( + names[&t], + resolved.namespace_member_names_legacy(t), + "namespace enumeration contract" + ); + } + assert_eq!( + resolved.unused_private_imports(), + expected, + "all-unit contract" + ); + let expected: Vec<_> = expected + .into_iter() + .filter(|(_, _, u, _)| units.contains(u)) + .collect(); + assert_eq!( + resolved.unused_private_imports_for_units(&units), + expected, + "unit-filtered contract" + ); + assert!(resolved.unused_private_imports_for_units(&[]).is_empty()); +} + +#[test] +fn indexed_imports_match_legacy_on_cold_and_replayed_corpora() { + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../.."); + let library = root.join("spec-refs/SysML-v2-Release/sysml.library"); + if !library.is_dir() { + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let mut corpora = vec![ + "spec-refs/SysML-v2-Release/sysml/src".to_string(), + "spec-refs/apollo-11-sysml-v2".to_string(), + ]; + if let Ok(path) = std::env::var("SYSMLV2_IMPORT_CORPUS") { + corpora.push(path); + } + for corpus in corpora { + let path = root.join(&corpus); + if !path.is_dir() { + continue; + } + let mut paths = Vec::new(); + files(&path, &mut paths); + paths.sort(); + for replay in [false, true] { + let mut model = Model::new(); + model.load_library_dir(&library).unwrap(); + if replay { + model.set_library_cache(cache.clone()); + } + for path in &paths { + model.add_source( + path.display().to_string(), + &fs::read_to_string(path).unwrap(), + ); + } + compare(&model); + } + } +} + +#[test] +fn indexed_imports_match_legacy_on_generated_graphs() { + // Deep grammar nesting needs more stack than the test harness default. + std::thread::Builder::new() + .stack_size(32 * 1024 * 1024) + .spawn(|| { + for depth in [1, 8, 63, 64, 65, 80] { + let mut model = Model::new(); + let mut defs = String::from("package Defs {"); + for n in 0..depth { + let _ = write!(defs, "package N{n} {{"); + } + defs.push_str("part def Leaf;"); + defs.push_str(&"}".repeat(depth + 1)); + model.add_source("defs.sysml", &defs); + for unit in 0..3 { + let mut source = format!("package U{unit} {{"); + for _ in 0..12 { + source.push_str("private import Defs::*;"); + } + source.push_str("private import Missing::*; public import Defs::*;"); + let name = format!( + "Defs::{}Leaf", + (0..depth).map(|n| format!("N{n}::")).collect::() + ); + let _ = write!(source, "part p : {name}; }}"); + model.add_source(format!("u{unit}.sysml"), &source); + } + compare(&model); + } + }) + .unwrap() + .join() + .unwrap(); +} + +#[test] +fn namespace_index_preserves_wide_traversal_cutoff() { + let mut source = String::from("package Defs {"); + for p in 0..12 { + let _ = write!(source, "package P{p} {{"); + for e in 0..400 { + let _ = write!(source, "part def E{e};"); + } + source.push('}'); + } + source.push('}'); + let mut model = Model::new(); + model.add_source("wide.sysml", &source); + let mut resolved = ResolvedModel::build(&model); + let target = resolved.resolve_qualified("Defs").unwrap(); + let expected = resolved.namespace_member_names_legacy(target); + assert!(expected.len() >= 4096); + assert!(expected.len() < 4813); + assert_eq!(resolved.namespace_member_names(target), expected); +} + +#[test] +fn ancestry_index_keeps_the_exact_64_owner_limit() { + std::thread::Builder::new() + .stack_size(32 * 1024 * 1024) + .spawn(|| { + for depth in [63, 64, 65] { + let defs = format!( + "package Defs {{ {} part def Leaf; {}", + (0..depth) + .map(|i| format!("package N{i} {{")) + .collect::(), + "}".repeat(depth + 1) + ); + let mut model = Model::new(); + model.add_source("defs.sysml", &defs); + model.add_source("user.sysml", "package User { private import Defs::*; }"); + let mut r = ResolvedModel::build(&model); + let leaf = + r.b.elements + .iter() + .position(|e| { + e.props.get("declaredName").and_then(|v| v.as_str()) == Some("Leaf") + }) + .unwrap(); + // Supply a resolved use directly so this boundary test does not + // depend on the resolver's separate qualified-name depth budget. + let mut site = + r.b.ref_sites + .iter() + .find(|s| s.unit == 1 && s.kind == "importedNamespace") + .unwrap() + .clone(); + site.span = Span::new(0, 1); + site.target = ElementRef(leaf); + site.kind = "type".into(); + r.b.ref_sites.push(site); + let expected = r.unused_private_imports_legacy(); + assert_eq!(expected.len(), usize::from(depth >= 64)); + assert_eq!(r.unused_private_imports_for_units(&[1]), expected); + } + }) + .unwrap() + .join() + .unwrap(); +} diff --git a/crates/sysmlv2-model/src/layered.rs b/crates/sysmlv2-model/src/layered.rs new file mode 100644 index 0000000..6056588 --- /dev/null +++ b/crates/sysmlv2-model/src/layered.rs @@ -0,0 +1,354 @@ +//! Immutable library prefixes with private, copy-on-write overrides and append-only +//! model tails. Cloning a prepared graph shares its large element/scope storage. +//! +//! The tables iterate by reference only. A pass that needs owned rows +//! copies the rows it selects, never a whole table, so the shared library +//! prefix is never duplicated behind a by-value loop. +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use std::{ + collections::HashMap, + ops::{Index, IndexMut}, + sync::Arc, +}; + +#[cfg(test)] +thread_local! { + static COPIED_ROWS: std::cell::Cell = const { std::cell::Cell::new(0) }; +} + +/// Rows deep-copied on the current thread by whole-table clones and +/// prefix merges. Building a graph copies rows; a check pass over a +/// built graph must not. +#[cfg(test)] +pub(crate) fn copied_rows() -> usize { + COPIED_ROWS.with(|c| c.get()) +} + +#[cfg(test)] +fn note_copied(rows: usize) { + COPIED_ROWS.with(|c| c.set(c.get() + rows)); +} + +#[cfg(not(test))] +fn note_copied(_rows: usize) {} + +pub(crate) struct LayeredVec { + base: Arc>, + changed: Vec>>, + tail: Vec, +} +impl Clone for LayeredVec { + fn clone(&self) -> Self { + note_copied(self.changed.iter().flatten().count() + self.tail.len()); + Self { + base: Arc::clone(&self.base), + changed: self.changed.clone(), + tail: self.tail.clone(), + } + } +} +impl Default for LayeredVec { + fn default() -> Self { + Self { + base: Arc::new(Vec::new()), + changed: Vec::new(), + tail: Vec::new(), + } + } +} +impl LayeredVec { + pub fn len(&self) -> usize { + self.base.len() + self.tail.len() + } + pub fn get(&self, i: usize) -> Option<&T> { + (i < self.len()).then(|| &self[i]) + } + pub fn is_empty(&self) -> bool { + self.len() == 0 + } + pub fn push(&mut self, value: T) { + self.tail.push(value) + } + pub fn iter(&self) -> impl DoubleEndedIterator { + self.base + .iter() + .enumerate() + .map(|(i, value)| { + self.changed + .get(i) + .and_then(Option::as_deref) + .unwrap_or(value) + }) + .chain(self.tail.iter()) + } + pub fn freeze(&mut self) + where + T: Clone, + { + if self.tail.is_empty() && self.changed.is_empty() { + return; + } + if self.base.is_empty() { + self.base = Arc::new(std::mem::take(&mut self.tail)); + } else { + note_copied(self.len()); + self.base = Arc::new(self.iter().cloned().collect()); + self.tail.clear(); + } + self.changed.clear(); + } +} +impl From> for LayeredVec { + fn from(tail: Vec) -> Self { + Self { + tail, + ..Self::default() + } + } +} +impl Index for LayeredVec { + type Output = T; + fn index(&self, i: usize) -> &T { + if i < self.base.len() { + self.changed + .get(i) + .and_then(Option::as_deref) + .unwrap_or(&self.base[i]) + } else { + &self.tail[i - self.base.len()] + } + } +} +impl IndexMut for LayeredVec { + fn index_mut(&mut self, i: usize) -> &mut T { + if i < self.base.len() { + if self.changed.is_empty() { + self.changed.resize_with(self.base.len(), || None); + } + self.changed[i].get_or_insert_with(|| Box::new(self.base[i].clone())) + } else { + &mut self.tail[i - self.base.len()] + } + } +} +impl Serialize for LayeredVec { + fn serialize(&self, s: S) -> Result { + s.collect_seq(self.iter()) + } +} +impl<'de, T: Deserialize<'de>> Deserialize<'de> for LayeredVec { + fn deserialize>(d: D) -> Result { + Vec::deserialize(d).map(Self::from) + } +} + +impl LayeredVec { + pub fn resize(&mut self, n: usize, value: T) { + assert!(n >= self.len()); + self.tail.resize(n - self.base.len(), value); + } +} + +#[cfg(test)] +impl LayeredVec { + pub fn shares_prefix(&self, other: &Self) -> bool { + Arc::ptr_eq(&self.base, &other.base) + } +} + +/// Lookup table with an immutable library base and a private model table. +pub(crate) struct LayeredMap { + base: Arc>, + local: HashMap, +} +impl Clone for LayeredMap { + fn clone(&self) -> Self { + note_copied(self.local.len()); + Self { + base: Arc::clone(&self.base), + local: self.local.clone(), + } + } +} +impl Default for LayeredMap { + fn default() -> Self { + Self { + base: Arc::new(HashMap::new()), + local: HashMap::new(), + } + } +} +impl LayeredMap { + pub fn get(&self, key: &K) -> Option<&V> { + self.local.get(key).or_else(|| self.base.get(key)) + } + pub fn insert(&mut self, key: K, value: V) { + self.local.insert(key, value); + } + pub fn freeze(&mut self) + where + K: Clone, + V: Clone, + { + if self.local.is_empty() { + return; + } + if self.base.is_empty() { + self.base = Arc::new(std::mem::take(&mut self.local)); + } else { + if Arc::get_mut(&mut self.base).is_none() { + note_copied(self.base.len()); + } + Arc::make_mut(&mut self.base).extend(std::mem::take(&mut self.local)); + } + } +} +impl Serialize for LayeredMap { + fn serialize(&self, s: S) -> Result { + use serde::ser::SerializeMap; + let len = self.local.len() + + self + .base + .keys() + .filter(|k| !self.local.contains_key(k)) + .count(); + let mut map = s.serialize_map(Some(len))?; + for (k, v) in self + .base + .iter() + .filter(|(k, _)| !self.local.contains_key(k)) + .chain(self.local.iter()) + { + map.serialize_entry(k, v)?; + } + map.end() + } +} +impl<'de, K: Deserialize<'de> + Eq + std::hash::Hash, V: Deserialize<'de>> Deserialize<'de> + for LayeredMap +{ + fn deserialize>(d: D) -> Result { + Ok(Self { + local: HashMap::deserialize(d)?, + ..Self::default() + }) + } +} + +impl LayeredMap { + pub fn contains_key(&self, k: &K) -> bool { + self.local.contains_key(k) || self.base.contains_key(k) + } + pub fn iter(&self) -> impl Iterator { + self.base + .iter() + .filter(|(k, _)| !self.local.contains_key(k)) + .chain(self.local.iter()) + } + pub fn keys(&self) -> impl Iterator { + self.iter().map(|(k, _)| k) + } +} +impl LayeredMap { + pub fn entry(&mut self, k: K) -> std::collections::hash_map::Entry<'_, K, V> { + if !self.local.contains_key(&k) { + if let Some(value) = self.base.get(&k) { + self.local.insert(k.clone(), value.clone()); + } + } + self.local.entry(k) + } +} +impl FromIterator<(K, V)> for LayeredMap { + fn from_iter>(iter: I) -> Self { + Self { + local: iter.into_iter().collect(), + ..Self::default() + } + } +} +impl<'a, K: Eq + std::hash::Hash, V> IntoIterator for &'a LayeredMap { + type Item = (&'a K, &'a V); + type IntoIter = Box + 'a>; + fn into_iter(self) -> Self::IntoIter { + Box::new(self.iter()) + } +} +impl<'a, T> IntoIterator for &'a LayeredVec { + type Item = &'a T; + type IntoIter = Box + 'a>; + fn into_iter(self) -> Self::IntoIter { + Box::new(self.iter()) + } +} +impl FromIterator for LayeredVec { + fn from_iter>(iter: I) -> Self { + Vec::from_iter(iter).into() + } +} +impl Extend for LayeredVec { + fn extend>(&mut self, iter: I) { + self.tail.extend(iter); + } +} + +#[cfg(test)] +mod overlay_tests { + use super::*; + #[test] + fn overrides_append_and_refreeze_do_not_change_shared_bases() { + let mut a: LayeredVec<_> = vec![1, 2].into(); + a.freeze(); + let mut b = a.clone(); + b[0] = 3; + b.push(4); + b.freeze(); + assert_eq!(a.iter().copied().collect::>(), vec![1, 2]); + assert_eq!(b.iter().copied().collect::>(), vec![3, 2, 4]); + let mut a: LayeredMap<_, _> = [(1, 2)].into_iter().collect(); + a.freeze(); + let mut b = a.clone(); + *b.entry(1).or_default() = 3; + b.insert(4, 5); + b.freeze(); + assert_eq!(a.get(&1), Some(&2)); + assert_eq!(a.get(&4), None); + assert_eq!(b.get(&1), Some(&3)); + assert_eq!(b.get(&4), Some(&5)); + } + #[test] + fn reference_iteration_copies_nothing_and_copies_are_counted() { + let mut a: LayeredVec<_> = vec![1, 2].into(); + a.freeze(); + let mut b = a.clone(); + b.push(3); + let before = copied_rows(); + assert_eq!(b.iter().sum::(), 6); + assert_eq!((&b).into_iter().count(), 3); + assert_eq!(copied_rows(), before, "reading a table copies no rows"); + let c = b.clone(); + assert_eq!(copied_rows(), before + 1, "a clone copies only the tail"); + drop(c); + b.freeze(); + assert_eq!( + copied_rows(), + before + 4, + "merging a shared prefix copies it" + ); + let mut m: LayeredMap<_, _> = [(1, 2)].into_iter().collect(); + m.freeze(); + let mut n = m.clone(); + n.insert(3, 4); + let before = copied_rows(); + assert_eq!(n.iter().count(), 2); + assert_eq!(copied_rows(), before); + let _ = n.clone(); + assert_eq!(copied_rows(), before + 1); + n.freeze(); + assert_eq!( + copied_rows(), + before + 2, + "merging a shared prefix copies it" + ); + } +} diff --git a/crates/sysmlv2-model/src/lib.rs b/crates/sysmlv2-model/src/lib.rs index da22608..b52c829 100644 --- a/crates/sysmlv2-model/src/lib.rs +++ b/crates/sysmlv2-model/src/lib.rs @@ -6,16 +6,37 @@ //! referential checks, and evaluates expressions. pub mod ambient; +mod cache_codec; pub mod cbor_tables; pub mod check; +mod derived_names; pub mod eval; pub mod full; pub mod ids; pub mod json; +mod layered; pub mod libcache; pub mod lift; +pub mod loader; +mod metaclass; + +/// The canonical (`'static`) spelling of an abstract-syntax metaclass +/// name, `None` for a name the metamodel does not declare. +pub fn metaclass_name(name: &str) -> Option<&'static str> { + metaclass::canonical_name(name) +} +#[cfg(test)] +mod metaclass_tests; pub mod model; +pub mod prepared; pub mod quantity; +pub mod rational; pub mod render; mod schema_props; pub mod structure; + +mod semantic_memo; + +mod properties; + +mod flat; diff --git a/crates/sysmlv2-model/src/libcache.rs b/crates/sysmlv2-model/src/libcache.rs index 8acee19..740ecef 100644 --- a/crates/sysmlv2-model/src/libcache.rs +++ b/crates/sysmlv2-model/src/libcache.rs @@ -39,7 +39,9 @@ use uuid::Uuid; // qualified-name IDs — cached `lib_ids` from earlier versions are stale. // From v5 on, [`TOOLKIT_BUILD`] invalidates automatically across source // changes; bump the MAGIC digit only for serialized-layout changes. -const MAGIC: &[u8; 8] = b"SYSML5LC"; +// v6: outcomes may carry the root names their resolution missed, so a +// replay can re-resolve exactly the entries a model's root additions reach. +const MAGIC: &[u8; 8] = b"SYSML6LC"; /// Toolkit build identity stamped into every serialized cache: the crate /// version plus a fingerprint of the semantics-bearing crate sources @@ -54,12 +56,22 @@ pub const TOOLKIT_BUILD: &str = concat!( env!("SYSMLV2_SEMANTICS_FINGERPRINT") ); +/// The serialized header carries the build identity's length in one byte. +const _: () = assert!( + TOOLKIT_BUILD.len() <= 255, + "the cache header stores the build identity's length in one byte" +); + /// Recorded resolution outcomes for a library's pending references, in /// queue order. `None` = the reference did not resolve (also cached — the /// unresolved long tail is re-reported identically without re-searching). #[derive(Clone)] pub struct LibraryCache { pub(crate) outcomes: Vec>, + /// Per outcome, the root-namespace names its resolution looked up and + /// missed. A model that introduces one of them resolves that entry + /// afresh instead of replaying it. + pub(crate) outcome_misses: Vec>, /// Element ids of the library prefix, in creation order — replayed at /// element creation so the warm build skips ownership-path /// construction, per-element UUIDv5 hashing, and the whole normative @@ -80,16 +92,46 @@ pub struct LibraryCache { pub(crate) fingerprint: u64, } +/// Largest cache file either loader reads. A file beyond it is a foreign +/// or damaged one, not an allocation request: the loaders check the size +/// before reading and bound the read itself, so a miss costs a `stat`. +pub(crate) const MAX_BYTES: u64 = 256 * 1024 * 1024; + +/// Write `bytes` to `path` so that readers see either the previous file +/// or the whole new one, never a partial write. The temporary file +/// carries a fresh identifier: two processes recording the same cache +/// would otherwise interleave their writes into one sibling file, and a +/// crash would strand a partial file exactly where the next writer looks. +pub(crate) fn write_atomically(path: &Path, bytes: &[u8]) -> io::Result<()> { + if let Some(dir) = path.parent() { + std::fs::create_dir_all(dir)?; + } + let temporary = path.with_extension(format!("{}.tmp", Uuid::new_v4())); + let result = (|| { + std::fs::File::create(&temporary)?.write_all(bytes)?; + std::fs::rename(&temporary, path) + })(); + if result.is_err() { + let _ = std::fs::remove_file(&temporary); + } + result +} + +/// Read a cache file whole, refusing one past [`MAX_BYTES`]. +pub(crate) fn read_capped(path: &Path) -> Option> { + let file = std::fs::File::open(path).ok()?; + if file.metadata().ok()?.len() > MAX_BYTES { + return None; + } + let mut buf = Vec::new(); + file.take(MAX_BYTES + 1).read_to_end(&mut buf).ok()?; + (buf.len() as u64 <= MAX_BYTES).then_some(buf) +} + impl LibraryCache { - /// Serialize to `path` (atomically via a sibling temp file). + /// Serialize to `path`, atomically. pub fn save(&self, path: &Path) -> io::Result<()> { - if let Some(dir) = path.parent() { - std::fs::create_dir_all(dir)?; - } - let buf = self.to_bytes(); - let tmp = path.with_extension("tmp"); - std::fs::File::create(&tmp)?.write_all(&buf)?; - std::fs::rename(&tmp, path) + write_atomically(path, &self.to_bytes()) } /// The serialized form `save` writes — for hosts that carry the @@ -104,13 +146,24 @@ impl LibraryCache { buf.extend_from_slice(TOOLKIT_BUILD.as_bytes()); buf.extend_from_slice(&self.fingerprint.to_le_bytes()); buf.extend_from_slice(&(self.outcomes.len() as u64).to_le_bytes()); - for o in &self.outcomes { - match o { - Some(id) => { - buf.push(1); - buf.extend_from_slice(id.as_bytes()); + for (i, o) in self.outcomes.iter().enumerate() { + let misses = self.outcome_misses.get(i).map_or(&[][..], Vec::as_slice); + let tag = match (o, misses.is_empty()) { + (None, true) => 0, + (Some(_), true) => 1, + (None, false) => 2, + (Some(_), false) => 3, + }; + buf.push(tag); + if let Some(id) = o { + buf.extend_from_slice(id.as_bytes()); + } + if !misses.is_empty() { + buf.extend_from_slice(&(misses.len() as u32).to_le_bytes()); + for name in misses { + buf.extend_from_slice(&(name.len() as u32).to_le_bytes()); + buf.extend_from_slice(name.as_bytes()); } - None => buf.push(0), } } buf.extend_from_slice(&(self.lib_ids.len() as u64).to_le_bytes()); @@ -137,13 +190,11 @@ impl LibraryCache { buf } - /// Deserialize from `path`; `None` on any mismatch (missing file, other - /// toolkit build, truncation) — the caller then falls back to a cold - /// build and re-records. + /// Deserialize from `path`; `None` on any mismatch (missing file, + /// other toolkit build, truncation, a file past the cache size limit) + /// — the caller then falls back to a cold build and re-records. pub fn load(path: &Path) -> Option { - let mut buf = Vec::new(); - std::fs::File::open(path).ok()?.read_to_end(&mut buf).ok()?; - Self::from_bytes(&buf) + Self::from_bytes(&read_capped(path)?) } /// Deserialize [`Self::to_bytes`] output; `None` on any mismatch @@ -179,22 +230,47 @@ impl LibraryCache { return None; } let mut outcomes = Vec::with_capacity(count); + let mut outcome_misses = Vec::with_capacity(count); for _ in 0..count { - let (tag, r) = rest.split_first()?; - match tag { - 0 => { - outcomes.push(None); - rest = r; + let (tag, mut r) = rest.split_first()?; + if !matches!(tag, 0..=3) { + return None; + } + if tag & 1 == 1 { + if r.len() < 16 { + return None; } - 1 => { - if r.len() < 16 { + outcomes.push(Some(Uuid::from_bytes(r[..16].try_into().ok()?))); + r = &r[16..]; + } else { + outcomes.push(None); + } + let mut misses = Vec::new(); + if tag & 2 == 2 { + if r.len() < 4 { + return None; + } + let n = u32::from_le_bytes(r[..4].try_into().ok()?) as usize; + r = &r[4..]; + // Each name costs at least its length prefix. + if n > r.len() / 4 { + return None; + } + for _ in 0..n { + if r.len() < 4 { + return None; + } + let len = u32::from_le_bytes(r[..4].try_into().ok()?) as usize; + r = &r[4..]; + if r.len() < len { return None; } - outcomes.push(Some(Uuid::from_bytes(r[..16].try_into().ok()?))); - rest = &r[16..]; + misses.push(String::from_utf8(r[..len].to_vec()).ok()?); + r = &r[len..]; } - _ => return None, } + outcome_misses.push(misses); + rest = r; } fn take<'a>(rest: &mut &'a [u8], n: usize) -> Option<&'a [u8]> { if rest.len() < n { @@ -248,6 +324,7 @@ impl LibraryCache { } Some(LibraryCache { outcomes, + outcome_misses, fingerprint, lib_ids, lib_qnames, diff --git a/crates/sysmlv2-model/src/lift.rs b/crates/sysmlv2-model/src/lift.rs index b396efe..578e5bb 100644 --- a/crates/sysmlv2-model/src/lift.rs +++ b/crates/sysmlv2-model/src/lift.rs @@ -15,7 +15,7 @@ //! `emit(parse(print(lift(j)))) == j` for compact `j` emitted by this crate. use serde_json::{Map, Value}; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use sysmlv2_syntax::ast::*; use sysmlv2_syntax::span::Span; @@ -28,26 +28,60 @@ pub struct Lifted { pub errors: Vec, } +/// Why a payload could not be lifted at all. A problem inside an +/// otherwise well-formed payload may be reported in [`Lifted::errors`], +/// but a cycle or exhausted depth budget refuses the document: returning +/// a partial expression could change its value while still printing as +/// valid source. +/// +/// Non-exhaustive: a payload shape the lift cannot start on may be +/// recognised later, and naming one is not a breaking change. +#[derive(Clone, Debug, PartialEq, Eq)] +#[non_exhaustive] +pub enum LiftError { + /// The payload is not the flat array of elements KerML 10.4.6 + /// describes. + NotAnElementArray, + /// An entry of the array is not a JSON object. + NotAnElement, + /// An element carries no `@id`, so nothing can point at it. + ElementWithoutId, + /// Following the ownership graph would lose a subtree or operand. + Incomplete { errors: Vec }, +} + +impl std::fmt::Display for LiftError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + LiftError::NotAnElementArray => { + f.write_str("expected a flat JSON array of elements (KerML 10.4.6)") + } + LiftError::NotAnElement => f.write_str("expected every element to be a JSON object"), + LiftError::ElementWithoutId => f.write_str("element without @id"), + LiftError::Incomplete { errors } => { + write!( + f, + "cannot lift the document without data loss: {}", + errors.join("; ") + ) + } + } + } +} + +impl std::error::Error for LiftError {} + +impl From for String { + fn from(error: LiftError) -> String { + error.to_string() + } +} + /// Lift a compact-JSON element array into a syntax AST. -pub fn from_compact_json(value: &Value) -> Result { +pub fn from_compact_json(value: &Value) -> Result { from_compact_json_with_names(value, &HashMap::new()) } -/// Like [`from_compact_json`], with an extra `id → qualified-name segments` -/// table for references that point outside the document (e.g. the standard -/// library when the JSON was emitted with library resolution). -/// Split a multi-document element list into per-root-namespace chunks. -/// -/// Interchange JSON holds one root `Namespace` element per document (an -/// element of `@type` `Namespace` with no `owningRelationship`); every -/// other element is reachable from exactly one root through the ownership -/// closure (`ownedRelationship` on elements, `ownedRelatedElement` on -/// relationships). Returns one `(root_name, elements)` pair per root in -/// input order — `root_name` is the root's `qualifiedName`/`declaredName` -/// when present (the Flexo convention stores the source file name there). -/// `None` when the input has no root namespaces or when any element is -/// unreachable from every root (callers then treat the input as one -/// document). /// Qualified-name map over a whole element list: element `@id` → name /// segments, built by walking the ownership closure from each root /// namespace and collecting `declaredName`s. Feed it to @@ -89,6 +123,11 @@ pub fn document_name_map(value: &Value) -> std::collections::HashMap Option, Value)>> { let elements = value.as_array()?; let id_of = |e: &Value| e.get("@id").and_then(|v| v.as_str()).map(str::to_owned); @@ -273,21 +330,76 @@ pub fn split_documents(value: &Value) -> Option, Value)>> { ) } +/// Like [`from_compact_json`], with an extra `id → qualified-name segments` +/// table for references that point outside the document (e.g. the standard +/// library when the JSON was emitted with library resolution). pub fn from_compact_json_with_names( value: &Value, extra_names: &HashMap>, -) -> Result { +) -> Result { + // The lift recurses once per membership and owned definition or + // usage (expressions use a work stack), so its stack need is set by + // [`MAX_LIFT_DEPTH`] rather than by whichever thread called it (a + // language-server worker, a test thread), and it gets a thread of its + // own to carry that need. + // + // Only a payload that nests deeply enough to want one takes it: + // spawning costs several times what lifting a small document does, + // and anything lifting many documents would pay that per document. + // Depth decides it rather than size, because it is depth the stack + // answers for — and a payload that does nest deeply is never the + // small one the spawn would dominate. + // + // A target without threads, or a host that refuses one, lifts in + // place; the depth guard applies either way. + #[cfg(not(target_family = "wasm"))] + if value + .as_array() + .is_some_and(|items| nests_deeper_than(items, IN_PLACE_DEPTH)) + { + let spawned = std::thread::scope(|scope| { + std::thread::Builder::new() + .name("sysmlv2-lift".into()) + .stack_size(LIFT_STACK_BYTES) + .spawn_scoped(scope, || lift_document(value, extra_names)) + .map(std::thread::ScopedJoinHandle::join) + }); + match spawned { + Ok(Ok(lifted)) => return lifted, + Ok(Err(panic)) => std::panic::resume_unwind(panic), + Err(_) => {} + } + } + lift_document(value, extra_names) +} + +/// [`from_compact_json_with_names`] without moving the lift onto a stack +/// of its own: what a target without threads does, and what a caller +/// already holding a stack sized for [`MAX_LIFT_DEPTH`] steps can ask +/// for. The depth guard applies here too — this is the same lift, on the +/// calling thread. +pub fn from_compact_json_on_this_stack( + value: &Value, + extra_names: &HashMap>, +) -> Result { + lift_document(value, extra_names) +} + +fn lift_document( + value: &Value, + extra_names: &HashMap>, +) -> Result { let Value::Array(items) = value else { - return Err("expected a flat JSON array of elements (KerML 10.4.6)".into()); + return Err(LiftError::NotAnElementArray); }; let mut by_id: HashMap<&str, El> = HashMap::new(); let mut order: Vec<&str> = Vec::new(); for item in items { let Value::Object(el) = item else { - return Err("expected every element to be a JSON object".into()); + return Err(LiftError::NotAnElement); }; let Some(id) = el.get("@id").and_then(|v| v.as_str()) else { - return Err("element without @id".into()); + return Err(LiftError::ElementWithoutId); }; by_id.insert(id, el); order.push(id); @@ -317,6 +429,11 @@ pub fn from_compact_json_with_names( next_featuring: true, body_featuring: false, errors: Vec::new(), + reported: HashSet::new(), + depth_reported: HashSet::new(), + in_progress: HashSet::new(), + depth: 0, + incomplete: false, }; lifter.dialect = lifter.detect_dialect(); lifter.compute_qnames(&order); @@ -359,6 +476,11 @@ pub fn from_compact_json_with_names( } } } + if lifter.incomplete { + return Err(LiftError::Incomplete { + errors: lifter.errors, + }); + } Ok(Lifted { unit: SourceUnit { dialect: lifter.dialect, @@ -532,6 +654,110 @@ const KERML_MARKERS: &[&str] = &[ "MetadataFeature", ]; +/// The most lift steps one ownership path may take: a step is a +/// membership or the package, definition or usage it owns. Expressions +/// use an iterative walk with a separate bound. Ownership pointers come from the payload, so a +/// chain that loops back on itself or nests without bound must end in an +/// error rather than exhaust the stack. A nesting level of written +/// notation costs two steps (its membership and the member). The parser +/// can accept a leaf member inside its deepest body, hence the extra pair. +pub const MAX_LIFT_DEPTH: usize = 2 * (sysmlv2_syntax::parser::MAX_NESTING as usize + 1); + +/// Expressions are walked without recursive stack frames, but their AST +/// consumers still need a bound. Match the parser's operator budget plus +/// its leaf operand; expression bodies retain the structural budget. +pub const MAX_LIFT_EXPR_DEPTH: usize = sysmlv2_syntax::parser::MAX_EXPR_OPERATORS as usize + 1; + +/// Stack reserved for the lift thread: enough for [`MAX_LIFT_DEPTH`] +/// steps in an unoptimized build, where one step costs up to about +/// 190 KiB (an optimized build needs a twentieth of that). Reserved +/// address space only — pages are committed as the recursion touches +/// them. +#[cfg(not(target_family = "wasm"))] +const LIFT_STACK_BYTES: usize = 128 << 20; + +/// The deepest payload lifted on the caller's own stack. +/// +/// Measured against the two megabytes a thread gets when it asks for +/// none, in an unoptimized build, where a step is at its most +/// expensive. That is the smallest stack a caller can be on: one that +/// parses has already reserved a larger one for the parser's own bound +/// (`sysmlv2_syntax::parser::MAX_NESTING_STACK_BYTES`), and a caller +/// that only lifts need not have. Past this the payload could nest +/// toward [`MAX_LIFT_DEPTH`], which needs a stack sized for it; a +/// nesting level of written notation costs two steps, so this is eight +/// levels of braces. +#[cfg(not(target_family = "wasm"))] +const IN_PLACE_DEPTH: usize = 16; + +/// Whether the payload's ownership pointers reach more than `limit` steps +/// below a root — the question [`from_compact_json_with_names`] decides +/// by, answered in one pass without recursing and without lifting +/// anything. +/// +/// A payload whose ownership is not a forest — an element owned twice, a +/// cycle, an element with no `@id` — counts as deep: the lift's own +/// guards handle those, and a stack sized for the bound is what they need +/// to reach. +#[cfg(not(target_family = "wasm"))] +fn nests_deeper_than(items: &[Value], limit: usize) -> bool { + // A step enters an element no step on the path has entered, so a + // payload of at most `limit` elements cannot nest past `limit`. This + // is the common case and it costs nothing to answer. + if items.len() <= limit { + return false; + } + fn owned_ids(el: &Value) -> impl Iterator { + ["ownedRelationship", "ownedRelatedElement"] + .into_iter() + .filter_map(|key| el.get(key)) + .filter_map(Value::as_array) + .flatten() + .filter_map(|child| child.get("@id").and_then(Value::as_str)) + } + let mut by_id: HashMap<&str, &Value> = HashMap::with_capacity(items.len()); + for item in items { + let Some(id) = item.get("@id").and_then(Value::as_str) else { + return true; + }; + if by_id.insert(id, item).is_some() { + return true; + } + } + let mut owned: HashSet<&str> = HashSet::new(); + for item in items { + for child in owned_ids(item) { + if by_id.contains_key(child) && !owned.insert(child) { + return true; + } + } + } + let mut level: Vec<&str> = by_id + .keys() + .copied() + .filter(|id| !owned.contains(id)) + .collect(); + let mut seen: HashSet<&str> = level.iter().copied().collect(); + let mut depth = 0usize; + while !level.is_empty() { + depth += 1; + if depth > limit { + return true; + } + let mut next = Vec::new(); + for id in level { + for child in owned_ids(by_id[id]) { + if by_id.contains_key(child) && seen.insert(child) { + next.push(child); + } + } + } + level = next; + } + // Whatever no root reaches sits in a cycle. + seen.len() != by_id.len() +} + struct Lifter<'a> { by_id: HashMap<&'a str, El<'a>>, /// Dangling id → source spelling, from unresolved-reference recovery @@ -550,9 +776,74 @@ struct Lifter<'a> { /// a variant member inherits its variation's featuring. body_featuring: bool, errors: Vec, + /// The messages already in `errors`, so one condition met again and + /// again over a payload is recorded once. The list is read by a + /// person; its length should follow the payload's problems, not its + /// size. + reported: HashSet, + /// Roots of the subtrees already reported as truncated. Reaching the + /// bound truncates the subtree under the element the step was about to + /// enter; a later walk reaching the bound below one of these roots + /// truncates the same subtree again and is not reported twice, so the + /// list follows the number of subtrees the payload loses rather than + /// the number of elements in them — while a payload losing two + /// subtrees with nothing in common still says so twice. + depth_reported: HashSet<&'a str>, + /// Ids of the memberships, usages, definitions and expression + /// elements on the current lift path — re-entering one means the + /// payload's ownership pointers form a cycle. + in_progress: HashSet<&'a str>, + /// Lift steps on the current path (see [`MAX_LIFT_DEPTH`]). + depth: usize, + /// A structural failure must not escape as a successful partial AST. + incomplete: bool, } impl<'a> Lifter<'a> { + /// Record `message`, unless the same message is recorded already. + fn record(&mut self, message: String) { + if self.reported.insert(message.clone()) { + self.errors.push(message); + } + } + + /// Take one lift step into `id`. `None` — with an error recorded — + /// when the payload's ownership pointers loop back to an element + /// already being lifted or nest past [`MAX_LIFT_DEPTH`]; the caller + /// skips that subtree, diagnoses siblings, then refuses the document. + fn enter(&mut self, id: &'a str) -> Option<()> { + if self.depth >= MAX_LIFT_DEPTH { + self.incomplete = true; + // A walk that starts lower down the same chain reaches the + // bound again a little further along it and truncates inside a + // subtree already reported, which says nothing new; a payload + // that loses two subtrees with nothing in common says so + // twice. + let inside_reported = self + .depth_reported + .iter() + .any(|root| self.in_progress.contains(root)); + if !inside_reported && self.depth_reported.insert(id) { + self.record(format!( + "ownership nesting deeper than {MAX_LIFT_DEPTH} at {id}" + )); + } + return None; + } + if !self.in_progress.insert(id) { + self.incomplete = true; + self.record(format!("ownership cycle through {id}")); + return None; + } + self.depth += 1; + Some(()) + } + + fn leave(&mut self, id: &'a str) { + self.in_progress.remove(id); + self.depth -= 1; + } + fn detect_dialect(&self) -> Dialect { for el in self.by_id.values() { if KERML_MARKERS.contains(&ty(el)) { @@ -594,6 +885,19 @@ impl<'a> Lifter<'a> { /// for unnamed features — the effective name taken from the first /// referenced or redefined feature (KerML 8.2.3.5 / SysML reference /// forms), mirroring the emitter's scope registration. + /// + /// One naming rule, four representations — an element is named by + /// its declaration, else by its *naming feature*: the first feature + /// it redefines, else the one it references, else the last link of + /// its chain, each followed transitively. The implementations are + /// this one (over payload JSON), `json::Builder::graph_effective_name` + /// (over the lowered element graph, where `Builder::effective_name` + /// is the declaration-only half), `full::effective_name_of` (over the + /// full form's element maps, which also derives the positional + /// implied names), and the fixpoint inside `ids::walk` (over a + /// compact payload, for id segments). They agree by construction and + /// by the differential test in the round-trip gate; a change to one + /// belongs in all of them. fn effective_name(&self, el: El<'a>, depth: usize) -> Option { // A binary connector-family end is findable only as `source`/ // `target` (its implied redefinition of the BinaryConnection ends — @@ -707,29 +1011,43 @@ impl<'a> Lifter<'a> { if let Some(cached) = self.qnames.get(id) { return cached.clone(); } - // Placeholder guards cycles. - self.qnames.insert(id, None); - // An id outside the document (library reference, dangling patched - // @ref) has no in-document qualified name — callers fall through - // to `extra_names` / recovery spellings. - let &el = self.by_id.get(id)?; - let result = (|| { - let own = self.effective_name(el, 0)?; + // Walk the owner chain up to the nearest named ancestor, a root, + // or a cycle, then name downward — iteratively, so a deep chain + // costs no stack. A placeholder entry guards cycles; an id outside + // the document (library reference, dangling patched @ref) has no + // in-document qualified name — callers fall through to + // `extra_names` / recovery spellings. + let mut chain: Vec<(&'a str, El<'a>)> = Vec::new(); + let mut cur = id; + let base: Option> = loop { + if let Some(cached) = self.qnames.get(cur) { + break cached.clone(); + } + self.qnames.insert(cur, None); + let Some(&el) = self.by_id.get(cur) else { + break None; + }; + chain.push((cur, el)); match self.owner_of(el) { - None => Some(vec![own]), + None => break Some(Vec::new()), Some(owner) if ty(owner) == "Namespace" && self.owner_of(owner).is_none() => { - Some(vec![own]) - } - Some(owner) => { - let owner_id: &'a str = id_of(owner); - let mut path = self.qname_of(owner_id)?; - path.push(own); - Some(path) + break Some(Vec::new()); } + Some(owner) => cur = id_of(owner), } - })(); - self.qnames.insert(id, result.clone()); - result + }; + let mut path = base; + for (cid, el) in chain.into_iter().rev() { + path = match (path, self.effective_name(el, 0)) { + (Some(mut p), Some(own)) => { + p.push(own); + Some(p) + } + _ => None, + }; + self.qnames.insert(cid, path.clone()); + } + path } /// Whether `el` carries materialized derived properties (a full-form @@ -867,7 +1185,7 @@ impl<'a> Lifter<'a> { if let Some(name) = self.unresolved_names.get(id) { return Some(target_from_ref_string(name)); } - self.errors.push(format!( + self.record(format!( "cannot name reference target {id} (element outside document?)" )); // Even unnameable, the reference must not silently vanish from @@ -966,8 +1284,7 @@ impl<'a> Lifter<'a> { leading_then = true; leading_then_multiplicity = self .lift_connector_end(rels[0]) - .and_then(|e| e.multiplicity) - .map(Box::new); + .and_then(|e| e.multiplicity); continue; } } @@ -1075,7 +1392,57 @@ impl<'a> Lifter<'a> { } } + /// An Annotation owned by the annotated element that owns its + /// annotating element lifts that element as a member; an annotating + /// element with `about` targets of its own keeps the owner among them. + #[inline(never)] + fn lift_prefix_annotation(&mut self, rel: El<'a>, vis: Option) -> Option { + let Some(el) = self + .first_related(rel) + .filter(|el| crate::metaclass::conforms(ty(el), "AnnotatingElement")) + else { + self.errors + .push("unsupported member relationship @type Annotation".to_string()); + return None; + }; + let in_type = self.owner_is_type(rel); + let mut member = self.lift_owning_member_element(el, vis, in_type)?; + // An annotating element with `about` targets of its own + // annotates only those; the owner it also annotated in this + // shape joins the targets so nothing is lost. + let owner = match self.target(rel, "owningRelatedElement") { + Some(TargetRef::Name(qn)) => Some(qn), + _ => None, + }; + match &mut member.kind { + MemberKind::Comment(c) if !c.about.is_empty() => { + if let Some(owner) = owner { + c.about.insert(0, owner); + } + } + MemberKind::Usage(u) => { + if let UsageDetail::Metadata { about } = &mut u.detail { + if !about.is_empty() { + if let Some(owner) = owner { + about.insert(0, owner); + } + } + } + } + _ => {} + } + Some(member) + } + fn lift_member(&mut self, rel: El<'a>) -> Option { + let id = id_of(rel); + self.enter(id)?; + let member = self.lift_member_inner(rel); + self.leave(id); + member + } + + fn lift_member_inner(&mut self, rel: El<'a>) -> Option { let vis = Self::visibility(rel); // The visibility indicator is mandatory on imports (`ImportPrefix`), // so a public import must print explicitly — unlike other members, @@ -1148,6 +1515,15 @@ impl<'a> Lifter<'a> { let in_type = self.owner_is_type(rel); self.lift_owning_member_element(el, vis, in_type) } + // The prefix-annotation shape (KerML `ownedAnnotatingElement`): + // the annotated element owns the Annotation, which owns the + // annotating element — a body comment, documentation or + // metadata of the owner, exactly what the owning-membership + // shape spells. + // The prefix-annotation shape (KerML `ownedAnnotatingElement`): + // out of line, because this function recurses through every + // member and its frame must stay small. + "Annotation" => self.lift_prefix_annotation(rel, vis), "FeatureMembership" | "EndFeatureMembership" => { let el = self.first_related(rel)?; let usage = self.lift_usage(el, false)?; @@ -1266,8 +1642,7 @@ impl<'a> Lifter<'a> { )) } other => { - self.errors - .push(format!("unsupported member relationship @type {other}")); + self.record(format!("unsupported member relationship @type {other}")); None } } @@ -1297,9 +1672,14 @@ impl<'a> Lifter<'a> { let t = ty(el); // Packages / namespaces. if matches!(t, "Package" | "LibraryPackage" | "Namespace") { + // The only owned element whose body is lifted here rather + // than through `lift_definition` / `lift_usage`, so this is + // where its own step is counted. + self.enter(id_of(el))?; let rels = self.owned_rels(el); let (metadata, rest) = self.take_prefix_metadata(&rels); let members = self.lift_members(&rest); + self.leave(id_of(el)); return Some(Self::member( vis, MemberKind::Package(Package { @@ -1465,7 +1845,7 @@ impl<'a> Lifter<'a> { } } } - let range = self.bounds_to_multiplicity(bounds); + let range = self.bounds_to_multiplicity(bounds).map(|m| *m); return Some(Self::member( vis, MemberKind::MultiplicityDecl(MultiplicityDecl { @@ -1497,8 +1877,7 @@ impl<'a> Lifter<'a> { usage.prefix.is_type_member = owner_is_type && self.dialect == Dialect::Kerml; return Some(Self::member(vis, MemberKind::Usage(usage))); } - self.errors - .push(format!("unsupported owned element @type {t}")); + self.record(format!("unsupported owned element @type {t}")); None } @@ -1530,21 +1909,21 @@ impl<'a> Lifter<'a> { (metadata, rest) } - fn bounds_to_multiplicity(&mut self, mut bounds: Vec) -> Option { + fn bounds_to_multiplicity(&self, mut bounds: Vec) -> Option> { match bounds.len() { - 1 => Some(Multiplicity { + 1 => Some(Box::new(Multiplicity { lower: None, upper: bounds.pop().unwrap(), span: Span::default(), - }), + })), 2 => { let upper = bounds.pop().unwrap(); let lower = bounds.pop().unwrap(); - Some(Multiplicity { + Some(Box::new(Multiplicity { lower: Some(lower), upper, span: Span::default(), - }) + })) } _ => None, } @@ -1553,6 +1932,14 @@ impl<'a> Lifter<'a> { // ---- definitions ---- fn lift_definition(&mut self, el: El<'a>, kind: DefKind) -> Option { + let id = id_of(el); + self.enter(id)?; + let definition = self.lift_definition_inner(el, kind); + self.leave(id); + definition + } + + fn lift_definition_inner(&mut self, el: El<'a>, kind: DefKind) -> Option { let rels = self.owned_rels(el); let (metadata, rels) = self.take_prefix_metadata(&rels); let mut specializes = Vec::new(); @@ -1676,8 +2063,16 @@ impl<'a> Lifter<'a> { // ---- usages ---- - #[allow(clippy::too_many_lines)] fn lift_usage(&mut self, el: El<'a>, is_variant: bool) -> Option { + let id = id_of(el); + self.enter(id)?; + let usage = self.lift_usage_inner(el, is_variant); + self.leave(id); + usage + } + + #[allow(clippy::too_many_lines)] + fn lift_usage_inner(&mut self, el: El<'a>, is_variant: bool) -> Option { let t = ty(el); let featuring = std::mem::replace(&mut self.next_featuring, true); let kind = usage_kind_of(t, self.dialect).unwrap_or(UsageKind::Default); @@ -1984,6 +2379,23 @@ impl<'a> Lifter<'a> { "OwningMembership" => { let inner = self.first_related(rel); match inner.map(ty) { + // A chain source (`first a.b`): the membership owns + // the synthesized chain feature and names it as its + // member. + Some("Feature") + if kind == UsageKind::Transition + && transition_source.is_none() + && self + .owned_rels(inner.unwrap()) + .iter() + .any(|r| ty(r) == "FeatureChaining") => + { + // `memberElement` is derived on an + // OwningMembership; a producer may omit it. + transition_source = self + .target(rel, "memberElement") + .or_else(|| self.lift_feature_chain(inner.unwrap())); + } Some("MultiplicityRange") if declaration.multiplicity.is_none() && Self::declared_name(inner.unwrap()).is_none() => @@ -2106,6 +2518,8 @@ impl<'a> Lifter<'a> { } body_rels.push(rel); } + // A plain-name source (`first s1`) rides a Membership; a + // chain source is handled with the OwningMemberships above. "Membership" if matches!(t, "TransitionUsage") && transition_source.is_none() => { transition_source = self.target(rel, "memberElement"); } @@ -2210,7 +2624,7 @@ impl<'a> Lifter<'a> { kind, declaration, detail, - value, + value: value.map(Box::new), is_parallel: bval(el, "isParallel"), body: if members.is_empty() { None @@ -2247,7 +2661,22 @@ impl<'a> Lifter<'a> { { UsageDetail::Connector { ends } } - UsageKind::Binding if !ends.is_empty() => UsageDetail::Binding { ends }, + UsageKind::Binding if ends.len() == 2 => UsageDetail::Binding { ends }, + UsageKind::Binding => { + // A binding connector binds exactly two ends; any other + // arity is a partial document — including none at all, + // which is what a minimally populated payload builds. + // Keep whatever ends are there visible as a plain + // connector detail so the text shows what is there, and + // report the arity either way: the printer's fallback + // spelling relies on that report having been made. + self.record(format!( + "binding connector {} has {} end(s), expected two", + id_of(el), + ends.len() + )); + UsageDetail::Connector { ends } + } UsageKind::Succession if !ends.is_empty() => { let mut ends = ends; if ends.len() >= 2 { @@ -2258,17 +2687,20 @@ impl<'a> Lifter<'a> { // its `then [1] x;` variant, kept in `source`). let source = if source.name.is_none() && source.multiplicity.is_none() - && matches!(&source.target, TargetRef::Chain(links) if links.is_empty()) + && source.target.is_unspelled() { None } else { Some(source) }; - UsageDetail::Succession { source, target } + UsageDetail::Succession { + source: source.map(Box::new), + target: Box::new(target), + } } else { UsageDetail::Succession { source: None, - target: ends.remove(0), + target: Box::new(ends.remove(0)), } } } @@ -2284,7 +2716,7 @@ impl<'a> Lifter<'a> { (None, None) }; UsageDetail::Flow { - payload: flow_payload, + payload: flow_payload.map(Box::new), source: s, target: tt, } @@ -2301,9 +2733,9 @@ impl<'a> Lifter<'a> { UsageKind::Transition => UsageDetail::Transition { source, trigger, - guard, + guard: guard.map(Box::new), effect, - target, + target: target.map(Box::new), is_default: false, }, UsageKind::Accept => { @@ -2338,9 +2770,9 @@ impl<'a> Lifter<'a> { } } UsageDetail::Accept { - payload: payload_part.unwrap_or_default(), - trigger: trigger_part, - via, + payload: Box::new(payload_part.unwrap_or_default()), + trigger: trigger_part.map(Box::new), + via: via.map(Box::new), } } UsageKind::Send => { @@ -2357,7 +2789,11 @@ impl<'a> Lifter<'a> { let to = slots.pop().unwrap(); let via = slots.pop().unwrap(); let payload = slots.pop().unwrap(); - UsageDetail::Send { payload, via, to } + UsageDetail::Send { + payload: payload.map(Box::new), + via: via.map(Box::new), + to: to.map(Box::new), + } } UsageKind::Assign => { let mut exprs = Vec::new(); @@ -2371,7 +2807,10 @@ impl<'a> Lifter<'a> { if exprs.len() == 2 { let value = exprs.pop().unwrap(); let target = exprs.pop().unwrap(); - UsageDetail::Assign { target, value } + UsageDetail::Assign { + target: Box::new(target), + value: Box::new(value), + } } else { UsageDetail::None } @@ -2385,7 +2824,9 @@ impl<'a> Lifter<'a> { } } } - UsageDetail::Terminate { target } + UsageDetail::Terminate { + target: target.map(Box::new), + } } UsageKind::IfNode => { let mut cond = None; @@ -2407,10 +2848,10 @@ impl<'a> Lifter<'a> { Box::new(bodies.remove(0)) }; UsageDetail::IfNode { - cond: cond.unwrap_or(Expr { + cond: Box::new(cond.unwrap_or_else(|| Expr { kind: ExprKind::Null, span: Span::default(), - }), + })), then_body, else_body: if bodies.is_empty() { None @@ -2439,7 +2880,11 @@ impl<'a> Lifter<'a> { } } match body { - Some(body) => UsageDetail::WhileLoop { cond, body, until }, + Some(body) => UsageDetail::WhileLoop { + cond: cond.map(Box::new), + body, + until: until.map(Box::new), + }, None => UsageDetail::None, } } @@ -2458,7 +2903,11 @@ impl<'a> Lifter<'a> { } } match (seq, body) { - (Some(seq), Some(body)) => UsageDetail::ForLoop { var, seq, body }, + (Some(seq), Some(body)) => UsageDetail::ForLoop { + var: Box::new(var), + seq: Box::new(seq), + body, + }, _ => UsageDetail::None, } } @@ -2551,7 +3000,7 @@ impl<'a> Lifter<'a> { Some(ConnectorEnd { multiplicity, name: sval(el, "declaredName").map(name), - target: target.unwrap_or(TargetRef::Chain(Vec::new())), + target: target.unwrap_or_else(TargetRef::unspelled), }) } @@ -2623,10 +3072,10 @@ impl<'a> Lifter<'a> { "FeatureValue" => { if let Some(ex) = self.first_related(rel) { if let Some(expr) = self.lift_expr(ex) { - payload.value = Some(FeatureValue { + payload.value = Some(Box::new(FeatureValue { kind: ValueKind::Bound, expr, - }); + })); } } } @@ -2639,6 +3088,119 @@ impl<'a> Lifter<'a> { // ---- expressions ---- fn lift_expr(&mut self, el: El<'a>) -> Option { + // Postorder on an explicit work stack: even a left-associated + // operator chain consumes no recursive lift frames. Each occurrence + // is evaluated separately, so shared payload operands keep their + // position without cloning an ever-growing expression subtree. + enum Work<'a> { + Enter(El<'a>, usize), + Finish(El<'a>, usize), + } + let mut work = vec![Work::Enter(el, 0)]; + let mut values = Vec::new(); + while let Some(step) = work.pop() { + match step { + Work::Enter(el, depth) => { + let id = id_of(el); + if depth >= MAX_LIFT_EXPR_DEPTH { + self.incomplete = true; + self.record(format!( + "expression nesting deeper than {MAX_LIFT_EXPR_DEPTH} at {id}" + )); + values.push(None); + continue; + } + if !self.in_progress.insert(id) { + self.incomplete = true; + self.record(format!("ownership cycle through {id}")); + values.push(None); + continue; + } + let children = self.expression_children(el); + work.push(Work::Finish(el, children.len())); + work.extend( + children + .into_iter() + .rev() + .map(|child| Work::Enter(child, depth + 1)), + ); + } + Work::Finish(el, count) => { + let children = values.split_off(values.len() - count); + let missing = children.iter().any(Option::is_none); + let implicit_subject = ty(el) == "OperatorExpression" + && matches!( + sval(el, "operator"), + Some("istype" | "hastype" | "@" | "@@" | "as" | "meta") + ); + let expr = if missing && !implicit_subject { + None + } else { + self.lift_expr_inner(el, &mut children.into_iter()) + }; + // An implicit subject is the one intentional empty + // expression: classification operators read it as self. + let self_reference = ty(el) == "FeatureReferenceExpression" + && self + .owned_rels(el) + .iter() + .any(|r| ty(r) == "ReturnParameterMembership"); + if expr.is_none() && !self_reference && !self.incomplete { + self.incomplete = true; + self.record(format!( + "cannot lift expression {} at {}", + ty(el), + id_of(el) + )); + } + self.in_progress.remove(id_of(el)); + values.push(expr); + } + } + } + values.pop().flatten() + } + + /// Children in precisely the order the expression assembler consumes + /// them. Parameter wrappers and type-reference parameters add no AST + /// depth. An expression body goes through the bounded member lifter. + fn expression_children(&mut self, el: El<'a>) -> Vec> { + match ty(el) { + "FeatureReferenceExpression" => { + for rel in self.owned_rels(el) { + if ty(rel) == "ReturnParameterMembership" { + continue; + } + if self.target(rel, "memberElement").is_some() { + break; + } + if let Some(inner) = self.first_related(rel) { + return vec![inner]; + } + } + Vec::new() + } + "FeatureChainExpression" + | "IndexExpression" + | "CollectExpression" + | "SelectExpression" + | "InvocationExpression" + | "ConstructorExpression" + | "OperatorExpression" => self + .owned_rels(el) + .into_iter() + .filter(|rel| ty(rel) == "ParameterMembership") + .filter_map(|rel| self.param_expr_el(rel)) + .collect(), + _ => Vec::new(), + } + } + + fn lift_expr_inner( + &mut self, + el: El<'a>, + children: &mut std::vec::IntoIter>, + ) -> Option { let mk = |kind: ExprKind| { Some(Expr { kind, @@ -2659,17 +3221,30 @@ impl<'a> Lifter<'a> { mk(ExprKind::Literal(Literal::Integer(raw))) } "LiteralRational" => { - let raw = match el.get("value") { - Some(Value::Number(n)) => { - let s = n.to_string(); - // A real literal must contain a fraction or exponent. - if s.contains('.') || s.contains('e') || s.contains('E') { - s - } else { - format!("{s}.0") - } + // A real literal must contain a fraction or exponent. + // The value is a JSON number when a double denotes it + // exactly and the written text otherwise (a decimal with + // more digits than a double holds, an exponent past its + // range); both spellings read back the same way. + // The fraction is appended only to a written whole + // number. A value the payload spells some other way — a + // rational's `1/3`, say — is kept verbatim: appending to + // it changes what it denotes, and `1/3.0` reads back as a + // division by a different number. + let whole = |s: &str| { + let digits = s.strip_prefix(['+', '-']).unwrap_or(s); + !digits.is_empty() && digits.bytes().all(|b| b.is_ascii_digit()) + }; + let real = |s: &str| { + if whole(s) { + format!("{s}.0") + } else { + s.to_string() } - Some(Value::String(s)) => s.clone(), + }; + let raw = match el.get("value") { + Some(Value::Number(n)) => real(&n.to_string()), + Some(Value::String(s)) => real(s), _ => "0.0".to_string(), }; mk(ExprKind::Literal(Literal::Real(raw))) @@ -2687,8 +3262,8 @@ impl<'a> Lifter<'a> { return Some(target_to_expr(target)); } // Nested expression member (lazy operand wrapper). - if let Some(inner) = self.first_related(rel) { - return self.lift_expr(inner); + if self.first_related(rel).is_some() { + return children.next().flatten(); } } None @@ -2707,8 +3282,8 @@ impl<'a> Lifter<'a> { for rel in self.owned_rels(el) { match ty(rel) { "ParameterMembership" => { - if let Some(inner) = self.param_expr_el(rel) { - target_expr = self.lift_expr(inner); + if self.param_expr_el(rel).is_some() { + target_expr = children.next().flatten(); } } "Membership" | "OwningMembership" => { @@ -2723,7 +3298,7 @@ impl<'a> Lifter<'a> { }) } "IndexExpression" => { - let ops = self.operands(el); + let ops = children.by_ref().flatten().collect::>(); let mut it = ops.into_iter(); mk(ExprKind::Index { target: Box::new(it.next()?), @@ -2732,7 +3307,7 @@ impl<'a> Lifter<'a> { } "CollectExpression" | "SelectExpression" => { let is_select = ty(el) == "SelectExpression"; - let ops = self.operands(el); + let ops = children.by_ref().flatten().collect::>(); let mut it = ops.into_iter(); let target = Box::new(it.next()?); let body = Box::new(it.next()?); @@ -2748,7 +3323,11 @@ impl<'a> Lifter<'a> { let mut args = Vec::new(); for rel in self.owned_rels(el) { match ty(rel) { - "Membership" => fn_ty = self.target(rel, "memberElement"), + // A chained callee (`a.b(x)`) rides an + // OwningMembership owning the chain feature. + "Membership" | "OwningMembership" => { + fn_ty = self.target(rel, "memberElement") + } "FeatureMembership" => { fnref = self.target(rel, "memberElement").and_then(|t| match t { TargetRef::Name(qn) => Some(qn), @@ -2788,8 +3367,8 @@ impl<'a> Lifter<'a> { } } } - if let Some(inner) = self.param_expr_el(rel) { - if let Some(value) = self.lift_expr(inner) { + if self.param_expr_el(rel).is_some() { + if let Some(value) = children.next().flatten() { args.push(Arg { name: arg_name, value, @@ -2804,7 +3383,7 @@ impl<'a> Lifter<'a> { let ty_target = fn_ty?; if ty(el) == "ConstructorExpression" { return mk(ExprKind::Constructor { - ty: ty_target, + ty: Box::new(ty_target), args, }); } @@ -2814,44 +3393,33 @@ impl<'a> Lifter<'a> { let target = it.next()?.value; return mk(ExprKind::Arrow { target: Box::new(target), - ty: ty_target, + ty: Box::new(ty_target), args: ArrowArgs::FunctionRef(f), }); } mk(ExprKind::Invocation { - ty: ty_target, + ty: Box::new(ty_target), args, }) } - "OperatorExpression" => self.lift_operator_expr(el), + "OperatorExpression" => self.lift_operator_expr(el, children), "Expression" => { let rels = self.owned_rels(el); let members = self.lift_members(&rels); mk(ExprKind::Body { members }) } other => { - self.errors - .push(format!("unsupported expression @type {other}")); + self.record(format!("unsupported expression @type {other}")); None } } } - fn operands(&mut self, el: El<'a>) -> Vec { - let mut ops = Vec::new(); - for rel in self.owned_rels(el) { - if ty(rel) == "ParameterMembership" { - if let Some(inner) = self.param_expr_el(rel) { - if let Some(e) = self.lift_expr(inner) { - ops.push(e); - } - } - } - } - ops - } - - fn lift_operator_expr(&mut self, el: El<'a>) -> Option { + fn lift_operator_expr( + &mut self, + el: El<'a>, + children: &mut std::vec::IntoIter>, + ) -> Option { let op = sval(el, "operator").unwrap_or(""); let mk = |kind: ExprKind| { Some(Expr { @@ -2884,7 +3452,7 @@ impl<'a> Lifter<'a> { ty_target = self.target(rel, "memberElement"); } } - let ops = self.operands(el); + let ops = children.by_ref().flatten().collect::>(); if op == "if" { let mut it = ops.into_iter(); @@ -2898,7 +3466,9 @@ impl<'a> Lifter<'a> { return mk(ExprKind::Sequence(ops)); } if op == "all" { - return mk(ExprKind::Extent { ty: ty_target? }); + return mk(ExprKind::Extent { + ty: Box::new(ty_target?), + }); } if op == "[" { let mut it = ops.into_iter(); @@ -2933,7 +3503,7 @@ impl<'a> Lifter<'a> { return mk(ExprKind::Classification { op: cop, operand, - ty: ty_target?, + ty: Box::new(ty_target?), }); } if ops.len() == 1 { @@ -2976,7 +3546,7 @@ impl<'a> Lifter<'a> { "**" => BinaryOp::Pow, "^" => BinaryOp::Caret, other => { - self.errors.push(format!("unknown operator {other:?}")); + self.record(format!("unknown operator {other:?}")); return None; } }; @@ -3119,3 +3689,195 @@ pub(crate) fn usage_kind_of(t: &str, dialect: Dialect) -> Option { _ => return None, }) } + +#[cfg(test)] +mod tests { + use super::*; + + /// A chain of `depth` parts, each owned by the one above through a + /// membership: the shape whose ownership pointers the lift follows. + fn chain(depth: usize) -> Vec { + chain_named("", depth) + } + + /// The same chain with every id under `prefix`, so two of them are + /// independent subtrees of one payload. + /// + /// Ownership is spelled both ways round, as a payload spells it: the + /// chain then has the one root it reads as, rather than as many roots + /// as it has elements. + fn chain_named(prefix: &str, depth: usize) -> Vec { + let mut items = Vec::new(); + for i in 0..depth { + let mut membership = serde_json::json!({ + "@id": format!("{prefix}m{i}"), + "@type": "OwningMembership", + "ownedRelatedElement": [{ "@id": format!("{prefix}p{i}") }], + }); + if i > 0 { + membership["owningRelatedElement"] = + serde_json::json!({ "@id": format!("{prefix}p{}", i - 1) }); + } + items.push(membership); + let owned = if i + 1 < depth { + serde_json::json!([{ "@id": format!("{prefix}m{}", i + 1) }]) + } else { + serde_json::json!([]) + }; + items.push(serde_json::json!({ + "@id": format!("{prefix}p{i}"), + "@type": "PartUsage", + "declaredName": format!("{prefix}p{i}"), + "owningRelationship": { "@id": format!("{prefix}m{i}") }, + "ownedRelationship": owned, + })); + } + items + } + + /// The decision that keeps a small document off a thread of its own + /// reads the payload's depth, not its size: a wide document stays in + /// place however many elements it holds, and a deep one does not. + #[test] + fn the_in_place_decision_follows_the_payload_depth() { + // Two steps per level, so the chain crosses the bound at half of + // it. + assert!(!nests_deeper_than(&chain(4), IN_PLACE_DEPTH)); + assert!(nests_deeper_than(&chain(IN_PLACE_DEPTH), IN_PLACE_DEPTH)); + + // Many siblings under one owner is one level, whatever the count. + let mut wide = vec![serde_json::json!({ + "@id": "root", + "@type": "Namespace", + "ownedRelationship": (0..500) + .map(|i| serde_json::json!({ "@id": format!("m{i}") })) + .collect::>(), + })]; + for i in 0..500 { + wide.push(serde_json::json!({ + "@id": format!("m{i}"), + "@type": "OwningMembership", + "ownedRelatedElement": [], + })); + } + assert!(!nests_deeper_than(&wide, IN_PLACE_DEPTH)); + + // A payload whose ownership is not a forest takes the stack the + // lift's own guards need to report it. + let cycle = vec![ + serde_json::json!({ + "@id": "a", "@type": "OwningMembership", + "ownedRelatedElement": [{ "@id": "b" }], + }), + serde_json::json!({ + "@id": "b", "@type": "PartUsage", + "ownedRelationship": [{ "@id": "a" }], + }), + ]; + assert!(nests_deeper_than(&cycle, 1)); + } + + /// The deepest payload the lift takes in place fits the smallest + /// stack an ordinary caller runs on: a worker thread given one + /// megabyte. Overflowing here would end the process rather than + /// report anything, so the bound is measured by lifting that payload + /// on such a thread — in an unoptimized build, where a step costs the + /// most. + #[test] + fn the_deepest_in_place_payload_fits_a_small_stack() { + // Two steps per level of nesting, so the deepest chain taken in + // place is half the step bound. + let items = chain(IN_PLACE_DEPTH / 2); + assert!(!nests_deeper_than(&items, IN_PLACE_DEPTH)); + let lifted = std::thread::Builder::new() + .stack_size(1 << 20) + .spawn(move || from_compact_json(&Value::Array(items))) + .unwrap() + .join() + .unwrap() + .expect("a well-formed payload lifts"); + assert!(lifted.errors.is_empty(), "{:?}", lifted.errors); + } + + /// A payload nesting past the bound is reported rather than followed, + /// and reported once however far past it goes. + #[test] + fn nesting_past_the_bound_is_reported_once() { + let Err(LiftError::Incomplete { errors }) = + from_compact_json(&Value::Array(chain(MAX_LIFT_DEPTH * 2))) + else { + panic!("an over-budget document must not return a partial AST") + }; + assert_eq!( + errors + .iter() + .filter(|e| e.contains("ownership nesting deeper than")) + .count(), + 1, + "{:?}", + errors + ); + } + + /// Each truncated subtree is reported: two independent chains past the + /// bound lose their elements at two different places, and a reader + /// given one entry would take the other loss for elements the payload + /// never held. + #[test] + fn every_truncated_subtree_is_reported() { + let mut items = chain_named("a", MAX_LIFT_DEPTH * 2); + items.extend(chain_named("b", MAX_LIFT_DEPTH * 2)); + let Err(LiftError::Incomplete { errors }) = from_compact_json(&Value::Array(items)) else { + panic!("an over-budget document must not return a partial AST") + }; + let reports: Vec<&String> = errors + .iter() + .filter(|e| e.contains("ownership nesting deeper than")) + .collect(); + assert_eq!(reports.len(), 2, "{:?}", errors); + assert!( + reports.iter().any(|e| e.contains(" at am")) + && reports.iter().any(|e| e.contains(" at bm")), + "{reports:?}" + ); + } + + /// A binding connector with no ends at all is as much a partial + /// document as one with three, and it is what a minimally populated + /// payload builds. Its arity is reported, and the usage keeps the + /// plain connector detail the notation can still spell — a bare + /// binding has no spelling of its own. + #[test] + fn a_binding_with_no_ends_is_reported() { + let items = vec![ + serde_json::json!({ + "@id": "m0", + "@type": "OwningMembership", + "ownedRelatedElement": [{ "@id": "b0" }], + }), + serde_json::json!({ + "@id": "b0", + "@type": "BindingConnectorAsUsage", + "owningRelationship": { "@id": "m0" }, + "ownedRelationship": [], + }), + ]; + let lifted = from_compact_json(&Value::Array(items)).expect("a well-formed payload lifts"); + assert!( + lifted + .errors + .iter() + .any(|e| e.contains("binding connector b0 has 0 end(s), expected two")), + "{:?}", + lifted.errors + ); + let sysmlv2_syntax::ast::MemberKind::Usage(u) = &lifted.unit.members[0].kind else { + panic!("expected a usage: {:#?}", lifted.unit.members[0].kind) + }; + assert!( + matches!(&u.detail, UsageDetail::Connector { ends } if ends.is_empty()), + "{:?}", + u.detail + ); + } +} diff --git a/crates/sysmlv2-model/src/loader.rs b/crates/sysmlv2-model/src/loader.rs new file mode 100644 index 0000000..4c7468d --- /dev/null +++ b/crates/sysmlv2-model/src/loader.rs @@ -0,0 +1,317 @@ +//! Loading an interchange document into a model while keeping the ids +//! it carried. +//! +//! This toolkit's model derives every element id from the ownership +//! graph (IDS.md); a document from another producer, or one emitted under +//! other unit names, carries ids the derivation would replace. The loader +//! pairs the document's elements with the rebuilt model's by ownership +//! path and records the given ids as an **overlay** — applied to the +//! resolved model for the read API and to every emitted element array — +//! so a loaded document keeps its identity end to end. + +use crate::json::{ResolvedModel, model_to_compact_json}; +use crate::model::Model; +use serde_json::Value; +use std::collections::HashMap; +use uuid::Uuid; + +/// Explicit ids: graph-derived id → (the id the document carried, the +/// element's metaclass). +pub type ExplicitIds = HashMap; + +/// The explicit-id map of a loaded document: `(derived id → given id)` +/// for every element of `document` whose structural counterpart in the +/// rebuilt `model` derives a different id, plus the number of document +/// elements with no counterpart. Counterparts are paired by ownership +/// path (`ids::segment_paths`): roots by document order, then the +/// `ownedRelationship` / `ownedRelatedElement` positions and names — +/// the same walk the derivation uses, so a document this toolkit emitted +/// pairs completely and maps nothing. +pub fn explicit_id_map( + document: &Value, + model: &Model, + external: &dyn Fn(&str) -> Option, + warnings: &mut Vec, +) -> (ExplicitIds, usize) { + use crate::ids::segment_paths; + let emitted = model_to_compact_json(model); + let (doc_paths, model_paths) = match ( + segment_paths(document, external), + segment_paths(&emitted, external), + ) { + (Ok(d), Ok(m)) => (d, m), + (Err(e), _) | (_, Err(e)) => { + warnings.push(format!( + "the document's elements could not be paired with the model's; ids are not \ + preserved: {e}" + )); + return (HashMap::new(), 0); + } + }; + let id_at = |v: &Value, i: usize| -> Option { + v.get(i)? + .get("@id")? + .as_str() + .and_then(|s| Uuid::parse_str(s).ok()) + }; + let ty_at = |v: &Value, i: usize| -> String { + v.get(i) + .and_then(|e| e.get("@type")) + .and_then(|t| t.as_str()) + .unwrap_or("") + .to_string() + }; + // Paths carry the root's *element index*; key roots by their ordinal + // among roots instead, so a document whose elements are not in this + // toolkit's emission order still pairs root by root (roots are in + // document order on both sides — units are lifted in document order). + // Only document roots (`Namespace` elements) count for the ordinal + // when a payload has any, so a stray unowned element cannot shift + // the pairing of every document. + let ordinal_paths = + |paths: Vec>, arr: &Value| -> Vec> { + let all: std::collections::BTreeSet = + paths.iter().flatten().map(|(r, _)| *r).collect(); + let namespaces: Vec = all + .iter() + .copied() + .filter(|&r| ty_at(arr, r) == "Namespace") + .collect(); + let roots: Vec = if namespaces.is_empty() { + all.into_iter().collect() + } else { + namespaces + }; + paths + .into_iter() + .map(|p| p.and_then(|(r, chain)| roots.binary_search(&r).ok().map(|o| (o, chain)))) + .collect() + }; + let doc_paths = ordinal_paths(doc_paths, document); + let model_paths = ordinal_paths(model_paths, &emitted); + // A document whose root is not a document Namespace (a bare Package + // at the top, as other producers emit) is rebuilt under a synthetic + // root Namespace whose sole member it becomes: re-root the document's + // chains under that member so the pairing lines up. + let doc_root_is_namespace: Vec = { + let mut v = Vec::new(); + for (i, p) in doc_paths.iter().enumerate() { + if let Some((o, chain)) = p { + if chain.is_empty() { + if v.len() <= *o { + v.resize(*o + 1, true); + } + v[*o] = ty_at(document, i) == "Namespace"; + } + } + } + v + }; + let sole_member_chain: HashMap = { + // A named sole member chains past its membership (`::Name`); an + // unnamed one sits under a positional membership (`r0/e0`). + let mut per_root: HashMap> = HashMap::new(); + for p in model_paths.iter().flatten() { + if !p.1.is_empty() && !p.1.contains('/') { + per_root.entry(p.0).or_default().push(p.1.clone()); + } + } + per_root + .into_iter() + .filter_map(|(o, chains)| { + if chains.len() != 1 { + return None; + } + let c = &chains[0]; + if c.starts_with("::") { + Some((o, c.clone())) + } else { + let element = format!("{c}/e0"); + model_paths + .iter() + .flatten() + .any(|p| p.0 == o && p.1 == element) + .then_some((o, element)) + } + }) + .collect() + }; + let doc_paths: Vec> = doc_paths + .into_iter() + .map(|p| { + p.map(|(o, chain)| { + if doc_root_is_namespace.get(o).copied().unwrap_or(true) { + return (o, chain); + } + match sole_member_chain.get(&o) { + Some(c) if chain.is_empty() => (o, c.clone()), + Some(c) => (o, format!("{c}/{chain}")), + None => (o, chain), + } + }) + }) + .collect(); + let mut by_path: HashMap<(usize, String), (Uuid, String)> = HashMap::new(); + for (i, path) in model_paths.into_iter().enumerate() { + if let (Some(path), Some(id)) = (path, id_at(&emitted, i)) { + by_path.insert(path, (id, ty_at(&emitted, i))); + } + } + // Elements the lift deliberately drops are not "unpreserved": implied + // relationships and unresolved-reference recovery annotations (with + // their memberships) of a full-form document. + let recovery: std::collections::HashSet = document + .as_array() + .map(|a| { + let mut set = std::collections::HashSet::new(); + for e in a { + if e["language"] == crate::full::UNRESOLVED_REP_LANGUAGE { + if let Some(id) = e["@id"].as_str() { + set.insert(id.to_string()); + } + if let Some(m) = e["owningRelationship"]["@id"].as_str() { + set.insert(m.to_string()); + } + } + } + set + }) + .unwrap_or_default(); + let mut map = HashMap::new(); + let mut unmatched = 0usize; + for (i, path) in doc_paths.into_iter().enumerate() { + let Some(given) = id_at(document, i) else { + continue; + }; + let el = &document[i]; + if el["isImplied"] == true || recovery.contains(given.to_string().as_str()) { + continue; + } + let doc_ty = ty_at(document, i); + match path.and_then(|p| by_path.get(&p)) { + // Positional pairing is only trusted between elements of the + // same metaclass (a document that lists a feature's typing + // and value in the other order must not swap their ids). The + // one sanctioned change is the chain-target membership this + // toolkit now spells as an OwningMembership. + Some((derived, model_ty)) + if *model_ty == doc_ty + || (doc_ty == "Membership" && model_ty == "OwningMembership") => + { + if *derived != given { + let ty = crate::metaclass_name(model_ty).unwrap_or(""); + map.insert(*derived, (given, ty)); + } + } + _ => unmatched += 1, + } + } + (map, unmatched) +} + +/// Apply a session's explicit ids to an emitted element array: every +/// id the derivation produced is replaced by the id the document +/// carried (`@id`, `elementId`, and every reference), and a reference the +/// lift could only spell as a quoted id (`{"@ref": "''"}`) binds to +/// the element carrying that id. Emission re-lowers the session's text, +/// so the overlay is applied on every emission path; the resolved model +/// carries the same overlay for the read API. +pub fn overlay_explicit_ids(value: &mut Value, explicit_ids: &ExplicitIds) { + let text_map: HashMap = explicit_ids + .iter() + .map(|(d, (g, _))| (d.to_string(), g.to_string())) + .collect(); + fn remap(v: &mut Value, map: &HashMap) { + match v { + Value::Object(o) => { + for (k, x) in o.iter_mut() { + if (k == "@id" + || k == "elementId" + || k == "memberElementId" + || k == "ownedMemberElementId") + && x.is_string() + { + if let Some(n) = map.get(x.as_str().unwrap()) { + *x = Value::String(n.clone()); + } + } else { + remap(x, map); + } + } + } + Value::Array(a) => a.iter_mut().for_each(|x| remap(x, map)), + _ => {} + } + } + remap(value, &text_map); + // An id-shaped spelling is a reference by id whether or not its target + // is in the document (a library element with no library loaded). + fn bind(v: &mut Value) { + match v { + Value::Object(o) => { + let spelled = o + .get("@ref") + .and_then(|r| r.as_str()) + .map(|r| r.trim_matches('\'').to_string()); + if let Some(id) = spelled.filter(|id| Uuid::parse_str(id).is_ok()) { + o.clear(); + o.insert("@id".into(), Value::String(id)); + return; + } + o.values_mut().for_each(bind); + } + Value::Array(a) => a.iter_mut().for_each(bind), + _ => {} + } + } + bind(value); +} + +/// Load a compact (or full) interchange document into a fresh model +/// with no library: the lift names references through `names` +/// (id text → qualified-name segments, as [`crate::json::library_name_map`] +/// produces), the text is rebuilt, and the document's ids are kept as +/// explicit ids. Returns the model, its resolved form with the overlay +/// applied, the overlay, and the lift's non-fatal problems. +pub fn load_document( + document: &Value, + names: &HashMap>, +) -> Result<(Model, ResolvedModel, ExplicitIds, Vec), String> { + let mut names = names.clone(); + names.extend(crate::lift::document_reference_name_map(document)); + let docs = + crate::lift::split_documents(document).unwrap_or_else(|| vec![(None, document.clone())]); + let mut model = Model::new(); + let mut warnings = Vec::new(); + for (i, (_, doc)) in docs.iter().enumerate() { + let lifted = crate::lift::from_compact_json_with_names(doc, &names)?; + warnings.extend(lifted.errors); + let ext = match lifted.unit.dialect { + sysmlv2_syntax::ast::Dialect::Kerml => "kerml", + _ => "sysml", + }; + let text = sysmlv2_syntax::print::print_source(&lifted.unit); + let unit = model.add_source(format!("document-{}.{ext}", i + 1), &text); + if let Some(d) = unit + .diagnostics + .iter() + .find(|d| d.severity == sysmlv2_syntax::diag::Severity::Error) + { + return Err(format!("lifted text does not parse: {}", d.message)); + } + } + let mut resolved = ResolvedModel::build(&model); + let external = |s: &str| names.get(s).and_then(|segs| segs.last().cloned()); + let (mut explicit_ids, unmatched) = explicit_id_map(document, &model, &external, &mut warnings); + if unmatched > 0 { + warnings.push(format!( + "{unmatched} element(s) of the document have no structural counterpart in the \ + rebuilt model; their ids are not preserved" + )); + } + let map: HashMap = explicit_ids.iter().map(|(d, (g, _))| (*d, *g)).collect(); + let applied = resolved.override_ids(&map); + explicit_ids.retain(|d, _| applied.iter().any(|(a, _, _)| a == d)); + resolved.bind_id_spelled_references(); + Ok((model, resolved, explicit_ids, warnings)) +} diff --git a/crates/sysmlv2-model/src/metaclass.rs b/crates/sysmlv2-model/src/metaclass.rs new file mode 100644 index 0000000..a72ce36 --- /dev/null +++ b/crates/sysmlv2-model/src/metaclass.rs @@ -0,0 +1,2266 @@ +//! Generated from the pinned `spec-refs/{KerML,SysML}.xmi` by +//! `tools/gen_metaclass_hierarchy.py`; do not edit. +//! +//! Abstract-syntax inheritance, distinct from a model element's declared +//! specializations. Used to validate the kinds of explicit typing targets. +//! +//! `NAMES` holds every metaclass in sorted order and `ANCESTORS[i]` the +//! bit set, over that same order, of the metaclasses `NAMES[i]` strictly +//! specializes; a conformance test is two generated name dispatches and a bit test. + +const COUNT: usize = 175; +const WORDS: usize = 3; + +/// Every metaclass name, in stable index order. +const NAMES: [&str; COUNT] = [ + "AcceptActionUsage", + "ActionDefinition", + "ActionUsage", + "ActorMembership", + "AllocationDefinition", + "AllocationUsage", + "AnalysisCaseDefinition", + "AnalysisCaseUsage", + "AnnotatingElement", + "Annotation", + "AssertConstraintUsage", + "AssignmentActionUsage", + "Association", + "AssociationStructure", + "AttributeDefinition", + "AttributeUsage", + "Behavior", + "BindingConnector", + "BindingConnectorAsUsage", + "BooleanExpression", + "CalculationDefinition", + "CalculationUsage", + "CaseDefinition", + "CaseUsage", + "Class", + "Classifier", + "CollectExpression", + "Comment", + "ConcernDefinition", + "ConcernUsage", + "ConjugatedPortDefinition", + "ConjugatedPortTyping", + "Conjugation", + "ConnectionDefinition", + "ConnectionUsage", + "Connector", + "ConnectorAsUsage", + "ConstraintDefinition", + "ConstraintUsage", + "ConstructorExpression", + "ControlNode", + "CrossSubsetting", + "DataType", + "DecisionNode", + "Definition", + "Dependency", + "Differencing", + "Disjoining", + "Documentation", + "Element", + "ElementFilterMembership", + "EndFeatureMembership", + "EnumerationDefinition", + "EnumerationUsage", + "EventOccurrenceUsage", + "ExhibitStateUsage", + "Expose", + "Expression", + "Feature", + "FeatureChainExpression", + "FeatureChaining", + "FeatureInverting", + "FeatureMembership", + "FeatureReferenceExpression", + "FeatureTyping", + "FeatureValue", + "Flow", + "FlowDefinition", + "FlowEnd", + "FlowUsage", + "ForLoopActionUsage", + "ForkNode", + "FramedConcernMembership", + "Function", + "IfActionUsage", + "Import", + "IncludeUseCaseUsage", + "IndexExpression", + "InstantiationExpression", + "Interaction", + "InterfaceDefinition", + "InterfaceUsage", + "Intersecting", + "Invariant", + "InvocationExpression", + "ItemDefinition", + "ItemUsage", + "JoinNode", + "LibraryPackage", + "LiteralBoolean", + "LiteralExpression", + "LiteralInfinity", + "LiteralInteger", + "LiteralRational", + "LiteralString", + "LoopActionUsage", + "Membership", + "MembershipExpose", + "MembershipImport", + "MergeNode", + "Metaclass", + "MetadataAccessExpression", + "MetadataDefinition", + "MetadataFeature", + "MetadataUsage", + "Multiplicity", + "MultiplicityRange", + "Namespace", + "NamespaceExpose", + "NamespaceImport", + "NullExpression", + "ObjectiveMembership", + "OccurrenceDefinition", + "OccurrenceUsage", + "OperatorExpression", + "OwningMembership", + "Package", + "ParameterMembership", + "PartDefinition", + "PartUsage", + "PayloadFeature", + "PerformActionUsage", + "PortConjugation", + "PortDefinition", + "PortUsage", + "Predicate", + "Redefinition", + "ReferenceSubsetting", + "ReferenceUsage", + "Relationship", + "RenderingDefinition", + "RenderingUsage", + "RequirementConstraintMembership", + "RequirementDefinition", + "RequirementUsage", + "RequirementVerificationMembership", + "ResultExpressionMembership", + "ReturnParameterMembership", + "SatisfyRequirementUsage", + "SelectExpression", + "SendActionUsage", + "Specialization", + "StakeholderMembership", + "StateDefinition", + "StateSubactionMembership", + "StateUsage", + "Step", + "Structure", + "Subclassification", + "SubjectMembership", + "Subsetting", + "Succession", + "SuccessionAsUsage", + "SuccessionFlow", + "SuccessionFlowUsage", + "TerminateActionUsage", + "TextualRepresentation", + "TransitionFeatureMembership", + "TransitionUsage", + "TriggerInvocationExpression", + "Type", + "TypeFeaturing", + "Unioning", + "Usage", + "UseCaseDefinition", + "UseCaseUsage", + "VariantMembership", + "VerificationCaseDefinition", + "VerificationCaseUsage", + "ViewDefinition", + "ViewRenderingMembership", + "ViewUsage", + "ViewpointDefinition", + "ViewpointUsage", + "WhileLoopActionUsage", +]; + +/// Strict ancestors of `NAMES[i]`, as a bit set in `NAMES` order. +const ANCESTORS: [[u64; WORDS]; COUNT] = [ + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002100003010000, 0x0001080000000000, 0x0000000100000000], + [0x0402000000000000, 0x0002080000000000, 0x0000000900040000], + [0x4002000000000000, 0x0028000100000000, 0x0000000000000002], + [0x0002100203003000, 0x0041080000200000, 0x0000000100080002], + [0x0402001c00000000, 0x0082080000400000, 0x0000000900000002], + [0x0002100003510002, 0x0001080000000200, 0x0000000100000000], + [0x0602000000a00004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0602004000080000, 0x0002080000080000, 0x0000000900040000], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000002000000, 0x0000080000000000, 0x0000000100000002], + [0x0002000003001000, 0x0000080000000000, 0x0000000100080002], + [0x0002140002000000, 0x0000080000000000, 0x0000000100000000], + [0x0402000000000000, 0x0000080000000000, 0x0000000900000000], + [0x0002000003000000, 0x0000080000000000, 0x0000000100000000], + [0x0402000800000000, 0x0000080000000000, 0x0000000100000002], + [0x0402001800020000, 0x0000080000000000, 0x0000000900000002], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0002100003010002, 0x0001080000000200, 0x0000000100000000], + [0x0602000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002100003110002, 0x0001080000000200, 0x0000000100000000], + [0x0602000000200004, 0x0002080000000000, 0x0000000900040000], + [0x0002000002000000, 0x0000080000000000, 0x0000000100000000], + [0x0002000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0602000000000000, 0x0004080000104000, 0x0000000100040000], + [0x0002000000000100, 0x0000000000000000, 0x0000000000000000], + [0x0002102003010000, 0x2001080000000200, 0x0000000100000020], + [0x0602004000080000, 0x0002080000000000, 0x0000000900040040], + [0x0002100003000000, 0x0801080000000000, 0x0000000100080000], + [0x0002000000000000, 0x0000000000000001, 0x0000000000002002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002100003003000, 0x0041080000200000, 0x0000000100080002], + [0x0402001800000000, 0x0082080000400000, 0x0000000900000002], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000002], + [0x0402000800000000, 0x0000080000000000, 0x0000000900000002], + [0x0002100003010000, 0x2001080000000200, 0x0000000100000000], + [0x0602000000080000, 0x0002080000000000, 0x0000000900040000], + [0x0602000000000000, 0x0000080000004000, 0x0000000100040000], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000402002], + [0x0002000002000000, 0x0000080000000000, 0x0000000100000000], + [0x0402010000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000002000000, 0x0000080000000000, 0x0000000100000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000008000100, 0x0000000000000000, 0x0000000000000000], + [0x0000000000000000, 0x0000000000000000, 0x0000000000000000], + [0x0002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0002140002004000, 0x0000080000000000, 0x0000000100000000], + [0x0402000000008000, 0x0000080000000000, 0x0000000900000000], + [0x0402000000000000, 0x0002080000000000, 0x0000000900000000], + [0x0442000000000004, 0x0202080000000000, 0x0000000900060000], + [0x0002000000000000, 0x0000000000000800, 0x0000000000000002], + [0x0402000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0002000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0602000000000000, 0x0004080000104000, 0x0000000100040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000002002], + [0x0002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0402000800000000, 0x0000080000000000, 0x0000000100040002], + [0x0002100003011002, 0x0001080000008000, 0x0000000100000002], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0402001800000004, 0x0002080000000004, 0x0000000900040002], + [0x0402000000000004, 0x0002080080000000, 0x0000000900040000], + [0x0402010000000004, 0x0002080000000000, 0x0000000900040000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000012], + [0x0002000003010000, 0x0000080000000000, 0x0000000100000000], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0642000000a00004, 0x0202080000000000, 0x0000002900040000], + [0x0602000000000000, 0x0004080000104000, 0x0000000100040000], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0002000003011000, 0x0000080000000000, 0x0000000100000002], + [0x0002100203003000, 0x0041080000200000, 0x0000000100080002], + [0x0402001c00000000, 0x0082080000400000, 0x0000000900000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0602000000080000, 0x0000080000000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080000004000, 0x0000000100040000], + [0x0002100003000000, 0x0001080000000000, 0x0000000100080000], + [0x0402000000000000, 0x0002080000000000, 0x0000000900000000], + [0x0402010000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0010080000000000, 0x0000000000000000], + [0x0602000000000000, 0x0000080004000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080004000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080004000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080004000000, 0x0000000100040000], + [0x0602000000000000, 0x0000080004000000, 0x0000000100040000], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0102000000000000, 0x0000000400000800, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000800, 0x0000000000000002], + [0x0402010000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000003000000, 0x0000080000000000, 0x0000000100080000], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x0002100003000000, 0x0001081000200000, 0x0000000100080000], + [0x0402000000000100, 0x0000080000000000, 0x0000000100000000], + [0x0402000000000100, 0x0002088000400000, 0x0000000900000000], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0402000000000000, 0x00000a0000000000, 0x0000000100000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000000], + [0x0102000000000000, 0x0000200000000800, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000800, 0x0000000000000002], + [0x0602000000000000, 0x0000080000000000, 0x0000000100040000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0002100003000000, 0x0000080000000000, 0x0000000100000000], + [0x0402000000000000, 0x0000080000000000, 0x0000000900000000], + [0x0602000000000000, 0x0000080000104000, 0x0000000100040000], + [0x0002000000000000, 0x0000000100000000, 0x0000000000000002], + [0x0002000000000000, 0x0000080000000000, 0x0000000000000000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0002100003000000, 0x0001080000200000, 0x0000000100080000], + [0x0402000000000000, 0x0002080000400000, 0x0000000900000000], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0442000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000100000000, 0x0000000000000000, 0x0000000000000002], + [0x0002100003000000, 0x0001080000000000, 0x0000000100080000], + [0x0402000000000000, 0x0002080000000000, 0x0000000900000000], + [0x0002000003010000, 0x0000080000000200, 0x0000000100000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000402002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000402002], + [0x0402000000000000, 0x0000080000000000, 0x0000000900000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000000], + [0x0002100003000000, 0x0041080000200000, 0x0000000100080000], + [0x0402000000000000, 0x0082080000400000, 0x0000000900000000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0002102003010000, 0x2001080000000200, 0x0000000100000000], + [0x0602004000080000, 0x0002080000000000, 0x0000000900040000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000012], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x4002000000000000, 0x0028000100000000, 0x0000000000000002], + [0x0602004000080400, 0x0002080000080000, 0x0000000900040040], + [0x0602000000000000, 0x0004080000104000, 0x0000000100040000], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x4002000000000000, 0x0028000100000000, 0x0000000000000002], + [0x0002100003010002, 0x0001080000000000, 0x0000000100000000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0002000003000000, 0x0000080000000000, 0x0000000100000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000002002], + [0x4002000000000000, 0x0028000100000000, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000002002], + [0x0402000800000000, 0x0000080000000000, 0x0000000100000002], + [0x0402001800000000, 0x0000080000000000, 0x0000000900800002], + [0x0402000800000000, 0x0000080000000004, 0x0000000100840002], + [0x0402001800000004, 0x0002080000000024, 0x0000000902840002], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000100, 0x0000000000000000, 0x0000000000000000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0402000000000004, 0x0002080000000000, 0x0000000900040000], + [0x0602000000000000, 0x0000080000104000, 0x0000000100040000], + [0x0002000000000000, 0x0000080000000000, 0x0000000000000000], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0002000000000000, 0x0000000000000000, 0x0000000000000002], + [0x0402000000000000, 0x0000080000000000, 0x0000000100000000], + [0x0002100003510002, 0x0001080000000200, 0x0000000100000000], + [0x0602000000a00004, 0x0002080000000000, 0x0000000900040000], + [0x0002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0002100003510002, 0x0001080000000200, 0x0000000100000000], + [0x0602000000a00004, 0x0002080000000000, 0x0000000900040000], + [0x0002100003000000, 0x0041080000200000, 0x0000000100080000], + [0x4002000000000000, 0x0008000100000000, 0x0000000000000002], + [0x0402000000000000, 0x0082080000400000, 0x0000000900000000], + [0x0002102003010000, 0x2001080000000200, 0x0000000100000020], + [0x0602004000080000, 0x0002080000000000, 0x0000000900040040], + [0x0402000000000004, 0x0002080080000000, 0x0000000900040000], +]; + +fn index(name: &str) -> Option { + match name { + "AcceptActionUsage" => Some(0), + "ActionDefinition" => Some(1), + "ActionUsage" => Some(2), + "ActorMembership" => Some(3), + "AllocationDefinition" => Some(4), + "AllocationUsage" => Some(5), + "AnalysisCaseDefinition" => Some(6), + "AnalysisCaseUsage" => Some(7), + "AnnotatingElement" => Some(8), + "Annotation" => Some(9), + "AssertConstraintUsage" => Some(10), + "AssignmentActionUsage" => Some(11), + "Association" => Some(12), + "AssociationStructure" => Some(13), + "AttributeDefinition" => Some(14), + "AttributeUsage" => Some(15), + "Behavior" => Some(16), + "BindingConnector" => Some(17), + "BindingConnectorAsUsage" => Some(18), + "BooleanExpression" => Some(19), + "CalculationDefinition" => Some(20), + "CalculationUsage" => Some(21), + "CaseDefinition" => Some(22), + "CaseUsage" => Some(23), + "Class" => Some(24), + "Classifier" => Some(25), + "CollectExpression" => Some(26), + "Comment" => Some(27), + "ConcernDefinition" => Some(28), + "ConcernUsage" => Some(29), + "ConjugatedPortDefinition" => Some(30), + "ConjugatedPortTyping" => Some(31), + "Conjugation" => Some(32), + "ConnectionDefinition" => Some(33), + "ConnectionUsage" => Some(34), + "Connector" => Some(35), + "ConnectorAsUsage" => Some(36), + "ConstraintDefinition" => Some(37), + "ConstraintUsage" => Some(38), + "ConstructorExpression" => Some(39), + "ControlNode" => Some(40), + "CrossSubsetting" => Some(41), + "DataType" => Some(42), + "DecisionNode" => Some(43), + "Definition" => Some(44), + "Dependency" => Some(45), + "Differencing" => Some(46), + "Disjoining" => Some(47), + "Documentation" => Some(48), + "Element" => Some(49), + "ElementFilterMembership" => Some(50), + "EndFeatureMembership" => Some(51), + "EnumerationDefinition" => Some(52), + "EnumerationUsage" => Some(53), + "EventOccurrenceUsage" => Some(54), + "ExhibitStateUsage" => Some(55), + "Expose" => Some(56), + "Expression" => Some(57), + "Feature" => Some(58), + "FeatureChainExpression" => Some(59), + "FeatureChaining" => Some(60), + "FeatureInverting" => Some(61), + "FeatureMembership" => Some(62), + "FeatureReferenceExpression" => Some(63), + "FeatureTyping" => Some(64), + "FeatureValue" => Some(65), + "Flow" => Some(66), + "FlowDefinition" => Some(67), + "FlowEnd" => Some(68), + "FlowUsage" => Some(69), + "ForLoopActionUsage" => Some(70), + "ForkNode" => Some(71), + "FramedConcernMembership" => Some(72), + "Function" => Some(73), + "IfActionUsage" => Some(74), + "Import" => Some(75), + "IncludeUseCaseUsage" => Some(76), + "IndexExpression" => Some(77), + "InstantiationExpression" => Some(78), + "Interaction" => Some(79), + "InterfaceDefinition" => Some(80), + "InterfaceUsage" => Some(81), + "Intersecting" => Some(82), + "Invariant" => Some(83), + "InvocationExpression" => Some(84), + "ItemDefinition" => Some(85), + "ItemUsage" => Some(86), + "JoinNode" => Some(87), + "LibraryPackage" => Some(88), + "LiteralBoolean" => Some(89), + "LiteralExpression" => Some(90), + "LiteralInfinity" => Some(91), + "LiteralInteger" => Some(92), + "LiteralRational" => Some(93), + "LiteralString" => Some(94), + "LoopActionUsage" => Some(95), + "Membership" => Some(96), + "MembershipExpose" => Some(97), + "MembershipImport" => Some(98), + "MergeNode" => Some(99), + "Metaclass" => Some(100), + "MetadataAccessExpression" => Some(101), + "MetadataDefinition" => Some(102), + "MetadataFeature" => Some(103), + "MetadataUsage" => Some(104), + "Multiplicity" => Some(105), + "MultiplicityRange" => Some(106), + "Namespace" => Some(107), + "NamespaceExpose" => Some(108), + "NamespaceImport" => Some(109), + "NullExpression" => Some(110), + "ObjectiveMembership" => Some(111), + "OccurrenceDefinition" => Some(112), + "OccurrenceUsage" => Some(113), + "OperatorExpression" => Some(114), + "OwningMembership" => Some(115), + "Package" => Some(116), + "ParameterMembership" => Some(117), + "PartDefinition" => Some(118), + "PartUsage" => Some(119), + "PayloadFeature" => Some(120), + "PerformActionUsage" => Some(121), + "PortConjugation" => Some(122), + "PortDefinition" => Some(123), + "PortUsage" => Some(124), + "Predicate" => Some(125), + "Redefinition" => Some(126), + "ReferenceSubsetting" => Some(127), + "ReferenceUsage" => Some(128), + "Relationship" => Some(129), + "RenderingDefinition" => Some(130), + "RenderingUsage" => Some(131), + "RequirementConstraintMembership" => Some(132), + "RequirementDefinition" => Some(133), + "RequirementUsage" => Some(134), + "RequirementVerificationMembership" => Some(135), + "ResultExpressionMembership" => Some(136), + "ReturnParameterMembership" => Some(137), + "SatisfyRequirementUsage" => Some(138), + "SelectExpression" => Some(139), + "SendActionUsage" => Some(140), + "Specialization" => Some(141), + "StakeholderMembership" => Some(142), + "StateDefinition" => Some(143), + "StateSubactionMembership" => Some(144), + "StateUsage" => Some(145), + "Step" => Some(146), + "Structure" => Some(147), + "Subclassification" => Some(148), + "SubjectMembership" => Some(149), + "Subsetting" => Some(150), + "Succession" => Some(151), + "SuccessionAsUsage" => Some(152), + "SuccessionFlow" => Some(153), + "SuccessionFlowUsage" => Some(154), + "TerminateActionUsage" => Some(155), + "TextualRepresentation" => Some(156), + "TransitionFeatureMembership" => Some(157), + "TransitionUsage" => Some(158), + "TriggerInvocationExpression" => Some(159), + "Type" => Some(160), + "TypeFeaturing" => Some(161), + "Unioning" => Some(162), + "Usage" => Some(163), + "UseCaseDefinition" => Some(164), + "UseCaseUsage" => Some(165), + "VariantMembership" => Some(166), + "VerificationCaseDefinition" => Some(167), + "VerificationCaseUsage" => Some(168), + "ViewDefinition" => Some(169), + "ViewRenderingMembership" => Some(170), + "ViewUsage" => Some(171), + "ViewpointDefinition" => Some(172), + "ViewpointUsage" => Some(173), + "WhileLoopActionUsage" => Some(174), + _ => None, + } +} + +pub(crate) fn conforms(specific: &str, general: &str) -> bool { + if specific == general { + return true; + } + let (Some(s), Some(g)) = (index(specific), index(general)) else { + return false; + }; + ANCESTORS[s][g / 64] >> (g % 64) & 1 == 1 +} + +pub(crate) fn canonical_name(name: &str) -> Option<&'static str> { + index(name).map(|i| NAMES[i]) +} + +/// The same hierarchy as name lists: `(metaclass, strict ancestors)`, +/// for the test that pins the bit table. +#[cfg(test)] +pub(crate) const ANCESTOR_NAMES: [(&str, &[&str]); COUNT] = [ + ( + "AcceptActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ActionDefinition", + &[ + "Behavior", + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "ActionUsage", + &[ + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ActorMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "ParameterMembership", + "Relationship", + ], + ), + ( + "AllocationDefinition", + &[ + "Association", + "AssociationStructure", + "Class", + "Classifier", + "ConnectionDefinition", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "PartDefinition", + "Relationship", + "Structure", + "Type", + ], + ), + ( + "AllocationUsage", + &[ + "ConnectionUsage", + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "PartUsage", + "Relationship", + "Type", + "Usage", + ], + ), + ( + "AnalysisCaseDefinition", + &[ + "ActionDefinition", + "Behavior", + "CalculationDefinition", + "CaseDefinition", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "AnalysisCaseUsage", + &[ + "ActionUsage", + "CalculationUsage", + "CaseUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("AnnotatingElement", &["Element"]), + ("Annotation", &["Element", "Relationship"]), + ( + "AssertConstraintUsage", + &[ + "BooleanExpression", + "ConstraintUsage", + "Element", + "Expression", + "Feature", + "Invariant", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "AssignmentActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "Association", + &["Classifier", "Element", "Namespace", "Relationship", "Type"], + ), + ( + "AssociationStructure", + &[ + "Association", + "Class", + "Classifier", + "Element", + "Namespace", + "Relationship", + "Structure", + "Type", + ], + ), + ( + "AttributeDefinition", + &[ + "Classifier", + "DataType", + "Definition", + "Element", + "Namespace", + "Type", + ], + ), + ( + "AttributeUsage", + &["Element", "Feature", "Namespace", "Type", "Usage"], + ), + ( + "Behavior", + &["Class", "Classifier", "Element", "Namespace", "Type"], + ), + ( + "BindingConnector", + &[ + "Connector", + "Element", + "Feature", + "Namespace", + "Relationship", + "Type", + ], + ), + ( + "BindingConnectorAsUsage", + &[ + "BindingConnector", + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "Namespace", + "Relationship", + "Type", + "Usage", + ], + ), + ( + "BooleanExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "CalculationDefinition", + &[ + "ActionDefinition", + "Behavior", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "CalculationUsage", + &[ + "ActionUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "CaseDefinition", + &[ + "ActionDefinition", + "Behavior", + "CalculationDefinition", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "CaseUsage", + &[ + "ActionUsage", + "CalculationUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Class", &["Classifier", "Element", "Namespace", "Type"]), + ("Classifier", &["Element", "Namespace", "Type"]), + ( + "CollectExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "OperatorExpression", + "Step", + "Type", + ], + ), + ("Comment", &["AnnotatingElement", "Element"]), + ( + "ConcernDefinition", + &[ + "Behavior", + "Class", + "Classifier", + "ConstraintDefinition", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Predicate", + "RequirementDefinition", + "Type", + ], + ), + ( + "ConcernUsage", + &[ + "BooleanExpression", + "ConstraintUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "RequirementUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ConjugatedPortDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "OccurrenceDefinition", + "PortDefinition", + "Structure", + "Type", + ], + ), + ( + "ConjugatedPortTyping", + &["Element", "FeatureTyping", "Relationship", "Specialization"], + ), + ("Conjugation", &["Element", "Relationship"]), + ( + "ConnectionDefinition", + &[ + "Association", + "AssociationStructure", + "Class", + "Classifier", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "PartDefinition", + "Relationship", + "Structure", + "Type", + ], + ), + ( + "ConnectionUsage", + &[ + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "PartUsage", + "Relationship", + "Type", + "Usage", + ], + ), + ( + "Connector", + &["Element", "Feature", "Namespace", "Relationship", "Type"], + ), + ( + "ConnectorAsUsage", + &[ + "Connector", + "Element", + "Feature", + "Namespace", + "Relationship", + "Type", + "Usage", + ], + ), + ( + "ConstraintDefinition", + &[ + "Behavior", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Predicate", + "Type", + ], + ), + ( + "ConstraintUsage", + &[ + "BooleanExpression", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ConstructorExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "ControlNode", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "CrossSubsetting", + &["Element", "Relationship", "Specialization", "Subsetting"], + ), + ("DataType", &["Classifier", "Element", "Namespace", "Type"]), + ( + "DecisionNode", + &[ + "ActionUsage", + "ControlNode", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "Definition", + &["Classifier", "Element", "Namespace", "Type"], + ), + ("Dependency", &["Element", "Relationship"]), + ("Differencing", &["Element", "Relationship"]), + ("Disjoining", &["Element", "Relationship"]), + ( + "Documentation", + &["AnnotatingElement", "Comment", "Element"], + ), + ("Element", &[]), + ( + "ElementFilterMembership", + &["Element", "Membership", "OwningMembership", "Relationship"], + ), + ( + "EndFeatureMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "EnumerationDefinition", + &[ + "AttributeDefinition", + "Classifier", + "DataType", + "Definition", + "Element", + "Namespace", + "Type", + ], + ), + ( + "EnumerationUsage", + &[ + "AttributeUsage", + "Element", + "Feature", + "Namespace", + "Type", + "Usage", + ], + ), + ( + "EventOccurrenceUsage", + &[ + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Type", + "Usage", + ], + ), + ( + "ExhibitStateUsage", + &[ + "ActionUsage", + "Element", + "EventOccurrenceUsage", + "Feature", + "Namespace", + "OccurrenceUsage", + "PerformActionUsage", + "StateUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Expose", &["Element", "Import", "Relationship"]), + ( + "Expression", + &["Element", "Feature", "Namespace", "Step", "Type"], + ), + ("Feature", &["Element", "Namespace", "Type"]), + ( + "FeatureChainExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "OperatorExpression", + "Step", + "Type", + ], + ), + ("FeatureChaining", &["Element", "Relationship"]), + ("FeatureInverting", &["Element", "Relationship"]), + ( + "FeatureMembership", + &["Element", "Membership", "OwningMembership", "Relationship"], + ), + ( + "FeatureReferenceExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "FeatureTyping", + &["Element", "Relationship", "Specialization"], + ), + ( + "FeatureValue", + &["Element", "Membership", "OwningMembership", "Relationship"], + ), + ( + "Flow", + &[ + "Connector", + "Element", + "Feature", + "Namespace", + "Relationship", + "Step", + "Type", + ], + ), + ( + "FlowDefinition", + &[ + "ActionDefinition", + "Association", + "Behavior", + "Class", + "Classifier", + "Definition", + "Element", + "Interaction", + "Namespace", + "OccurrenceDefinition", + "Relationship", + "Type", + ], + ), + ("FlowEnd", &["Element", "Feature", "Namespace", "Type"]), + ( + "FlowUsage", + &[ + "ActionUsage", + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "Flow", + "Namespace", + "OccurrenceUsage", + "Relationship", + "Step", + "Type", + "Usage", + ], + ), + ( + "ForLoopActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "LoopActionUsage", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ForkNode", + &[ + "ActionUsage", + "ControlNode", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "FramedConcernMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + "RequirementConstraintMembership", + ], + ), + ( + "Function", + &[ + "Behavior", + "Class", + "Classifier", + "Element", + "Namespace", + "Type", + ], + ), + ( + "IfActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Import", &["Element", "Relationship"]), + ( + "IncludeUseCaseUsage", + &[ + "ActionUsage", + "CalculationUsage", + "CaseUsage", + "Element", + "EventOccurrenceUsage", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "PerformActionUsage", + "Step", + "Type", + "Usage", + "UseCaseUsage", + ], + ), + ( + "IndexExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "OperatorExpression", + "Step", + "Type", + ], + ), + ( + "InstantiationExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "Interaction", + &[ + "Association", + "Behavior", + "Class", + "Classifier", + "Element", + "Namespace", + "Relationship", + "Type", + ], + ), + ( + "InterfaceDefinition", + &[ + "Association", + "AssociationStructure", + "Class", + "Classifier", + "ConnectionDefinition", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "PartDefinition", + "Relationship", + "Structure", + "Type", + ], + ), + ( + "InterfaceUsage", + &[ + "ConnectionUsage", + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "PartUsage", + "Relationship", + "Type", + "Usage", + ], + ), + ("Intersecting", &["Element", "Relationship"]), + ( + "Invariant", + &[ + "BooleanExpression", + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "InvocationExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "ItemDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "OccurrenceDefinition", + "Structure", + "Type", + ], + ), + ( + "ItemUsage", + &[ + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Type", + "Usage", + ], + ), + ( + "JoinNode", + &[ + "ActionUsage", + "ControlNode", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("LibraryPackage", &["Element", "Namespace", "Package"]), + ( + "LiteralBoolean", + &[ + "Element", + "Expression", + "Feature", + "LiteralExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LiteralExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LiteralInfinity", + &[ + "Element", + "Expression", + "Feature", + "LiteralExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LiteralInteger", + &[ + "Element", + "Expression", + "Feature", + "LiteralExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LiteralRational", + &[ + "Element", + "Expression", + "Feature", + "LiteralExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LiteralString", + &[ + "Element", + "Expression", + "Feature", + "LiteralExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "LoopActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Membership", &["Element", "Relationship"]), + ( + "MembershipExpose", + &[ + "Element", + "Expose", + "Import", + "MembershipImport", + "Relationship", + ], + ), + ("MembershipImport", &["Element", "Import", "Relationship"]), + ( + "MergeNode", + &[ + "ActionUsage", + "ControlNode", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "Metaclass", + &[ + "Class", + "Classifier", + "Element", + "Namespace", + "Structure", + "Type", + ], + ), + ( + "MetadataAccessExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "MetadataDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "ItemDefinition", + "Metaclass", + "Namespace", + "OccurrenceDefinition", + "Structure", + "Type", + ], + ), + ( + "MetadataFeature", + &[ + "AnnotatingElement", + "Element", + "Feature", + "Namespace", + "Type", + ], + ), + ( + "MetadataUsage", + &[ + "AnnotatingElement", + "Element", + "Feature", + "ItemUsage", + "MetadataFeature", + "Namespace", + "OccurrenceUsage", + "Type", + "Usage", + ], + ), + ("Multiplicity", &["Element", "Feature", "Namespace", "Type"]), + ( + "MultiplicityRange", + &["Element", "Feature", "Multiplicity", "Namespace", "Type"], + ), + ("Namespace", &["Element"]), + ( + "NamespaceExpose", + &[ + "Element", + "Expose", + "Import", + "NamespaceImport", + "Relationship", + ], + ), + ("NamespaceImport", &["Element", "Import", "Relationship"]), + ( + "NullExpression", + &[ + "Element", + "Expression", + "Feature", + "Namespace", + "Step", + "Type", + ], + ), + ( + "ObjectiveMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "OccurrenceDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "Type", + ], + ), + ( + "OccurrenceUsage", + &["Element", "Feature", "Namespace", "Type", "Usage"], + ), + ( + "OperatorExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "Step", + "Type", + ], + ), + ( + "OwningMembership", + &["Element", "Membership", "Relationship"], + ), + ("Package", &["Element", "Namespace"]), + ( + "ParameterMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "PartDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "Structure", + "Type", + ], + ), + ( + "PartUsage", + &[ + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "Type", + "Usage", + ], + ), + ( + "PayloadFeature", + &["Element", "Feature", "Namespace", "Type"], + ), + ( + "PerformActionUsage", + &[ + "ActionUsage", + "Element", + "EventOccurrenceUsage", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "PortConjugation", + &["Conjugation", "Element", "Relationship"], + ), + ( + "PortDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "OccurrenceDefinition", + "Structure", + "Type", + ], + ), + ( + "PortUsage", + &[ + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Type", + "Usage", + ], + ), + ( + "Predicate", + &[ + "Behavior", + "Class", + "Classifier", + "Element", + "Function", + "Namespace", + "Type", + ], + ), + ( + "Redefinition", + &["Element", "Relationship", "Specialization", "Subsetting"], + ), + ( + "ReferenceSubsetting", + &["Element", "Relationship", "Specialization", "Subsetting"], + ), + ( + "ReferenceUsage", + &["Element", "Feature", "Namespace", "Type", "Usage"], + ), + ("Relationship", &["Element"]), + ( + "RenderingDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "PartDefinition", + "Structure", + "Type", + ], + ), + ( + "RenderingUsage", + &[ + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "PartUsage", + "Type", + "Usage", + ], + ), + ( + "RequirementConstraintMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "RequirementDefinition", + &[ + "Behavior", + "Class", + "Classifier", + "ConstraintDefinition", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Predicate", + "Type", + ], + ), + ( + "RequirementUsage", + &[ + "BooleanExpression", + "ConstraintUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "RequirementVerificationMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + "RequirementConstraintMembership", + ], + ), + ( + "ResultExpressionMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "ReturnParameterMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "ParameterMembership", + "Relationship", + ], + ), + ( + "SatisfyRequirementUsage", + &[ + "AssertConstraintUsage", + "BooleanExpression", + "ConstraintUsage", + "Element", + "Expression", + "Feature", + "Invariant", + "Namespace", + "OccurrenceUsage", + "RequirementUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "SelectExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "OperatorExpression", + "Step", + "Type", + ], + ), + ( + "SendActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Specialization", &["Element", "Relationship"]), + ( + "StakeholderMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "ParameterMembership", + "Relationship", + ], + ), + ( + "StateDefinition", + &[ + "ActionDefinition", + "Behavior", + "Class", + "Classifier", + "Definition", + "Element", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "StateSubactionMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "StateUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("Step", &["Element", "Feature", "Namespace", "Type"]), + ( + "Structure", + &["Class", "Classifier", "Element", "Namespace", "Type"], + ), + ( + "Subclassification", + &["Element", "Relationship", "Specialization"], + ), + ( + "SubjectMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "ParameterMembership", + "Relationship", + ], + ), + ("Subsetting", &["Element", "Relationship", "Specialization"]), + ( + "Succession", + &[ + "Connector", + "Element", + "Feature", + "Namespace", + "Relationship", + "Type", + ], + ), + ( + "SuccessionAsUsage", + &[ + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "Namespace", + "Relationship", + "Succession", + "Type", + "Usage", + ], + ), + ( + "SuccessionFlow", + &[ + "Connector", + "Element", + "Feature", + "Flow", + "Namespace", + "Relationship", + "Step", + "Succession", + "Type", + ], + ), + ( + "SuccessionFlowUsage", + &[ + "ActionUsage", + "Connector", + "ConnectorAsUsage", + "Element", + "Feature", + "Flow", + "FlowUsage", + "Namespace", + "OccurrenceUsage", + "Relationship", + "Step", + "Succession", + "SuccessionFlow", + "Type", + "Usage", + ], + ), + ( + "TerminateActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ("TextualRepresentation", &["AnnotatingElement", "Element"]), + ( + "TransitionFeatureMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "TransitionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "TriggerInvocationExpression", + &[ + "Element", + "Expression", + "Feature", + "InstantiationExpression", + "InvocationExpression", + "Namespace", + "Step", + "Type", + ], + ), + ("Type", &["Element", "Namespace"]), + ("TypeFeaturing", &["Element", "Relationship"]), + ("Unioning", &["Element", "Relationship"]), + ("Usage", &["Element", "Feature", "Namespace", "Type"]), + ( + "UseCaseDefinition", + &[ + "ActionDefinition", + "Behavior", + "CalculationDefinition", + "CaseDefinition", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "UseCaseUsage", + &[ + "ActionUsage", + "CalculationUsage", + "CaseUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "VariantMembership", + &["Element", "Membership", "OwningMembership", "Relationship"], + ), + ( + "VerificationCaseDefinition", + &[ + "ActionDefinition", + "Behavior", + "CalculationDefinition", + "CaseDefinition", + "Class", + "Classifier", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Type", + ], + ), + ( + "VerificationCaseUsage", + &[ + "ActionUsage", + "CalculationUsage", + "CaseUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "ViewDefinition", + &[ + "Class", + "Classifier", + "Definition", + "Element", + "ItemDefinition", + "Namespace", + "OccurrenceDefinition", + "PartDefinition", + "Structure", + "Type", + ], + ), + ( + "ViewRenderingMembership", + &[ + "Element", + "FeatureMembership", + "Membership", + "OwningMembership", + "Relationship", + ], + ), + ( + "ViewUsage", + &[ + "Element", + "Feature", + "ItemUsage", + "Namespace", + "OccurrenceUsage", + "PartUsage", + "Type", + "Usage", + ], + ), + ( + "ViewpointDefinition", + &[ + "Behavior", + "Class", + "Classifier", + "ConstraintDefinition", + "Definition", + "Element", + "Function", + "Namespace", + "OccurrenceDefinition", + "Predicate", + "RequirementDefinition", + "Type", + ], + ), + ( + "ViewpointUsage", + &[ + "BooleanExpression", + "ConstraintUsage", + "Element", + "Expression", + "Feature", + "Namespace", + "OccurrenceUsage", + "RequirementUsage", + "Step", + "Type", + "Usage", + ], + ), + ( + "WhileLoopActionUsage", + &[ + "ActionUsage", + "Element", + "Feature", + "LoopActionUsage", + "Namespace", + "OccurrenceUsage", + "Step", + "Type", + "Usage", + ], + ), +]; diff --git a/crates/sysmlv2-model/src/metaclass_tests.rs b/crates/sysmlv2-model/src/metaclass_tests.rs new file mode 100644 index 0000000..10fd1f5 --- /dev/null +++ b/crates/sysmlv2-model/src/metaclass_tests.rs @@ -0,0 +1,65 @@ +//! Pins the generated metaclass conformance tables against the hierarchy +//! they were generated from. +use crate::metaclass::{ANCESTOR_NAMES, canonical_name, conforms}; + +#[test] +fn conformance_table_matches_the_generated_hierarchy() { + let names: Vec<&str> = ANCESTOR_NAMES.iter().map(|(name, _)| *name).collect(); + assert!(names.windows(2).all(|w| w[0] < w[1]), "sorted, unique"); + for (specific, ancestors) in ANCESTOR_NAMES { + assert!(ancestors.windows(2).all(|w| w[0] < w[1])); + for general in &names { + let expected = specific == *general || ancestors.contains(general); + assert_eq!( + conforms(specific, general), + expected, + "{specific} -> {general}" + ); + } + // Inheritance is transitive: every ancestor's ancestors are ours. + for ancestor in ancestors { + let (_, theirs) = ANCESTOR_NAMES[names.binary_search(ancestor).unwrap()]; + for further in theirs { + assert!( + ancestors.contains(further), + "{specific}: {ancestor} -> {further}" + ); + } + } + } +} + +#[test] +fn conformance_samples_and_unknown_names() { + for (specific, general, expected) in [ + ("PortDefinition", "Definition", true), + ("PortDefinition", "Classifier", true), + ("PortDefinition", "Element", true), + ("PortDefinition", "Usage", false), + ("Definition", "PortDefinition", false), + ("AcceptActionUsage", "Step", true), + ("AcceptActionUsage", "Behavior", false), + ("Membership", "Relationship", true), + ("Relationship", "Membership", false), + ("LiteralInteger", "Expression", true), + ("MetadataUsage", "ItemUsage", true), + ("Element", "Element", true), + ("Unknown", "Element", false), + ("Element", "Unknown", false), + ("Unknown", "Unknown", true), + ] { + assert_eq!( + conforms(specific, general), + expected, + "{specific} -> {general}" + ); + } + assert_eq!(canonical_name("PortDefinition"), Some("PortDefinition")); + assert_eq!(canonical_name("portdefinition"), None); + assert_eq!(canonical_name(""), None); + assert!( + ANCESTOR_NAMES + .iter() + .all(|(n, _)| canonical_name(n) == Some(*n)) + ); +} diff --git a/crates/sysmlv2-model/src/model.rs b/crates/sysmlv2-model/src/model.rs index e9bcd87..8b97a00 100644 --- a/crates/sysmlv2-model/src/model.rs +++ b/crates/sysmlv2-model/src/model.rs @@ -14,14 +14,17 @@ use std::io; use std::path::Path; use sysmlv2_syntax::ast::{Dialect, SourceUnit}; use sysmlv2_syntax::diag::Diagnostic; -use sysmlv2_syntax::parser::{parse_kerml_source, parse_source}; +use sysmlv2_syntax::parser::{Parse, parse_kerml_source, parse_source}; use sysmlv2_syntax::span::LineIndex; /// One parsed file within a model. +#[derive(Clone, serde::Serialize, serde::Deserialize)] pub struct ModelUnit { /// Display name (usually the file name); also salts element IDs. pub name: String, - pub unit: SourceUnit, + /// Parsed syntax shared by prepared-library models. Clone the Arc for + /// sharing, or use `unit.as_ref().clone()` for an independent syntax tree. + pub unit: std::sync::Arc, pub diagnostics: Vec, /// Library units provide resolution targets but are not serialized. pub is_library: bool, @@ -30,10 +33,69 @@ pub struct ModelUnit { pub lines: LineIndex, } +/// A parsed user source whose name, syntax and line index travel together. +/// +/// Inspect diagnostics or validate the syntax, then transfer this value into +/// a model with [`Model::add_parsed_source`] without parsing the text again. +/// The original source text is not retained. +pub struct ParsedSource { + name: String, + parse: Parse, + lines: LineIndex, +} + +impl ParsedSource { + /// Parse using the name's case-insensitive extension: `.kerml` selects + /// KerML; other names select SysML, as with [`Model::add_source`]. + #[must_use] + pub fn new(name: impl Into, src: &str) -> Self { + let name = name.into(); + let parse = match Model::dialect_for(&name) { + Dialect::Kerml => parse_kerml_source(src), + Dialect::Sysml => parse_source(src), + }; + Self { + name, + parse, + lines: LineIndex::new(src), + } + } + + /// Display name and element-ID seed of this source. + #[must_use] + pub fn name(&self) -> &str { + &self.name + } + + /// Parsed syntax, including recovered members when diagnostics exist. + #[must_use] + pub fn unit(&self) -> &SourceUnit { + &self.parse.unit + } + + /// Parse diagnostics; context and model validation are separate stages. + #[must_use] + pub fn diagnostics(&self) -> &[Diagnostic] { + &self.parse.diagnostics + } + + /// Line index for positions in this source's syntax and diagnostics. + #[must_use] + pub fn lines(&self) -> &LineIndex { + &self.lines + } +} + /// A set of parsed source units sharing one global root namespace. #[derive(Default)] pub struct Model { units: Vec, + // Original text is retained only for library snapshots. Public ModelUnit + // continues to expose the exact, shared syntax tree. + sources: Vec>, + library: Option>, + all_units: std::sync::OnceLock>, + pub(crate) prepared: Option>, /// Standard-library resolution cache state (see [`crate::libcache`]). /// Interior mutability: the builder consumes hints / deposits a /// recording through `&Model`. @@ -46,52 +108,97 @@ pub(crate) enum LibCacheSlot { /// No caching (the default; also the post-consumption state). #[default] Off, - /// Replay these outcomes on the next build. - Use(crate::libcache::LibraryCache), + /// Replay these outcomes on the next build. Shared: a build reads + /// the recorded ids in place and the slot survives repeated builds. + Use(std::sync::Arc), /// Record outcomes during the next build. Record, /// Outcomes recorded by a build, awaiting [`Model::take_recorded_library_cache`]. Recorded(crate::libcache::LibraryCache), + /// A recording on disk, read only if a build cannot reuse the prepared + /// graph. Prepared builds never pay for loading it. + Lazy(std::path::PathBuf), } impl Model { + pub(crate) fn install_prepared( + &mut self, + library: std::sync::Arc, + ) -> io::Result<()> { + if self.unit_count() != 0 { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "install a prepared library before adding source units", + )); + } + self.library = Some(library.units.clone()); + self.prepared = Some(library); + Ok(()) + } + + /// Prepare and retain this library-only model for subsequent user builds. + pub fn prepare_library( + &mut self, + ) -> io::Result> { + let library = std::sync::Arc::new(crate::prepared::PreparedLibrary::build(self)?); + self.prepared = Some(library.clone()); + Ok(library) + } + + #[must_use] pub fn new() -> Self { Model::default() } - fn dialect_for(name: &str) -> Dialect { - if name.ends_with(".kerml") { + /// The dialect a unit name spells. The extension is read without + /// case, so `Model.KerML` is KerML like `model.kerml` — the file + /// systems these names come from do not distinguish the two. + pub(crate) fn dialect_for(name: &str) -> Dialect { + let kerml = Path::new(name) + .extension() + .is_some_and(|e| e.eq_ignore_ascii_case("kerml")); + if kerml { Dialect::Kerml } else { Dialect::Sysml } } - fn add(&mut self, name: String, src: &str, is_library: bool) -> &ModelUnit { - let parse = match Self::dialect_for(&name) { - Dialect::Kerml => parse_kerml_source(src), - Dialect::Sysml => parse_source(src), - }; + fn add_parsed(&mut self, parsed: ParsedSource, source: Option<&str>) -> &ModelUnit { + self.all_units.take(); + let is_library = source.is_some(); + if is_library { + self.prepared = None; + } + self.sources.push(source.unwrap_or("").into()); self.units.push(ModelUnit { - name, - unit: parse.unit, - diagnostics: parse.diagnostics, + name: parsed.name, + unit: std::sync::Arc::new(parsed.parse.unit), + diagnostics: parsed.parse.diagnostics, is_library, - lines: LineIndex::new(src), + lines: parsed.lines, }); self.units.last().unwrap() } + /// Add an already parsed user source without reparsing or cloning its tree. + /// Like [`Self::add_source`], this retains partial syntax and diagnostics; + /// callers requiring clean syntax must check them before building a model. + pub fn add_parsed_source(&mut self, parsed: ParsedSource) -> &ModelUnit { + self.add_parsed(parsed, None) + } + /// Parse and add a user source. The dialect is chosen by the name's - /// extension (`.kerml` → KerML, anything else → SysML). + /// extension, read without case (`.kerml` → KerML, anything else → + /// SysML). pub fn add_source(&mut self, name: impl Into, src: &str) -> &ModelUnit { - self.add(name.into(), src, false) + self.add_parsed_source(ParsedSource::new(name, src)) } /// Parse and add a library source: it participates in name resolution /// but its elements are not included in serialized output. pub fn add_library_source(&mut self, name: impl Into, src: &str) -> &ModelUnit { - self.add(name.into(), src, true) + self.add_parsed(ParsedSource::new(name, src), Some(src)) } /// Recursively load every `.sysml` / `.kerml` file under `dir` as @@ -111,20 +218,101 @@ impl Model { Ok(count) } + /// All parsed units. A disk-loaded library reconstructs syntax on first + /// access; validation and unit metadata queries do not require this work. pub fn units(&self) -> &[ModelUnit] { - &self.units + if let Some(library) = &self.library { + self.all_units.get_or_init(|| { + (0..library.len()) + .map(|i| library.unit(i).clone()) + .chain(self.units.iter().cloned()) + .collect() + }) + } else { + &self.units + } + } + + /// Number of units, without materializing library syntax. + pub fn unit_count(&self) -> usize { + self.library.as_ref().map_or(0, |l| l.len()) + self.units.len() + } + + /// Access one parsed unit, reconstructing only that library file if needed. + /// + /// # Panics + /// + /// When `index` is not a unit of this model — it must be below + /// [`Self::unit_count`]. + pub fn unit(&self, index: usize) -> &ModelUnit { + let boundary = self.library.as_ref().map_or(0, |l| l.len()); + if index < boundary { + self.library.as_ref().unwrap().unit(index) + } else { + &self.units[index - boundary] + } + } + + /// Library units whose syntax tree is currently in memory. A prepared + /// library starts at zero and grows only through [`Self::units`] or + /// [`Self::unit`]; source-loaded libraries always count every unit. + /// Diagnostic for callers that must stay on the metadata-only paths. + pub fn loaded_library_unit_count(&self) -> usize { + self.library.as_ref().map_or(0, |l| l.loaded()) + + self.units.iter().filter(|u| u.is_library).count() + } + + /// Whether a unit supplies library definitions, without loading its syntax. + pub fn is_library_unit(&self, index: usize) -> bool { + let boundary = self.library.as_ref().map_or(0, |l| l.len()); + index < boundary || self.units[index - boundary].is_library + } + + pub(crate) fn unit_meta(&self, index: usize) -> (&str, &LineIndex) { + let boundary = self.library.as_ref().map_or(0, |l| l.len()); + if index < boundary { + self.library.as_ref().unwrap().meta(index) + } else { + let unit = &self.units[index - boundary]; + (&unit.name, &unit.lines) + } + } + + pub(crate) fn user_units(&self) -> impl Iterator { + let boundary = self.library.as_ref().map_or(0, |l| l.len()); + self.units + .iter() + .enumerate() + .filter(|(_, u)| !u.is_library) + .map(move |(i, u)| (boundary + i, u)) + } + + pub(crate) fn library_sources(&self) -> Vec { + let mut sources = self + .library + .as_ref() + .map_or_else(Vec::new, |l| l.sources.clone()); + sources.extend( + self.units + .iter() + .zip(&self.sources) + .map(|(unit, source)| crate::prepared::LibrarySource::new(unit, source.clone())), + ); + sources } /// Replay `cache` on the next build of this model (library units must /// match the content the cache was recorded from — key by /// [`crate::libcache::hash_library_dir`]). pub fn set_library_cache(&mut self, cache: crate::libcache::LibraryCache) { - *self.lib_cache.borrow_mut() = LibCacheSlot::Use(cache); + self.prepared = None; + *self.lib_cache.borrow_mut() = LibCacheSlot::Use(std::sync::Arc::new(cache)); } /// Record library resolution outcomes during the next build; collect /// them with [`Model::take_recorded_library_cache`]. pub fn record_library_cache(&mut self) { + self.prepared = None; *self.lib_cache.borrow_mut() = LibCacheSlot::Record; } @@ -146,12 +334,40 @@ impl Model { match &*slot { // Replay survives repeated builds of the same model (a CLI // invocation may build more than once). - LibCacheSlot::Use(c) => LibCacheSlot::Use(c.clone()), + LibCacheSlot::Use(c) => LibCacheSlot::Use(std::sync::Arc::clone(c)), LibCacheSlot::Record => std::mem::take(&mut *slot), + LibCacheSlot::Lazy(path) => match crate::libcache::LibraryCache::load(path) { + Some(cache) => { + let cache = std::sync::Arc::new(cache); + *slot = LibCacheSlot::Use(std::sync::Arc::clone(&cache)); + LibCacheSlot::Use(cache) + } + None => { + *slot = LibCacheSlot::Off; + LibCacheSlot::Off + } + }, _ => LibCacheSlot::Off, } } + /// Keep a recording available for builds that fall back from the + /// prepared graph, without reading it up front or disabling that graph. + pub(crate) fn set_lazy_library_cache(&self, path: std::path::PathBuf) { + *self.lib_cache.borrow_mut() = LibCacheSlot::Lazy(path); + } + + #[cfg(test)] + pub(crate) fn lib_cache_kind(&self) -> &'static str { + match &*self.lib_cache.borrow() { + LibCacheSlot::Off => "off", + LibCacheSlot::Use(_) => "use", + LibCacheSlot::Record => "record", + LibCacheSlot::Recorded(_) => "recorded", + LibCacheSlot::Lazy(_) => "lazy", + } + } + pub(crate) fn deposit_recorded(&self, cache: crate::libcache::LibraryCache) { *self.lib_cache.borrow_mut() = LibCacheSlot::Recorded(cache); } @@ -195,3 +411,27 @@ pub(crate) fn collect_model_files(dir: &Path, out: &mut Vec) } Ok(()) } + +#[cfg(test)] +mod dialect_tests { + use super::Model; + use sysmlv2_syntax::ast::Dialect; + + #[test] + fn the_extension_names_the_dialect_without_case() { + for name in ["m.kerml", "m.KerML", "m.KERML", "dir.sysml/m.kerml"] { + assert_eq!(Model::dialect_for(name), Dialect::Kerml, "{name}"); + } + for name in ["m.sysml", "m.SysML", "m", "kerml", "m.kerml.bak"] { + assert_eq!(Model::dialect_for(name), Dialect::Sysml, "{name}"); + } + } + + #[test] + fn a_unit_named_in_upper_case_parses_as_kerml() { + let mut model = Model::new(); + // `class` is KerML's; a SysML parse of the same text fails. + let unit = model.add_source("M.KERML", "package P { class A; }"); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + } +} diff --git a/crates/sysmlv2-model/src/prepared.rs b/crates/sysmlv2-model/src/prepared.rs new file mode 100644 index 0000000..e4426a7 --- /dev/null +++ b/crates/sysmlv2-model/src/prepared.rs @@ -0,0 +1,741 @@ +//! Prepared-library persistence. The cache is private to one toolkit build; +//! its source text, resolved graph and analysis facts are never interchange. +use crate::{ + json::Builder, + libcache::MAX_BYTES, + model::{Model, ModelUnit}, +}; +use serde::{Deserialize, Deserializer, Serialize}; +use std::{io, path::Path, sync::Arc}; +use sysmlv2_syntax::ast::QualifiedName; + +type Specialization = (usize, &'static str, usize, QualifiedName); + +pub(crate) fn specializations<'de, D: Deserializer<'de>>( + d: D, +) -> Result, D::Error> { + Vec::<(usize, String, usize, QualifiedName)>::deserialize(d)? + .into_iter() + .map(|(e, n, s, q)| { + Ok(( + e, + crate::metaclass::canonical_name(&n) + .ok_or_else(|| serde::de::Error::custom("unknown specialization metaclass"))?, + s, + q, + )) + }) + .collect() +} +pub(crate) fn implied_ends<'de, D: Deserializer<'de>>( + d: D, +) -> Result, D::Error> { + Vec::<(String, usize, usize)>::deserialize(d)? + .into_iter() + .map(|(n, e, s)| { + let name = match n.as_str() { + "source" => "source", + "target" => "target", + _ => return Err(serde::de::Error::custom("invalid implicit end")), + }; + Ok((name, e, s)) + }) + .collect() +} + +/// Sources are valid UTF-8 checked by the snapshot decoder. The ordinary, +/// error-tolerant parser recreates the original AST on demand, including spans +/// and recovery nodes. No deferred binary decoding can fail after installation. +#[derive(Serialize, Deserialize)] +pub(crate) struct LibraryUnits { + pub(crate) sources: Vec, +} +#[derive(Clone, Serialize, Deserialize)] +pub(crate) struct LibrarySource { + name: String, + source: Arc, + dialect: sysmlv2_syntax::ast::Dialect, + diagnostics: Vec, + is_library: bool, + lines: sysmlv2_syntax::span::LineIndex, + #[serde(skip)] + parsed: Arc>, +} +impl LibrarySource { + pub(crate) fn new(unit: &ModelUnit, source: Arc) -> Self { + Self { + name: unit.name.clone(), + source, + dialect: unit.unit.dialect, + diagnostics: unit.diagnostics.clone(), + is_library: unit.is_library, + lines: unit.lines.clone(), + parsed: Arc::new(std::sync::OnceLock::from(unit.clone())), + } + } +} +impl LibraryUnits { + pub(crate) fn len(&self) -> usize { + self.sources.len() + } + pub(crate) fn loaded(&self) -> usize { + self.sources + .iter() + .filter(|s| s.parsed.get().is_some()) + .count() + } + pub(crate) fn meta(&self, i: usize) -> (&str, &sysmlv2_syntax::span::LineIndex) { + (&self.sources[i].name, &self.sources[i].lines) + } + pub(crate) fn unit(&self, i: usize) -> &ModelUnit { + let source = &self.sources[i]; + source.parsed.get_or_init(|| { + use sysmlv2_syntax::{ + ast::Dialect, + parser::{parse_kerml_source, parse_source}, + }; + let parse = match source.dialect { + Dialect::Kerml => parse_kerml_source(&source.source), + Dialect::Sysml => parse_source(&source.source), + }; + ModelUnit { + name: source.name.clone(), + unit: Arc::new(parse.unit), + diagnostics: source.diagnostics.clone(), + is_library: source.is_library, + lines: source.lines.clone(), + } + }) + } +} + +// 7: scopes carry their implied bases separately from the written ones. +// 8: the integrity trailer is the same fixed hash the resolution cache +// uses, so a snapshot outlives a change of the standard library's +// hasher. +const MAGIC: &[u8] = b"SYSML-PREPARED-8\n"; +/// A resolved library with source text and static-analysis facts. Loaded syntax +/// trees are reconstructed on demand. Models share immutable element and scope +/// prefixes; user additions and resolver caches remain private. +#[derive(Serialize)] +pub struct PreparedLibrary { + pub(crate) units: Arc, + pub(crate) builder: Builder, + facts: Arc, + pub(crate) root_names: std::collections::HashSet, +} +impl PreparedLibrary { + /// Original unit names and text in library order, without loading syntax trees. + pub fn sources(&self) -> impl ExactSizeIterator { + self.units + .sources + .iter() + .map(|s| (s.name.as_str(), s.source.as_ref())) + } + + /// A library unit's original name and text, without loading its syntax tree. + pub fn source(&self, unit: usize) -> Option<(&str, &str)> { + self.units + .sources + .get(unit) + .map(|s| (s.name.as_str(), s.source.as_ref())) + } + + /// Prepare a library-only model. User units are refused. + pub fn build(model: &Model) -> io::Result { + if (0..model.unit_count()).any(|i| !model.is_library_unit(i)) { + return Err(io::Error::new( + io::ErrorKind::InvalidInput, + "prepared library contains user units", + )); + } + let mut builder = Builder::default(); + builder.build_model(model); + let mut resolved = crate::json::ResolvedModel::from_builder(builder, model); + resolved.prepare_quantity_memo(); + let mut builder = resolved.b; + let mut facts = builder.prepare_facts(); + facts.freeze(); + let facts = Arc::new(facts); + builder.library_facts = Some(facts.clone()); + builder.freeze_library(); + Ok(Self { + units: Arc::new(LibraryUnits { + sources: model.library_sources(), + }), + builder, + facts, + root_names: crate::json::top_level_names(model.units().iter()), + }) + } + /// Attach this library to an empty model, without parsing or graph lowering. + pub fn install(self: Arc, model: &mut Model) -> io::Result<()> { + model.install_prepared(self) + } + /// Decode a content- and build-identified snapshot. Stale, truncated or + /// corrupt caches are misses and may be rebuilt from source. + pub fn load(path: &Path, key: u64) -> Option { + Self::from_bytes(&crate::libcache::read_capped(path)?, key) + } + pub fn from_bytes(bytes: &[u8], key: u64) -> Option { + if bytes.len() as u64 > MAX_BYTES { + return None; + } + let bytes = bytes.strip_prefix(MAGIC)?; + let build = crate::libcache::TOOLKIT_BUILD.as_bytes(); + let bytes = bytes.strip_prefix(build)?.strip_prefix(b"\n")?; + let saved_key = u64::from_le_bytes(bytes.get(..8)?.try_into().ok()?); + let sum = u64::from_le_bytes(bytes.get(8..16)?.try_into().ok()?); + let payload = bytes.get(16..)?; + if saved_key != key || checksum(payload) != sum { + return None; + } + #[derive(Deserialize)] + struct Wire { + units: Arc, + builder: Builder, + facts: Arc, + root_names: std::collections::HashSet, + } + let wire: Wire = crate::cache_codec::decode(payload).ok()?; + let mut result = Self { + units: wire.units, + builder: wire.builder, + facts: wire.facts, + root_names: wire.root_names, + }; + result.builder.reset_lookup_caches(); + if result.units.sources.iter().any(|u| !u.is_library) + || !result.builder.valid_library(result.units.len()) + || !result.facts.valid(result.builder.elements.len()) + { + return None; + } + Arc::make_mut(&mut result.facts).freeze(); + result.builder.library_facts = Some(result.facts.clone()); + result.builder.freeze_library(); + Some(result) + } + pub fn to_bytes(&self, key: u64) -> io::Result> { + let payload = crate::cache_codec::encode(self).map_err(io::Error::other)?; + let mut out = MAGIC.to_vec(); + out.extend_from_slice(crate::libcache::TOOLKIT_BUILD.as_bytes()); + out.push(b'\n'); + out.extend_from_slice(&key.to_le_bytes()); + out.extend_from_slice(&checksum(&payload).to_le_bytes()); + out.extend_from_slice(&payload); + if out.len() as u64 > MAX_BYTES { + return Err(io::Error::other( + "prepared library exceeds cache size limit", + )); + } + Ok(out) + } + pub fn save(&self, path: &Path, key: u64) -> io::Result<()> { + crate::libcache::write_atomically(path, &self.to_bytes(key)?) + } +} +fn unsaved_warning(path: &Path, error: &io::Error) -> String { + format!( + "could not save the library cache at {}: {error}; every run will prepare the library from source", + path.display() + ) +} +/// Integrity trailer over a snapshot's payload. Deliberately the fixed, +/// dependency-free hash the resolution cache writes rather than the +/// standard library's default hasher, whose results are documented as +/// free to change between releases: a changed hash would silently +/// invalidate every snapshot on disk, one rebuild at a time, with no +/// version to explain it. +fn checksum(bytes: &[u8]) -> u64 { + let mut hash = crate::libcache::Fnv::new(); + hash.update(bytes); + hash.finish() +} + +/// What loading a directory library leaves for its caller. +/// +/// Non-exhaustive: callers read what they act on, so leaving something +/// further for them is not a breaking change. Build one with +/// [`Default`]. +#[derive(Debug, Default)] +#[non_exhaustive] +pub struct LibraryLoad { + /// Where to save a legacy resolution recording after building the + /// model, when one is wanted; `None` when the complete snapshot + /// already covers the library or caching is off. + pub recording_path: Option, + /// Conditions the caller should report but need not act on. Cache + /// persistence is an optimization, never a prerequisite, so a cache + /// that cannot be written is a warning — but a silent one would + /// repeat the full preparation on every run unexplained. The message + /// is the caller's to place: an interactive process has standard + /// error, a language server has its log, a browser has neither. + pub warnings: Vec, +} + +/// Load a directory library with ambient sources. Prepared snapshots serve new +/// models; the resolution-only cache remains available when appending libraries +/// to an existing model. `SYSMLV2_LIB_CACHE=off` disables both paths. +/// +/// Complete snapshots are saved during preparation; see [`LibraryLoad`] for +/// what the caller does with the result. +pub fn load_library_with_cache(model: &mut Model, dir: &Path) -> io::Result { + use crate::{ambient, libcache}; + let enabled = !std::env::var_os("SYSMLV2_LIB_CACHE").is_some_and(|v| v == "off"); + let key = enabled + .then(|| libcache::hash_library_dir(dir).map(ambient::mix_key)) + .transpose()?; + let cache = key.and_then(|key| Some((key, libcache::default_cache_path(key)?))); + load_library_with_cache_at(model, dir, cache) +} + +/// [`load_library_with_cache`] with an explicit content key and resolution +/// cache path. The complete snapshot lives beside that path under the +/// `prepared` extension. A prepared model also keeps the resolution recording +/// reachable, unread, for builds that must resolve jointly after all: those +/// replay it instead of resolving the whole library cold. A snapshot miss +/// records that recording while preparing. +pub(crate) fn load_library_with_cache_at( + model: &mut Model, + dir: &Path, + cache: Option<(u64, std::path::PathBuf)>, +) -> io::Result { + use crate::{ambient, libcache}; + use std::{ + collections::HashMap, + sync::{Mutex, OnceLock, Weak}, + }; + static SHARED: OnceLock>>> = OnceLock::new(); + let mut warnings = Vec::new(); + if model.unit_count() == 0 { + if let Some((key, path)) = cache { + let shared = SHARED.get_or_init(Mutex::default); + let cached = { + let mut entries = shared.lock().unwrap_or_else(|e| e.into_inner()); + entries.retain(|_, value| value.strong_count() > 0); + entries.get(&key).and_then(Weak::upgrade) + }; + if let Some(library) = cached { + library.install(model)?; + model.set_lazy_library_cache(path); + return Ok(LibraryLoad::default()); + } + let snapshot = path.with_extension("prepared"); + let library = if let Some(library) = PreparedLibrary::load(&snapshot, key) { + let library = Arc::new(library); + library.clone().install(model)?; + library + } else { + model.load_library_dir(dir)?; + ambient::add_to(model); + model.record_library_cache(); + let library = model.prepare_library()?; + if let Some(recording) = model.take_recorded_library_cache() { + if let Err(error) = recording.save(&path) { + warnings.push(unsaved_warning(&path, &error)); + } + } + if let Err(error) = library.save(&snapshot, key) { + warnings.push(unsaved_warning(&snapshot, &error)); + } + library + }; + model.set_lazy_library_cache(path); + shared + .lock() + .unwrap_or_else(|e| e.into_inner()) + .insert(key, Arc::downgrade(&library)); + return Ok(LibraryLoad { + recording_path: None, + warnings, + }); + } + } + model.load_library_dir(dir)?; + ambient::add_to(model); + let path = cache.map(|(_, path)| path); + if let Some(path) = path.as_ref() { + match libcache::LibraryCache::load(path) { + Some(cache) => model.set_library_cache(cache), + None => model.record_library_cache(), + } + } + Ok(LibraryLoad { + recording_path: path, + warnings, + }) +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::json::ResolvedModel; + #[test] + fn disk_syntax_is_lazy_exact_and_shared_without_changing_unit_indices() { + let sources = [ + ( + "library.kerml", + "// note\npackage L { datatype Number; feature n : Number = 2; }", + ), + ( + "library.sysml", + "package K { /* documentation */ attribute x = 3; }", + ), + ]; + let mut base = Model::new(); + for (name, source) in sources { + base.add_library_source(name, source); + } + let bytes = base.prepare_library().unwrap().to_bytes(7).unwrap(); + let library = Arc::new(PreparedLibrary::from_bytes(&bytes, 7).unwrap()); + let loaded = || { + library + .units + .sources + .iter() + .filter(|s| s.parsed.get().is_some()) + .count() + }; + let mut model = Model::new(); + library.clone().install(&mut model).unwrap(); + assert_eq!(model.unit_count(), 2); + model.add_source( + "user.kerml", + "package U { feature n : L::Number = L::n + 1; }", + ); + assert_eq!(model.unit_count(), 3); + assert_eq!(model.unit(2).name, "user.kerml"); + assert!(!model.is_library_unit(2)); + let mut resolved = ResolvedModel::build(&model); + crate::check::validate_model_with(&mut resolved, &model); + crate::check::validate_semantics_with(&mut resolved, &model); + assert!(resolved.b.library_facts.is_some()); + assert_eq!( + resolved.evaluate_qualified("U::n").unwrap(), + crate::eval::Value::Integer(3) + ); + // Reflection and both user/library graph exports need resolved data, + // but must not force reconstruction of unused source trees. + crate::json::model_to_compact_json(&model); + crate::json::library_to_compact_json(&model); + assert_eq!(loaded(), 0); + assert_eq!(*model.unit(1).unit, *base.unit(1).unit); + assert_eq!(loaded(), 1, "one-file access reconstructs only that file"); + let mut second = Model::new(); + library.clone().install(&mut second).unwrap(); + assert!(Arc::ptr_eq(&model.unit(1).unit, &second.unit(1).unit)); + for (a, b) in model.units()[..2].iter().zip(base.units()) { + assert_eq!( + serde_json::to_value(a).unwrap(), + serde_json::to_value(b).unwrap() + ); + } + assert_eq!(loaded(), 2); + model.add_source("next.kerml", "package Next;"); + assert_eq!( + model.units().len(), + 4, + "adding source invalidates the combined view" + ); + assert_eq!(model.unit(3).name, "next.kerml"); + assert_eq!(second.unit_count(), 2); + // Snapshot serialization itself must not reconstruct syntax either. + let fresh = PreparedLibrary::from_bytes(&bytes, 7).unwrap(); + assert!(PreparedLibrary::from_bytes(&fresh.to_bytes(7).unwrap(), 7).is_some()); + assert!(fresh.units.sources.iter().all(|s| s.parsed.get().is_none())); + } + + #[test] + fn disk_syntax_reconstructs_for_joint_resolution_and_extra_library_sources() { + let mut base = Model::new(); + base.add_library_source("l.kerml", "package L { class A :> Later; }"); + let bytes = base.prepare_library().unwrap().to_bytes(1).unwrap(); + let library = Arc::new(PreparedLibrary::from_bytes(&bytes, 1).unwrap()); + let mut model = Model::new(); + library.clone().install(&mut model).unwrap(); + model.add_source("u.kerml", "class Later; package U { feature a : L::A; }"); + assert!(ResolvedModel::build(&model).b.library_facts.is_none()); + assert!(library.units.sources[0].parsed.get().is_some()); + base.add_source("u.kerml", "class Later; package U { feature a : L::A; }"); + assert_eq!( + crate::json::model_to_compact_json(&model), + crate::json::model_to_compact_json(&base) + ); + // Clearing prepared resolution must retain the deferred sources. + let mut extra = Model::new(); + library.install(&mut extra).unwrap(); + extra.add_library_source("later.kerml", "class Later;"); + assert_eq!(extra.units().len(), 2); + let recompiled = extra.prepare_library().unwrap(); + let saved = recompiled.to_bytes(2).unwrap(); + assert!(PreparedLibrary::from_bytes(&saved, 2).is_some()); + } + + #[test] + fn ast_sharing_and_library_semantic_invalidation_are_isolated() { + let mut base = Model::new(); + base.add_library_source( + "lib.kerml", + "package Quantities { datatype MeasurementUnit; } package L { datatype A; datatype B; feature f : A; }", + ); + let prepared = base.prepare_library().unwrap(); + assert!(prepared.builder.semantic_memo.types.iter().next().is_some()); + let mut model = Model::new(); + prepared.clone().install(&mut model).unwrap(); + assert!(Arc::ptr_eq(&base.units()[0].unit, &model.units()[0].unit)); + // Preparing an already installed snapshot is supported as well. + model.prepare_library().unwrap(); + let ordinary = ResolvedModel::build(&model); + assert!(ordinary.b.semantic_memo.types.iter().next().is_some()); + model.add_source("user.kerml", "package U { typing L::f : L::B; }"); + let changed = ResolvedModel::build(&model); + assert!( + changed.b.library_facts.is_some(), + "user package still shares the library graph" + ); + assert!( + changed.b.semantic_memo.types.iter().next().is_none(), + "user typing invalidates derived library semantics" + ); + assert!( + prepared.builder.semantic_memo.types.iter().next().is_some(), + "the shared snapshot remains unchanged" + ); + } + #[test] + fn root_imports_and_named_root_relationships_keep_the_prepared_path() { + fn same_graphs(library: &[(&str, &str)], user: (&str, &str), prepared_path: bool) { + let mut base = Model::new(); + for (name, source) in library { + base.add_library_source(*name, source); + } + let prepared = base.prepare_library().unwrap(); + let mut cold = Model::new(); + for (name, source) in library { + cold.add_library_source(*name, source); + } + cold.add_source(user.0, user.1); + let mut warm = Model::new(); + prepared.install(&mut warm).unwrap(); + warm.add_source(user.0, user.1); + let r = ResolvedModel::build(&warm); + assert_eq!(r.b.library_facts.is_some(), prepared_path, "{}", user.1); + assert_eq!( + crate::json::model_to_compact_json(&cold), + crate::json::model_to_compact_json(&warm), + "{}", + user.1 + ); + assert_eq!( + crate::json::library_to_compact_json(&cold), + crate::json::library_to_compact_json(&warm), + "{}", + user.1 + ); + } + // Only names this library looked up at root and missed can complete + // it: here the implicit-base and quantity probes. Root imports, + // inferred root names and named root relationships that add other + // names keep the prepared graph. + let complete = [("lib.sysml", "package L { part def A; part def B :> A; }")]; + let mut base = Model::new(); + base.add_library_source(complete[0].0, complete[0].1); + let misses = base.prepare_library().unwrap().builder.root_misses.clone(); + assert!(misses.contains("Parts"), "{misses:?}"); + assert!(!misses.contains("A") && !misses.contains("B"), "{misses:?}"); + for source in [ + "private import L::*; package U { part a : A; part b : B; }", + "import L::*; package U { part a : A; }", + "package U { part a : L::A; } dependency D from U to L;", + "package U { part b : L::B; } private import U::*; part x : b;", + "package Q { part def Y; part def Parts; } private import Q::Y; package U { part a : L::A; }", + "package Q { part def Y { part def Parts; } } private import Q::*; package U { part a : L::A; }", + ] { + same_graphs(&complete, ("user.sysml", source), true); + } + for source in [ + // A user namespace re-exporting through its own import, an + // alias target, and a recursive import reaching a probed name. + "package Q { public import L::*; } private import Q::*; package U { part a : A; }", + "alias Q for L; private import Q::*; package U { part a : A; }", + "package Q { part def Y { part def Parts; } } private import Q::**; package U { part a : L::A; }", + "package Q { part def Parts; } private import Q::*; package U { part a : L::A; }", + ] { + same_graphs(&complete, ("user.sysml", source), false); + } + same_graphs( + &[("lib.kerml", "package L { class A; }")], + ( + "user.kerml", + "package P { feature x : L::A; } feature :>> P::x;", + ), + true, + ); + // A root filter can constrain library root imports: joint resolution. + same_graphs( + &complete, + ("user.sysml", "package U { part a : L::A; } filter true;"), + false, + ); + // A library with an unresolved root name can be completed through a + // root import, an inferred root name, or a matching declaration. + let incomplete = [( + "lib.sysml", + "package Other { part def X; } package L { part def A :> X; }", + )]; + let mut base = Model::new(); + base.add_library_source(incomplete[0].0, incomplete[0].1); + assert!( + base.prepare_library() + .unwrap() + .builder + .root_misses + .contains("X") + ); + for source in [ + "private import Other::*; package U { part a : L::A; }", + "package U { part a : L::A; part def X; } private import U::*;", + "part def X; package U { part a : L::A; }", + "package U { part a : L::A; } dependency X from U to L;", + ] { + same_graphs(&incomplete, ("user.sysml", source), false); + } + same_graphs( + &[("lib.kerml", "package L { feature f :> x; }")], + ("user.kerml", "package P { feature x; } feature :>> P::x;"), + false, + ); + } + /// A cache that cannot be written is handed back to the caller + /// rather than printed: the library runs inside hosts with no + /// standard error to print to, and the load itself still succeeds — + /// the cache is an optimization, never a prerequisite. + #[test] + fn an_unwritable_cache_is_reported_to_the_caller() { + let root = std::env::temp_dir().join(format!( + "sysml-prepared-unwritable-{}", + uuid::Uuid::new_v4() + )); + let dir = root.join("library"); + std::fs::create_dir_all(&dir).unwrap(); + std::fs::write(dir.join("Lib.sysml"), "package L { part def A; }").unwrap(); + // The cache directory's place is taken by a file, so neither the + // recording nor the snapshot can be created there. + let blocked = root.join("cache"); + std::fs::write(&blocked, b"not a directory").unwrap(); + + let mut model = Model::new(); + let load = load_library_with_cache_at( + &mut model, + &dir, + Some((7, blocked.join("stdlib.libcache"))), + ) + .unwrap(); + assert!(model.unit_count() > 0, "the library still loaded"); + assert_eq!(load.warnings.len(), 2, "{:?}", load.warnings); + for warning in &load.warnings { + assert!( + warning.contains("could not save the library cache at"), + "{warning}" + ); + } + std::fs::remove_dir_all(&root).ok(); + } + + #[test] + fn fallback_builds_replay_the_recorded_resolution_cache() { + let root = + std::env::temp_dir().join(format!("sysml-prepared-replay-{}", uuid::Uuid::new_v4())); + let dir = root.join("library"); + std::fs::create_dir_all(&dir).unwrap(); + let library = "package Other { part def X; } package L { part def A :> X; }"; + std::fs::write(dir.join("Lib.sysml"), library).unwrap(); + let recording = root.join("cache").join("stdlib.libcache"); + let cache = || Some((5, recording.clone())); + let mut cold = Model::new(); + let load = load_library_with_cache_at(&mut cold, &dir, cache()).unwrap(); + assert!(load.recording_path.is_none()); + assert!( + load.warnings.is_empty(), + "a writable cache directory produces no warning: {:?}", + load.warnings + ); + assert!( + recording.exists(), + "a snapshot miss records the resolution cache" + ); + assert!(recording.with_extension("prepared").exists()); + assert_eq!(cold.lib_cache_kind(), "lazy"); + drop(cold); + let mut warm = Model::new(); + load_library_with_cache_at(&mut warm, &dir, cache()).unwrap(); + assert_eq!(warm.loaded_library_unit_count(), 0); + assert_eq!(warm.lib_cache_kind(), "lazy"); + // Completing the missed root name forces joint resolution. + let user = "private import Other::*; package U { part a : L::A; }"; + warm.add_source("user.sysml", user); + let resolved = ResolvedModel::build(&warm); + assert!(resolved.b.library_facts.is_none()); + assert_eq!( + warm.lib_cache_kind(), + "use", + "the fallback replays the recording" + ); + let mut plain = Model::new(); + plain.add_library_source("Lib.sysml", library); + crate::ambient::add_to(&mut plain); + plain.add_source("user.sysml", user); + assert_eq!( + crate::json::model_to_compact_json(&plain), + crate::json::model_to_compact_json(&warm) + ); + assert_eq!( + crate::json::library_to_compact_json(&plain), + crate::json::library_to_compact_json(&warm) + ); + // A prepared build never reads the recording. + let mut fast = Model::new(); + load_library_with_cache_at(&mut fast, &dir, cache()).unwrap(); + fast.add_source("user.sysml", "package U { part a : L::A; }"); + assert!(ResolvedModel::build(&fast).b.library_facts.is_some()); + assert_eq!(fast.lib_cache_kind(), "lazy"); + // A stale recording is ignored rather than trusted. + std::fs::write(&recording, b"damaged").unwrap(); + let mut stale = Model::new(); + load_library_with_cache_at(&mut stale, &dir, cache()).unwrap(); + stale.add_source("user.sysml", user); + assert_eq!( + crate::json::model_to_compact_json(&plain), + crate::json::model_to_compact_json(&stale) + ); + assert_eq!(stale.lib_cache_kind(), "off"); + std::fs::remove_dir_all(root).unwrap(); + } + #[test] + fn prepared_builds_use_shared_prefixes_and_fall_back_for_root_dependencies() { + let mut base = Model::new(); + base.add_library_source("lib.kerml", "package L { class A; }"); + let prepared = base.prepare_library().unwrap(); + let mut model = Model::new(); + prepared.clone().install(&mut model).unwrap(); + model.add_source("user.kerml", "package U { feature a : L::A; }"); + let r = ResolvedModel::build(&model); + assert!( + r.b.library_facts.is_some(), + "ordinary models must take the prepared path" + ); + assert!(r.b.elements.shares_prefix(&prepared.builder.elements)); + let mut collision = Model::new(); + prepared.install(&mut collision).unwrap(); + collision.add_source("user.kerml", "package L { class A; }"); + assert!(ResolvedModel::build(&collision).b.library_facts.is_none()); + let mut base = Model::new(); + base.add_library_source("lib.kerml", "package L { class A :> Later; }"); + let prepared = base.prepare_library().unwrap(); + let mut model = Model::new(); + prepared.install(&mut model).unwrap(); + model.add_source("user.kerml", "class Later;"); + assert!(ResolvedModel::build(&model).b.library_facts.is_none()); + } +} diff --git a/crates/sysmlv2-model/src/properties.rs b/crates/sysmlv2-model/src/properties.rs new file mode 100644 index 0000000..7631b18 --- /dev/null +++ b/crates/sysmlv2-model/src/properties.rs @@ -0,0 +1,351 @@ +//! Typed semantic properties. JSON objects are constructed only for interchange +//! and reflection. References retain binary identities; booleans use bitsets. +use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::{Map, Value}; +use std::{ + borrow::Borrow, + collections::{BTreeMap, HashMap}, + sync::{Arc, OnceLock}, +}; +use uuid::Uuid; + +#[derive(Clone, Debug, Eq, PartialEq, Ord, PartialOrd)] +pub(crate) struct Key(Arc); +impl Key { + pub fn name(&self) -> &str { + &self.0 + } +} +impl Borrow for Key { + fn borrow(&self) -> &str { + &self.0 + } +} +impl Serialize for Key { + fn serialize(&self, s: S) -> Result { + s.serialize_str(&self.0) + } +} +impl<'de> Deserialize<'de> for Key { + fn deserialize>(d: D) -> Result { + struct Visitor; + impl serde::de::Visitor<'_> for Visitor { + type Value = Key; + fn expecting(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result { + f.write_str("a property name") + } + fn visit_str(self, v: &str) -> Result { + Ok(key(v)) + } + } + d.deserialize_str(Visitor) + } +} +fn key(name: &str) -> Key { + static KEYS: OnceLock>> = OnceLock::new(); + let keys = KEYS.get_or_init(|| { + let mut keys = HashMap::new(); + for (_, props) in crate::schema_props::METACLASS_PROPS { + for &(name, _) in *props { + keys.entry(name).or_insert_with(|| Arc::from(name)); + } + } + for name in ["@id", "@ref", "@type", "kind"] { + keys.entry(name).or_insert_with(|| Arc::from(name)); + } + keys + }); + Key(keys.get(name).cloned().unwrap_or_else(|| name.into())) +} +const FLAGS: &[&str] = &[ + "isAbstract", + "isComposite", + "isConstant", + "isDerived", + "isEnd", + "isImplied", + "isImpliedIncluded", + "isIndividual", + "isOrdered", + "isPortion", + "isReference", + "isSufficient", + "isUnique", + "isVariable", + "isVariation", +]; +fn flag(key: &str) -> Option { + if !key.starts_with("is") { + return None; + } + FLAGS.iter().position(|&s| s == key).map(|i| 1 << i) +} + +#[derive(Clone, Debug, Serialize, Deserialize)] +pub(crate) struct Reference { + pub id: Uuid, + #[serde(skip)] + spelling: OnceLock>, +} +#[derive(Clone, Debug, Serialize, Deserialize)] +pub(crate) enum Atom { + Null, + Bool(bool), + Number(serde_json::Number), + String(#[serde(deserialize_with = "crate::cache_codec::shared_string")] Arc), + Reference(Reference), + Array(Vec), + Object(BTreeMap), +} +impl PartialEq for Atom { + fn eq(&self, other: &Self) -> bool { + match (self, other) { + (Self::Null, Self::Null) => true, + (Self::Bool(a), Self::Bool(b)) => a == b, + (Self::String(a), Self::String(b)) => a == b, + (Self::Number(a), Self::Number(b)) => a == b, + (Self::Reference(a), Self::Reference(b)) => a.id == b.id, + (Self::Array(a), Self::Array(b)) => a == b, + (Self::Object(a), Self::Object(b)) => a == b, + _ => false, + } + } +} +impl Atom { + pub fn from_json(v: Value) -> Self { + match v { + Value::Null => Self::Null, + Value::Bool(v) => Self::Bool(v), + Value::Number(v) => Self::Number(v), + Value::String(v) => Self::String(v.into()), + Value::Array(v) => Self::Array(v.into_iter().map(Self::from_json).collect()), + Value::Object(v) => { + // A lone `@id` is an element reference. Its spelling is not + // retained: any parseable UUID form re-emits in the canonical + // hyphenated lowercase form. Every identity reaching here is + // builder-generated in that form already. + if v.len() == 1 { + if let Some(id) = v + .get("@id") + .and_then(Value::as_str) + .and_then(|s| Uuid::parse_str(s).ok()) + { + return Self::Reference(Reference { + id, + spelling: OnceLock::new(), + }); + } + } + Self::Object( + v.into_iter() + .map(|(k, v)| (key(&k), Self::from_json(v))) + .collect(), + ) + } + } + } + pub fn to_json(&self) -> Value { + match self { + Self::Null => Value::Null, + Self::Bool(v) => Value::Bool(*v), + Self::Number(v) => Value::Number(v.clone()), + Self::String(v) => Value::String(v.to_string()), + Self::Reference(r) => serde_json::json!({"@id":r.id.to_string()}), + Self::Array(v) => Value::Array(v.iter().map(Self::to_json).collect()), + Self::Object(v) => Value::Object( + v.iter() + .map(|(k, v)| (k.0.to_string(), v.to_json())) + .collect(), + ), + } + } + pub fn as_reference(&self) -> Option { + if let Self::Reference(r) = self { + Some(r.id) + } else { + None + } + } + pub fn as_str(&self) -> Option<&str> { + if let Self::String(s) = self { + Some(s) + } else { + None + } + } + pub fn as_bool(&self) -> Option { + if let Self::Bool(b) = self { + Some(*b) + } else { + None + } + } + pub fn is_string(&self) -> bool { + matches!(self, Self::String(_)) + } + pub fn is_null(&self) -> bool { + matches!(self, Self::Null) + } + pub fn as_array(&self) -> Option<&Vec> { + if let Self::Array(a) = self { + Some(a) + } else { + None + } + } + // Compatibility for uncommon graph/reflection queries. Semantic edge + // indexes use as_reference() and never materialize UUID strings. + pub fn get(&self, k: &str) -> Option<&Self> { + match self { + Self::Object(v) => v.get(k), + Self::Reference(r) if k == "@id" => Some( + r.spelling + .get_or_init(|| Box::new(Self::String(r.id.to_string().into()))), + ), + _ => None, + } + } + pub fn remap(&mut self, ids: &HashMap) { + match self { + Self::Reference(r) => { + if let Some(id) = ids.get(&r.id) { + r.id = *id; + r.spelling = OnceLock::new(); + } + } + Self::Array(v) => { + for v in v { + v.remap(ids); + } + } + Self::Object(v) => { + for v in v.values_mut() { + v.remap(ids); + } + } + _ => {} + } + } +} +#[derive(Clone, Default, Serialize, Deserialize)] +pub(crate) struct Properties { + pub(crate) present: u64, + pub(crate) flags: u64, + pub(crate) entries: crate::flat::Row<(Key, Atom)>, +} +impl Properties { + pub fn new() -> Self { + Self::default() + } + pub fn get(&self, k: &str) -> Option<&Atom> { + if let Some(bit) = flag(k) { + if self.present & bit != 0 { + return Some(if self.flags & bit != 0 { + &Atom::Bool(true) + } else { + &Atom::Bool(false) + }); + } + } + self.entries + .binary_search_by(|(key, _)| key.name().cmp(k)) + .ok() + .map(|i| &self.entries[i].1) + } + pub fn insert(&mut self, k: &str, v: Value) { + if let Some(bit) = flag(k) { + if let Value::Bool(b) = v { + self.present |= bit; + if b { + self.flags |= bit; + } else { + self.flags &= !bit; + } + if let Ok(i) = self.entries.binary_search_by(|(key, _)| key.name().cmp(k)) { + self.entries.make_mut().remove(i); + } + return; + } + self.present &= !bit; + self.flags &= !bit; + } + let value = (key(k), Atom::from_json(v)); + match self.entries.binary_search_by(|(key, _)| key.name().cmp(k)) { + Ok(i) => self.entries.make_mut()[i] = value, + Err(i) => self.entries.make_mut().insert(i, value), + } + } + pub fn append(&mut self, k: &str, value: Value) { + let i = match self.entries.binary_search_by(|(key, _)| key.name().cmp(k)) { + Ok(i) => i, + Err(i) => { + self.entries + .make_mut() + .insert(i, (key(k), Atom::Array(Vec::new()))); + i + } + }; + if let Atom::Array(a) = &mut self.entries.make_mut()[i].1 { + a.push(Atom::from_json(value)); + } + } + pub fn references(&self) -> impl Iterator + '_ { + self.entries + .iter() + .filter_map(|(k, v)| Some((k.clone(), v.as_reference()?))) + } + pub fn values_mut(&mut self) -> impl Iterator { + self.entries.make_mut().iter_mut().map(|(_, v)| v) + } + pub fn to_json(&self) -> Map { + let mut map: Map<_, _> = self + .entries + .iter() + .map(|(k, v)| (k.0.to_string(), v.to_json())) + .collect(); + for (i, &name) in FLAGS.iter().enumerate() { + if self.present & (1 << i) != 0 { + map.insert(name.into(), Value::Bool(self.flags & (1 << i) != 0)); + } + } + map + } +} + +#[cfg(test)] +mod tests { + use super::*; + use serde_json::json; + #[test] + fn typed_properties_preserve_presence_numbers_and_reference_remapping() { + let a = Uuid::from_u128(1); + let b = Uuid::from_u128(2); + let mut p = Properties::new(); + assert!(p.get("isAbstract").is_none()); + for v in [json!(false), json!(true), Value::Null, json!(false)] { + p.insert("isAbstract", v.clone()); + assert_eq!(p.get("isAbstract").unwrap().to_json(), v); + assert_eq!(p.to_json()["isAbstract"], v); + } + p.insert("target", json!({"@id":a})); + p.append("relatedElement", json!({"@id":a})); + p.insert("value", json!(u64::MAX)); + // Populate the compatibility spelling before remapping its identity. + assert_eq!( + p.get("target").unwrap().get("@id").unwrap().as_str(), + Some(a.to_string().as_str()) + ); + for v in p.values_mut() { + v.remap(&HashMap::from([(a, b)])); + } + let expected = json!({"isAbstract":false,"target":{"@id":b},"relatedElement":[{"@id":b}],"value":u64::MAX}); + assert_eq!(Value::Object(p.to_json()), expected); + let restored: Properties = + crate::cache_codec::decode(&crate::cache_codec::encode(&p).unwrap()).unwrap(); + assert_eq!(Value::Object(restored.to_json()), expected); + assert_eq!(restored.get("target").unwrap().as_reference(), Some(b)); + let first = key("declaredName"); + let second = key("declaredName"); + assert!(Arc::ptr_eq(&first.0, &second.0)); + } +} diff --git a/crates/sysmlv2-model/src/quantity.rs b/crates/sysmlv2-model/src/quantity.rs index db61959..301e245 100644 --- a/crates/sysmlv2-model/src/quantity.rs +++ b/crates/sysmlv2-model/src/quantity.rs @@ -24,7 +24,7 @@ use std::collections::{HashMap, HashSet, VecDeque}; use sysmlv2_syntax::Span; -use sysmlv2_syntax::ast::{Expr, ExprKind, Name, QualifiedName, TargetRef, escape_name}; +use sysmlv2_syntax::ast::{Dialect, Expr, ExprKind, Name, QualifiedName, TargetRef}; use crate::eval::{Unit, Value}; use crate::json::{ElementRef, ResolvedModel, ScopeRef}; @@ -33,30 +33,58 @@ use crate::json::{ElementRef, ResolvedModel, ScopeRef}; /// base-quantity element, exponents as reduced rationals (`den > 0`, /// gcd 1, zero factors dropped). Two dimensions are equal iff the /// factor lists are — the commensurability test. -#[derive(Clone, Debug, PartialEq, Eq)] +#[derive(Clone, Debug, PartialEq, Eq, Hash, serde::Serialize, serde::Deserialize)] pub struct QuantityDims { /// `(base-quantity element, exponent numerator, denominator)`. factors: Vec<(usize, i32, i32)>, } impl QuantityDims { + pub(crate) fn valid(&self, n: usize) -> bool { + self.factors + .iter() + .all(|&(e, num, den)| e < n && num != 0 && den > 0) + } + pub(crate) fn dimensionless() -> Self { + Self { + factors: Vec::new(), + } + } + + pub(crate) fn product(&self, other: &Self, divide: bool) -> Option { + let sign = if divide { -1 } else { 1 }; + normalize( + self.factors + .iter() + .map(|&(q, n, d)| (q, i64::from(n), i64::from(d))) + .chain( + other + .factors + .iter() + .map(|&(q, n, d)| (q, i64::from(n) * sign, i64::from(d))), + ) + .collect(), + ) + } + + pub(crate) fn pow(&self, exponent: i32) -> Option { + normalize( + self.factors + .iter() + .map(|&(q, n, d)| (q, i64::from(n) * i64::from(exponent), i64::from(d))) + .collect(), + ) + } + /// Dimension one — no base-quantity factors. + #[must_use] pub fn is_dimensionless(&self) -> bool { self.factors.is_empty() } - /// Canonical identity key (index/map currency). - fn key(&self) -> String { - use std::fmt::Write; - let mut out = String::new(); - for &(q, n, d) in &self.factors { - let _ = write!(out, "q{q}^{n}/{d};"); - } - out - } - /// Render for diagnostics with the base quantities' declared names: /// `L*T^-2`, `M`, `1` (dimensionless). + #[must_use] pub fn render(&self, model: &ResolvedModel) -> String { if self.factors.is_empty() { return "1".to_string(); @@ -136,10 +164,37 @@ fn simple_qn(name: &str) -> QualifiedName { impl ResolvedModel { /// The dimension a quantity value type declares: its `mRef` /// measurement reference's unit definition, read through - /// [`Self::unit_def_dims`]. `None` when the type does not carry a + /// its own `unit_def_dims`. `None` when the type does not carry a /// determinable dimension (not a quantity type, no standard /// library, an abstract measurement reference). pub fn quantity_dims_of_type(&mut self, ty: ElementRef) -> Option { + if !self.b.semantic_ready { + return self.quantity_dims_of_type_uncached(ty); + } + if let Some(hit) = self + .b + .semantic_memo + .types + .get(&(ty.0, crate::eval::unit_spelling_expansion())) + .cloned() + { + self.b.used_imports.extend(hit.imports); + return hit.value; + } + let imports = std::mem::take(&mut self.b.used_imports); + let value = self.quantity_dims_of_type_uncached(ty); + let proof = crate::semantic_memo::Proven { + value: value.clone(), + imports: self.b.used_imports.iter().copied().collect(), + }; + self.b.used_imports.extend(imports); + self.b + .semantic_memo + .types + .insert((ty.0, crate::eval::unit_spelling_expansion()), proof); + value + } + fn quantity_dims_of_type_uncached(&mut self, ty: ElementRef) -> Option { let (mref, _) = self.member_of(ty, &simple_qn("mRef"))?; self.typings(mref) .into_iter() @@ -178,6 +233,33 @@ impl ResolvedModel { /// unitPowerFactors = ()`); a definition stating neither reads /// through its explicit supertypes. fn unit_def_dims(&mut self, def: ElementRef) -> Option { + if !self.b.semantic_ready { + return self.unit_def_dims_uncached(def); + } + if let Some(hit) = self + .b + .semantic_memo + .definitions + .get(&(def.0, crate::eval::unit_spelling_expansion())) + .cloned() + { + self.b.used_imports.extend(hit.imports); + return hit.value; + } + let imports = std::mem::take(&mut self.b.used_imports); + let value = self.unit_def_dims_uncached(def); + let proof = crate::semantic_memo::Proven { + value: value.clone(), + imports: self.b.used_imports.iter().copied().collect(), + }; + self.b.used_imports.extend(imports); + self.b + .semantic_memo + .definitions + .insert((def.0, crate::eval::unit_spelling_expansion()), proof); + value + } + fn unit_def_dims_uncached(&mut self, def: ElementRef) -> Option { let qpf = self.resolve_qualified("Quantities::QuantityPowerFactor")?; let mut seen: HashSet = HashSet::new(); let mut queue = VecDeque::from([def]); @@ -220,7 +302,9 @@ impl ResolvedModel { let (escope, eexpr) = self.value_expr(em)?; let exp = match self.evaluate_in(escope, &eexpr).ok()? { Value::Integer(i) => i64::try_from(i).ok()?, - Value::Rational(r) if r.fract() == 0.0 && r.abs() < i64::MAX as f64 => r as i64, + // A literal `2.0` canonicalizes to the integer arm; the double + // arm covers a computed approximate integer. + Value::Real(r) if r.fract() == 0.0 && r.abs() < i64::MAX as f64 => r as i64, _ => return None, }; Some((quantity.0, exp)) @@ -230,7 +314,9 @@ impl ResolvedModel { /// settles on an element, else a structural read of a plain /// reference / member-chain spelling (`isq.L`). fn expr_element(&mut self, scope: ScopeRef, expr: &Expr) -> Option { - if let Ok(Value::Element(e) | Value::Unbound(e)) = self.evaluate_in(scope, expr) { + if let Ok(Value::Element(e) | Value::Unbound(e) | Value::UnboundMember(e)) = + self.evaluate_in(scope, expr) + { return Some(e); } fn flatten(e: &Expr, out: &mut Vec) -> bool { @@ -307,7 +393,7 @@ impl ResolvedModel { self.ensure_quantity_index(); self.quantity_index .as_ref() - .and_then(|ix| ix.by_dims.get(&dims.key())) + .and_then(|ix| ix.by_dims.get(dims)) .map(|v| v.iter().map(|&e| ElementRef(e)).collect()) .unwrap_or_default() } @@ -334,7 +420,7 @@ impl ResolvedModel { } fn build_quantity_index(&mut self) -> crate::json::QuantityIndex { - let mut by_dims: HashMap> = HashMap::new(); + let mut by_dims: HashMap> = HashMap::new(); let mut by_unit_def: HashMap> = HashMap::new(); let Some(sqv) = self.resolve_qualified("Quantities::ScalarQuantityValue") else { return crate::json::QuantityIndex { @@ -352,7 +438,7 @@ impl ResolvedModel { let Some(d) = self.quantity_dims_of_type(e) else { continue; }; - by_dims.entry(d.key()).or_default().push(e.0); + by_dims.entry(d).or_default().push(e.0); if let Some((mref, _)) = self.member_of(e, &simple_qn("mRef")) { for def in self.typings(mref) { let bucket = by_unit_def.entry(def.0).or_default(); @@ -375,15 +461,11 @@ impl ResolvedModel { named.sort_by(|a, b| (a.1.len(), &a.1).cmp(&(b.1.len(), &b.1))); named.into_iter().map(|(e, _)| e).collect() }; - for k in by_dims.keys().cloned().collect::>() { - let bucket = by_dims.remove(&k).unwrap_or_default(); - let sorted = order(bucket, self); - by_dims.insert(k, sorted); + for bucket in by_dims.values_mut() { + *bucket = order(std::mem::take(bucket), self); } - for k in by_unit_def.keys().copied().collect::>() { - let bucket = by_unit_def.remove(&k).unwrap_or_default(); - let sorted = order(bucket, self); - by_unit_def.insert(k, sorted); + for bucket in by_unit_def.values_mut() { + *bucket = order(std::mem::take(bucket), self); } crate::json::QuantityIndex { by_dims, @@ -398,7 +480,7 @@ impl ResolvedModel { let name = match v { Value::Boolean(_) => "Boolean", Value::Integer(_) => "Integer", - Value::Rational(_) => "Real", + Value::Rational(_) | Value::Real(_) => "Real", Value::String(_) => "String", _ => return None, }; @@ -411,8 +493,13 @@ impl ResolvedModel { /// import), the standard `ISQ` wrapper package's re-export, and /// every qualified suffix up to the full owner chain. `None` when /// nothing resolves to the target from there. - pub fn type_spelling_at(&mut self, scope: ScopeRef, target: ElementRef) -> Option { - self.reference_spelling_at(scope, None, target) + pub fn type_spelling_at( + &mut self, + dialect: Option, + scope: ScopeRef, + target: ElementRef, + ) -> Option { + self.reference_spelling_at(dialect, scope, None, target) } /// [`Self::type_spelling_at`] for an arbitrary reference site: the @@ -422,6 +509,7 @@ impl ResolvedModel { /// itself — `RefSite::exclude`). pub fn reference_spelling_at( &mut self, + dialect: Option, scope: ScopeRef, exclude: Option, target: ElementRef, @@ -435,7 +523,7 @@ impl ResolvedModel { } let mut spelled: Vec<(String, Vec)> = candidates .into_iter() - .map(|segs| (spell_segments(&segs), segs)) + .map(|segs| (spell_segments(dialect, &segs), segs)) .collect(); spelled.sort_by(|a, b| (a.0.len(), &a.0).cmp(&(b.0.len(), &b.0))); spelled.dedup_by(|a, b| a.0 == b.0); @@ -448,10 +536,14 @@ impl ResolvedModel { } /// The fully qualified spelling of `target` — its named owner chain - /// from the document root, each segment source-escaped. `None` for - /// anonymous elements. - pub fn full_spelling(&mut self, target: ElementRef) -> Option { - Some(spell_segments(&self.owner_name_chain(target)?)) + /// from the document root, each segment spelled for `dialect` (see + /// `spell_segments`). `None` for anonymous elements. + pub fn full_spelling( + &mut self, + dialect: Option, + target: ElementRef, + ) -> Option { + Some(spell_segments(dialect, &self.owner_name_chain(target)?)) } /// Whether `segments` (raw name values, unescaped) resolve to @@ -486,14 +578,13 @@ impl ResolvedModel { } } -/// Spell raw segment names as a source reference (`::`-joined, -/// non-identifier segments quoted). -fn spell_segments(segments: &[String]) -> String { - segments - .iter() - .map(|n| escape_name(n)) - .collect::>() - .join("::") +/// Spell raw segment names as a source reference (`::`-joined). Reserved +/// words of `dialect` — the unit the text is spliced into — and +/// non-identifier segments are quoted, so the result re-parses there +/// and the formatter leaves it alone; `None` quotes the words of either +/// dialect for text without a known destination. +fn spell_segments(dialect: Option, segments: &[String]) -> String { + sysmlv2_syntax::name::spell_path(dialect, segments) } fn segments_qn(segments: Vec) -> QualifiedName { @@ -509,3 +600,67 @@ fn segments_qn(segments: Vec) -> QualifiedName { span: Span::default(), } } + +impl ResolvedModel { + pub(crate) fn prepare_quantity_memo(&mut self) { + let imports = self.b.used_imports.clone(); + let unit_type = self.resolve_qualified("Quantities::MeasurementUnit"); + if let Some(unit_type) = unit_type { + for e in 0..self.b.elements.len() { + if crate::metaclass::conforms(self.b.elements[e].ty, "DataType") { + self.quantity_dims_of_type(ElementRef(e)); + if self.conforms(ElementRef(e), unit_type) { + self.unit_def_dims(ElementRef(e)); + } + } else if crate::metaclass::conforms(self.b.elements[e].ty, "Feature") + && self + .typings(ElementRef(e)) + .into_iter() + .any(|t| self.conforms(t, unit_type)) + { + crate::eval::prepare_unit(&mut self.b, e); + } + } + } + self.b.used_imports = imports; + } +} + +#[cfg(test)] +mod memo_tests { + use super::*; + #[test] + fn dimensions_match_uncached_queries_and_replay_complete_import_evidence() { + let path = std::path::Path::new(env!("CARGO_MANIFEST_DIR")) + .join("../../spec-refs/SysML-v2-Release/sysml.library"); + if !path.exists() { + return; + } + let mut model = crate::model::Model::new(); + model.load_library_dir(&path).unwrap(); + let mut r = ResolvedModel::build(&model); + for name in [ + "ISQ::AccelerationValue", + "ISQ::LengthValue", + "ISQ::MassValue", + "ScalarValues::Real", + ] { + let ty = r.resolve_qualified(name).unwrap(); + r.b.semantic_ready = false; + r.b.used_imports.clear(); + let expected = r.quantity_dims_of_type(ty); + let imports = r.b.used_imports.clone(); + r.b.semantic_ready = true; + assert_eq!(r.quantity_dims_of_type(ty), expected); + assert!( + r.b.semantic_memo + .types + .get(&(ty.0, crate::eval::unit_spelling_expansion())) + .is_some() + ); + r.b.used_imports.clear(); + assert_eq!(r.quantity_dims_of_type(ty), expected); + assert_eq!(r.b.used_imports, imports, "{name}"); + } + } +} diff --git a/crates/sysmlv2-model/src/rational.rs b/crates/sysmlv2-model/src/rational.rs new file mode 100644 index 0000000..b0d1e90 --- /dev/null +++ b/crates/sysmlv2-model/src/rational.rs @@ -0,0 +1,998 @@ +//! Exact rational numbers for expression evaluation. +//! +//! A [`Rational`] is a fraction in lowest terms with a positive +//! denominator. Values whose numerator and denominator fit 128 bits stay +//! inline; an operation that overflows moves to heap-allocated big +//! integers, and a result that fits again returns inline. Every +//! arithmetic result is exact regardless of magnitude, so `0.1 + 0.2` is +//! `3/10` and `100 * 1.1` is `110`. +//! +//! Text forms: a terminating decimal prints exactly (`0.3`, `110`); +//! anything else prints as a reduced fraction (`1/3`). Both spellings are +//! valid KerML expressions. + +use std::cmp::Ordering; +use std::fmt; +use std::hash::{Hash, Hasher}; + +use num_bigint::BigInt; +use num_integer::Integer as _; +use num_rational::{BigRational, Ratio}; +use num_traits::{CheckedAdd, CheckedDiv, CheckedMul, CheckedSub, One, Signed, ToPrimitive, Zero}; + +type Small = Ratio; + +/// An exact rational number in lowest terms. +#[derive(Clone)] +pub struct Rational(Repr); + +#[derive(Clone)] +enum Repr { + /// Reduced, positive denominator, neither component `i128::MIN`. + Small(Small), + /// Reduced, positive denominator, does not fit [`Repr::Small`]. + Big(Box), +} + +/// The largest bit size a power may produce, and the size beyond which +/// the evaluator refuses an exact result: about 315,000 decimal digits. +/// Past it a power reports `None` and callers degrade to an approximate +/// result instead of allocating without bound. +pub const MAX_BITS: u64 = 1 << 20; +/// Largest exponent magnitude accepted by [`Rational::parse_decimal`]. +const MAX_DECIMAL_EXPONENT: i64 = 100_000; + +fn fits_small(n: i128, d: i128) -> bool { + n != i128::MIN && d != i128::MIN +} + +impl Rational { + /// The integer `i` as a rational. + #[must_use] + pub fn from_integer(i: i128) -> Rational { + if i == i128::MIN { + return Self::from_big(BigRational::from_integer(BigInt::from(i))); + } + Rational(Repr::Small(Small::new_raw(i, 1))) + } + + /// `num / den`, reduced; `None` when `den` is zero. + #[must_use] + pub fn new(num: i128, den: i128) -> Option { + if den == 0 { + return None; + } + if !fits_small(num, den) { + return Some(Self::from_big(BigRational::new(num.into(), den.into()))); + } + Some(Self::small(Small::new(num, den))) + } + + /// Zero. + #[must_use] + pub fn zero() -> Rational { + Self::from_integer(0) + } + + /// One. + #[must_use] + pub fn one() -> Rational { + Self::from_integer(1) + } + + fn small(r: Small) -> Rational { + if fits_small(*r.numer(), *r.denom()) { + Rational(Repr::Small(r)) + } else { + Self::from_big(BigRational::new_raw( + BigInt::from(*r.numer()), + BigInt::from(*r.denom()), + )) + } + } + + /// A reduced big rational, demoted to the inline form when it fits. + fn from_big(b: BigRational) -> Rational { + if let (Some(n), Some(d)) = (b.numer().to_i128(), b.denom().to_i128()) { + if fits_small(n, d) { + return Rational(Repr::Small(Small::new_raw(n, d))); + } + } + Rational(Repr::Big(Box::new(b))) + } + + /// The exact big-integer form of an integer. + #[must_use] + pub fn from_bigint(i: BigInt) -> Rational { + Self::from_big(BigRational::from_integer(i)) + } + + fn to_big(&self) -> BigRational { + match &self.0 { + Repr::Small(r) => { + BigRational::new_raw(BigInt::from(*r.numer()), BigInt::from(*r.denom())) + } + Repr::Big(b) => (**b).clone(), + } + } + + /// Parse a decimal spelling exactly: an optional sign, digits with an + /// optional fraction (`12`, `1.5`, `.5`, `5.`), and an optional + /// decimal exponent (`1e-3`, `2.957353E-05`). No intermediate + /// double is involved. `None` for any other text, and for exponents + /// whose magnitude exceeds 100000. + #[must_use] + pub fn parse_decimal(s: &str) -> Option { + let s = s.trim(); + let (neg, s) = match s.strip_prefix('-') { + Some(rest) => (true, rest), + None => (false, s.strip_prefix('+').unwrap_or(s)), + }; + let (mantissa, exp) = match s.find(['e', 'E']) { + Some(i) => (&s[..i], s[i + 1..].parse::().ok()?), + None => (s, 0i64), + }; + let (int_part, frac_part) = match mantissa.split_once('.') { + Some((a, b)) => (a, b), + None => (mantissa, ""), + }; + if int_part.is_empty() && frac_part.is_empty() { + return None; + } + if !int_part.bytes().all(|b| b.is_ascii_digit()) + || !frac_part.bytes().all(|b| b.is_ascii_digit()) + { + return None; + } + let scale = exp.checked_sub(frac_part.len() as i64)?; + if scale.abs() > MAX_DECIMAL_EXPONENT { + return None; + } + let mut digits = String::with_capacity(int_part.len() + frac_part.len()); + digits.push_str(int_part); + digits.push_str(frac_part); + let digits = digits.trim_start_matches('0'); + if digits.is_empty() { + return Some(Rational::zero()); + } + // Inline fast path: up to 38 significant digits and a power of + // ten that fits `i128` (10^38 does). + if digits.len() <= 38 && scale.unsigned_abs() <= 38 { + if let Ok(m) = digits.parse::() { + let p = 10i128.pow(scale.unsigned_abs() as u32); + let r = if scale >= 0 { + m.checked_mul(p).map(|n| Small::new_raw(n, 1)) + } else { + Some(Small::new(m, p)) + }; + if let Some(r) = r { + let r = Self::small(r); + return Some(if neg { r.neg() } else { r }); + } + } + } + let m = BigInt::parse_bytes(digits.as_bytes(), 10)?; + let p = BigInt::from(10u32).pow(scale.unsigned_abs() as u32); + let b = if scale >= 0 { + BigRational::from_integer(m * p) + } else { + BigRational::new(m, p) + }; + let r = Self::from_big(b); + Some(if neg { r.neg() } else { r }) + } + + /// Parse either spelling this type prints: a decimal (`0.3`, `110`, + /// `2.957353E-05`) or a fraction of two decimals (`1/3`, `-500000/3183`). + /// `None` for any other text or a zero denominator. The inverse of + /// [`fmt::Display`], so a printed value reads back exactly. + #[must_use] + pub fn parse(s: &str) -> Option { + match s.trim().split_once('/') { + None => Self::parse_decimal(s), + Some((n, d)) => Self::parse_decimal(n)?.div(&Self::parse_decimal(d)?), + } + } + + /// `self ** k`, exact when the result is representable, otherwise the + /// exact value of the nearest double power, and one only when even + /// that is not finite. For unit scales, which must always compose. + #[must_use] + pub fn pow_or_approx(&self, k: i32) -> Rational { + self.pow(k) + .or_else(|| Rational::from_f64(self.to_f64().powi(k))) + .unwrap_or_else(Rational::one) + } + + /// `self ** (p/q)`: exact when the root exists, otherwise the exact + /// value of the nearest double power, and one only when even that is + /// not finite. For unit scales, which must always compose. + #[must_use] + pub fn pow_ratio_or_approx(&self, (p, q): (i32, i32)) -> Rational { + Rational::new(p as i128, q as i128) + .and_then(|e| self.pow_rational(&e)) + .or_else(|| Rational::from_f64(self.to_f64().powf(p as f64 / q as f64))) + .unwrap_or_else(Rational::one) + } + + /// The exact value of a finite double (every finite double is a + /// dyadic rational); `None` for infinities and NaN. + pub fn from_f64(f: f64) -> Option { + if !f.is_finite() { + return None; + } + // Fast path: integral doubles of moderate size. + if f.fract() == 0.0 && f.abs() < 1e30 { + return Some(Self::from_integer(f as i128)); + } + BigRational::from_float(f).map(Self::from_big) + } + + /// The nearest double (correctly rounded); `±inf` beyond the double + /// range. + #[must_use] + pub fn to_f64(&self) -> f64 { + let f = match &self.0 { + Repr::Small(r) => r.to_f64(), + Repr::Big(b) => b.to_f64(), + }; + f.unwrap_or_else(|| { + if self.is_negative() { + f64::NEG_INFINITY + } else { + f64::INFINITY + } + }) + } + + /// The tightest pair of doubles `(lo, hi)` with `lo <= self <= hi`: + /// a point when the value is a double, otherwise two adjacent + /// doubles. Values beyond the double range enclose against the + /// largest finite double and the matching infinity. + #[must_use] + pub fn to_f64_enclosure(&self) -> (f64, f64) { + let f = self.to_f64(); + if f == f64::INFINITY { + return (f64::MAX, f64::INFINITY); + } + if f == f64::NEG_INFINITY { + return (f64::NEG_INFINITY, f64::MIN); + } + match Rational::from_f64(f).map(|exact| exact.cmp(self)) { + Some(Ordering::Equal) | None => (f, f), + Some(Ordering::Less) => (f, f.next_up()), + Some(Ordering::Greater) => (f.next_down(), f), + } + } + + /// Whether the denominator is 1. + #[must_use] + pub fn is_integer(&self) -> bool { + match &self.0 { + Repr::Small(r) => *r.denom() == 1, + Repr::Big(b) => b.is_integer(), + } + } + + /// The value as an `i128` when it is an integer in range. + #[must_use] + pub fn to_i128(&self) -> Option { + match &self.0 { + Repr::Small(r) if *r.denom() == 1 => Some(*r.numer()), + _ => None, + } + } + + /// The value as a big integer when it is an integer. + #[must_use] + pub fn to_bigint(&self) -> Option { + match &self.0 { + Repr::Small(r) if *r.denom() == 1 => Some(BigInt::from(*r.numer())), + Repr::Big(b) if b.is_integer() => Some(b.numer().clone()), + _ => None, + } + } + + /// Numerator and denominator as `i128` when both fit. + #[must_use] + pub fn to_i128_parts(&self) -> Option<(i128, i128)> { + match &self.0 { + Repr::Small(r) => Some((*r.numer(), *r.denom())), + Repr::Big(_) => None, + } + } + + /// Numerator and denominator as `i32` when both fit. + #[must_use] + pub fn to_i32_parts(&self) -> Option<(i32, i32)> { + let (n, d) = self.to_i128_parts()?; + Some((i32::try_from(n).ok()?, i32::try_from(d).ok()?)) + } + + /// Numerator and denominator as decimal strings (denominator positive). + #[must_use] + pub fn to_string_parts(&self) -> (String, String) { + match &self.0 { + Repr::Small(r) => (r.numer().to_string(), r.denom().to_string()), + Repr::Big(b) => (b.numer().to_string(), b.denom().to_string()), + } + } + + #[must_use] + pub fn is_zero(&self) -> bool { + match &self.0 { + Repr::Small(r) => r.numer().is_zero(), + Repr::Big(b) => b.is_zero(), + } + } + + #[must_use] + pub fn is_negative(&self) -> bool { + match &self.0 { + Repr::Small(r) => r.numer().is_negative(), + Repr::Big(b) => b.is_negative(), + } + } + + #[must_use] + pub fn is_positive(&self) -> bool { + match &self.0 { + Repr::Small(r) => r.numer().is_positive(), + Repr::Big(b) => b.is_positive(), + } + } + + #[must_use] + pub fn is_one(&self) -> bool { + match &self.0 { + Repr::Small(r) => r.is_one(), + Repr::Big(b) => b.is_one(), + } + } + + fn binary( + &self, + o: &Rational, + small: impl Fn(&Small, &Small) -> Option, + big: impl Fn(&BigRational, &BigRational) -> BigRational, + ) -> Rational { + if let (Repr::Small(a), Repr::Small(b)) = (&self.0, &o.0) { + if let Some(r) = small(a, b) { + return Self::small(r); + } + } + Self::from_big(big(&self.to_big(), &o.to_big())) + } + + #[must_use] + pub fn add(&self, o: &Rational) -> Rational { + self.binary(o, |a, b| a.checked_add(b), |a, b| a + b) + } + + #[must_use] + pub fn sub(&self, o: &Rational) -> Rational { + self.binary(o, |a, b| a.checked_sub(b), |a, b| a - b) + } + + #[must_use] + pub fn mul(&self, o: &Rational) -> Rational { + self.binary(o, |a, b| a.checked_mul(b), |a, b| a * b) + } + + /// `self / o`; `None` when `o` is zero. + #[must_use] + pub fn div(&self, o: &Rational) -> Option { + if o.is_zero() { + return None; + } + Some(self.binary(o, |a, b| a.checked_div(b), |a, b| a / b)) + } + + /// Truncated remainder `self - o * trunc(self / o)`; `None` when `o` + /// is zero. + #[must_use] + pub fn rem(&self, o: &Rational) -> Option { + let q = self.div(o)?.trunc(); + Some(self.sub(&o.mul(&q))) + } + + #[must_use] + pub fn neg(&self) -> Rational { + match &self.0 { + Repr::Small(r) => Rational(Repr::Small(Small::new_raw(-r.numer(), *r.denom()))), + Repr::Big(b) => Self::from_big(-(**b).clone()), + } + } + + #[must_use] + pub fn abs(&self) -> Rational { + if self.is_negative() { + self.neg() + } else { + self.clone() + } + } + + /// `1 / self`; `None` for zero. + #[must_use] + pub fn recip(&self) -> Option { + Rational::one().div(self) + } + + #[must_use] + pub fn trunc(&self) -> Rational { + match &self.0 { + Repr::Small(r) => Self::small(r.trunc()), + Repr::Big(b) => Self::from_big(b.trunc()), + } + } + + #[must_use] + pub fn floor(&self) -> Rational { + match &self.0 { + Repr::Small(r) => Self::small(r.floor()), + Repr::Big(b) => Self::from_big(b.floor()), + } + } + + #[must_use] + pub fn ceil(&self) -> Rational { + match &self.0 { + Repr::Small(r) => Self::small(r.ceil()), + Repr::Big(b) => Self::from_big(b.ceil()), + } + } + + /// Round half away from zero. + #[must_use] + pub fn round(&self) -> Rational { + match &self.0 { + Repr::Small(r) => Self::small(r.round()), + Repr::Big(b) => Self::from_big(b.round()), + } + } + + /// Bits needed for the larger of numerator and denominator: the size + /// a value occupies, for budgets. + #[must_use] + pub fn bits(&self) -> u64 { + match &self.0 { + Repr::Small(r) => { + let n = r.numer().unsigned_abs(); + let d = r.denom().unsigned_abs(); + (128 - n.max(d).leading_zeros()) as u64 + } + Repr::Big(b) => b.numer().bits().max(b.denom().bits()), + } + } + + /// `self ** e` for an integer exponent; `None` for `0 ** negative` + /// and for results too large to materialize. + #[must_use] + pub fn pow(&self, e: i32) -> Option { + if e < 0 { + return self.recip()?.pow(e.checked_neg()?); + } + if e == 0 { + return Some(Rational::one()); + } + let e = e as u32; + if self.bits().checked_mul(e as u64)? > MAX_BITS { + return None; + } + if let Repr::Small(r) = &self.0 { + if let (Some(n), Some(d)) = (r.numer().checked_pow(e), r.denom().checked_pow(e)) { + return Some(Self::small(Small::new_raw(n, d))); + } + } + let b = self.to_big(); + Some(Self::from_big(BigRational::new_raw( + b.numer().pow(e), + b.denom().pow(e), + ))) + } + + /// The exact `n`-th root when one exists (`root(4, 2)` is `2`, + /// `root(-8, 3)` is `-2`, `root(1/4, 2)` is `1/2`); `None` when the + /// value is not a perfect power, `n` is zero, or the value is + /// negative with an even `n`. + #[must_use] + pub fn root(&self, n: u32) -> Option { + if n == 0 { + return None; + } + if n == 1 { + return Some(self.clone()); + } + if self.is_negative() { + if n.is_multiple_of(2) { + return None; + } + return Some(self.neg().root(n)?.neg()); + } + let b = self.to_big(); + let exact_root = |x: &BigInt| { + let r = x.nth_root(n); + (r.pow(n) == *x).then_some(r) + }; + let num = exact_root(b.numer())?; + let den = exact_root(b.denom())?; + Some(Self::from_big(BigRational::new_raw(num, den))) + } + + /// `self ** (p/q)` exactly when the root exists. + #[must_use] + pub fn pow_rational(&self, exp: &Rational) -> Option { + let (p, q) = exp.to_i32_parts()?; + let base = self.root(u32::try_from(q).ok()?)?; + base.pow(p) + } + + /// The exact decimal expansion when it terminates: `(negative, + /// digits, fraction_len)` with `digits` free of a leading zero unless + /// the integer part is zero. + fn decimal_parts(&self) -> Option<(bool, String, usize)> { + let (numer, denom): (BigInt, BigInt) = match &self.0 { + Repr::Small(r) => (BigInt::from(*r.numer()), BigInt::from(*r.denom())), + Repr::Big(b) => (b.numer().clone(), b.denom().clone()), + }; + if denom.is_one() { + return Some((numer.is_negative(), numer.abs().to_string(), 0)); + } + let two = BigInt::from(2u32); + let five = BigInt::from(5u32); + let mut d = denom; + let mut twos = 0u32; + let mut fives = 0u32; + while d.is_even() { + d /= &two; + twos += 1; + } + loop { + let (q, r) = d.div_rem(&five); + if !r.is_zero() { + break; + } + d = q; + fives += 1; + } + if !d.is_one() { + return None; + } + let k = twos.max(fives); + let m = numer.abs() * two.pow(k - twos) * five.pow(k - fives); + let mut s = m.to_string(); + let k = k as usize; + if s.len() <= k { + s = format!("{}{}", "0".repeat(k + 1 - s.len()), s); + } + Some((numer.is_negative(), s, k)) + } + + /// The exact decimal spelling when the expansion terminates. + #[must_use] + pub fn to_decimal_string(&self) -> Option { + let (neg, digits, k) = self.decimal_parts()?; + let mut out = String::with_capacity(digits.len() + 2); + if neg { + out.push('-'); + } + if k == 0 { + out.push_str(&digits); + } else { + let split = digits.len() - k; + out.push_str(&digits[..split]); + out.push('.'); + out.push_str(&digits[split..]); + } + Some(out) + } + + /// A display spelling that is always a decimal: the exact decimal + /// when the expansion terminates, otherwise the shortest spelling of + /// the nearest double marked as approximate (`≈0.3333333333333333`). + /// For surfaces that favour a glanceable number over a re-parseable + /// one; [`fmt::Display`] stays exact. + #[must_use] + pub fn to_approx_string(&self) -> String { + match self.to_decimal_string() { + Some(s) => s, + None => format!("≈{}", self.to_f64()), + } + } + + /// Whether printing this value as a JSON number literal loses + /// nothing: the spelling is an integer or a terminating decimal that + /// a double's shortest round-trip spelling reproduces exactly. A JSON + /// serializer may still spell that double with an exponent (`1e30`, + /// `1e-7`); the digits are the same, so the literal denotes exactly + /// this value. + #[must_use] + pub fn json_number_is_exact(&self) -> bool { + let Some(dec) = self.to_decimal_string() else { + return false; + }; + let f = self.to_f64(); + if !f.is_finite() { + return false; + } + let shortest = if f.fract() == 0.0 && f.abs() < 1e16 { + format!("{}", f as i64) + } else { + format!("{f}") + }; + shortest == dec + } +} + +impl Default for Rational { + fn default() -> Self { + Rational::zero() + } +} + +impl fmt::Display for Rational { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match self.to_decimal_string() { + Some(s) => f.write_str(&s), + None => { + let (n, d) = self.to_string_parts(); + write!(f, "{n}/{d}") + } + } + } +} + +impl fmt::Debug for Rational { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + let (n, d) = self.to_string_parts(); + write!(f, "Rational({n}/{d})") + } +} + +impl PartialEq for Rational { + fn eq(&self, other: &Rational) -> bool { + match (&self.0, &other.0) { + (Repr::Small(a), Repr::Small(b)) => a == b, + (Repr::Big(a), Repr::Big(b)) => a == b, + _ => false, + } + } +} + +impl Eq for Rational {} + +impl PartialOrd for Rational { + fn partial_cmp(&self, other: &Rational) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for Rational { + fn cmp(&self, other: &Rational) -> Ordering { + match (&self.0, &other.0) { + (Repr::Small(a), Repr::Small(b)) => a.cmp(b), + _ => self.to_big().cmp(&other.to_big()), + } + } +} + +impl Hash for Rational { + fn hash(&self, state: &mut H) { + match &self.0 { + Repr::Small(r) => { + 0u8.hash(state); + r.numer().hash(state); + r.denom().hash(state); + } + Repr::Big(b) => { + 1u8.hash(state); + b.numer().hash(state); + b.denom().hash(state); + } + } + } +} + +impl From for Rational { + fn from(i: i128) -> Self { + Rational::from_integer(i) + } +} + +impl From for Rational { + fn from(i: i64) -> Self { + Rational::from_integer(i as i128) + } +} + +impl From for Rational { + fn from(i: i32) -> Self { + Rational::from_integer(i as i128) + } +} + +impl From for Rational { + fn from(i: u32) -> Self { + Rational::from_integer(i as i128) + } +} + +impl serde::Serialize for Rational { + fn serialize(&self, s: S) -> Result { + self.to_string_parts().serialize(s) + } +} + +impl<'de> serde::Deserialize<'de> for Rational { + fn deserialize>(d: D) -> Result { + let (n, den): (String, String) = serde::Deserialize::deserialize(d)?; + let parse = |s: &str| { + BigInt::parse_bytes(s.as_bytes(), 10) + .ok_or_else(|| serde::de::Error::custom("malformed rational component")) + }; + let (n, den) = (parse(&n)?, parse(&den)?); + if !den.is_positive() { + return Err(serde::de::Error::custom( + "rational denominator must be positive", + )); + } + Ok(Rational::from_big(BigRational::new(n, den))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn dec(s: &str) -> Rational { + Rational::parse_decimal(s).unwrap() + } + + #[test] + fn decimal_literals_are_exact() { + assert_eq!(dec("0.1").add(&dec("0.2")), dec("0.3")); + assert_eq!(dec("0.1").add(&dec("0.2")), Rational::new(3, 10).unwrap()); + assert_eq!(dec("100").mul(&dec("1.1")), Rational::from_integer(110)); + assert_eq!(dec("1.1").mul(&dec("1.1")), dec("1.21")); + assert_eq!( + dec("2.957353E-05"), + Rational::new(2_957_353, 100_000_000_000).unwrap() + ); + assert_eq!(dec("1e30"), Rational::from_integer(10i128.pow(30))); + assert_eq!(dec(".5"), Rational::new(1, 2).unwrap()); + assert_eq!(dec("5."), Rational::from_integer(5)); + assert_eq!(dec("-0.25"), Rational::new(-1, 4).unwrap()); + assert_eq!(dec("+7"), Rational::from_integer(7)); + assert_eq!(dec("000.000"), Rational::zero()); + assert!(Rational::parse_decimal("1e").is_none()); + assert!(Rational::parse_decimal("abc").is_none()); + assert!(Rational::parse_decimal("1.2.3").is_none()); + assert!(Rational::parse_decimal("").is_none()); + assert!(Rational::parse_decimal("1e999999").is_none()); + } + + #[test] + fn printed_spellings_parse_back() { + for text in ["0.3", "110", "-0.5", "1/3", "-500000/3183", "2.957353E-05"] { + let r = Rational::parse(text).unwrap(); + assert_eq!(Rational::parse(&r.to_string()), Some(r.clone()), "{text}"); + } + assert_eq!(Rational::parse("1.5/0.5"), Some(Rational::from_integer(3))); + assert_eq!(Rational::parse(" 2/4 "), Rational::new(1, 2)); + assert!(Rational::parse("1/0").is_none()); + assert!(Rational::parse("1/2/3").is_none()); + assert!(Rational::parse("a/b").is_none()); + let big = Rational::from_integer(i128::MAX).add(&Rational::one()); + assert_eq!(Rational::parse(&big.to_string()), Some(big)); + } + + #[test] + fn scale_powers_always_compose() { + assert_eq!(dec("0.001").pow_or_approx(3), dec("1e-9")); + assert_eq!( + dec("4").pow_ratio_or_approx((1, 2)), + Rational::from_integer(2) + ); + assert_eq!( + dec("8").pow_ratio_or_approx((-2, 3)), + Rational::new(1, 4).unwrap() + ); + // Beyond the exact bound the nearest double stands in. + let huge = dec("10").pow_or_approx(1_000_000); + assert_eq!( + huge, + Rational::from_f64(f64::INFINITY).unwrap_or_else(Rational::one) + ); + let root = dec("2").pow_ratio_or_approx((1, 2)); + assert_eq!(root, Rational::from_f64(std::f64::consts::SQRT_2).unwrap()); + assert!(dec("2").pow_ratio_or_approx((1, 0)).is_one()); + } + + #[test] + fn big_literals_round_trip() { + let big = dec("123456789012345678901234567890123456789012345678901234567890"); + assert!(big.to_i128().is_none()); + assert!(big.is_integer()); + assert_eq!( + big.to_string(), + "123456789012345678901234567890123456789012345678901234567890" + ); + let tiny = dec("1.602176634e-19"); + assert_eq!(tiny.to_string(), "0.0000000000000000001602176634"); + assert_eq!(tiny.mul(&dec("1e19")), dec("1.602176634")); + } + + #[test] + fn display_terminating_or_fraction() { + assert_eq!(dec("0.3").to_string(), "0.3"); + assert_eq!(dec("110.0").to_string(), "110"); + assert_eq!(dec("-0.5").to_string(), "-0.5"); + assert_eq!(dec("0.000123").to_string(), "0.000123"); + assert_eq!(Rational::new(1, 3).unwrap().to_string(), "1/3"); + assert_eq!(Rational::new(-2, 6).unwrap().to_string(), "-1/3"); + assert_eq!(Rational::new(1, 8).unwrap().to_string(), "0.125"); + assert_eq!(Rational::new(1, 25).unwrap().to_string(), "0.04"); + assert_eq!(Rational::new(7, 2).unwrap().to_string(), "3.5"); + assert_eq!( + Rational::new(500_000, 3183).unwrap().to_string(), + "500000/3183" + ); + assert_eq!(Rational::zero().to_string(), "0"); + } + + #[test] + fn overflow_promotes_and_demotes() { + let big = Rational::from_integer(i128::MAX).add(&Rational::one()); + assert!(big.to_i128().is_none()); + assert_eq!(big.to_string(), "170141183460469231731687303715884105728"); + let back = big.sub(&Rational::one()); + assert_eq!(back.to_i128(), Some(i128::MAX)); + let min = Rational::from_integer(i128::MIN); + assert_eq!( + min.neg().to_string(), + "170141183460469231731687303715884105728" + ); + assert_eq!(min.abs().neg(), min); + let product = Rational::from_integer(i128::MAX).mul(&Rational::from_integer(i128::MAX)); + assert_eq!( + product + .div(&Rational::from_integer(i128::MAX)) + .unwrap() + .to_i128(), + Some(i128::MAX) + ); + // Rational overflow in the sum of two small fractions. + let a = Rational::new(1, i128::MAX).unwrap(); + let b = Rational::new(1, i128::MAX - 1).unwrap(); + let s = a.add(&b); + assert_eq!(s.sub(&b), a); + } + + #[test] + fn powers_and_roots() { + assert_eq!(dec("2").pow(10).unwrap(), Rational::from_integer(1024)); + assert_eq!(dec("2").pow(-2).unwrap(), Rational::new(1, 4).unwrap()); + assert_eq!(dec("0.5").pow(3).unwrap(), dec("0.125")); + assert!(Rational::zero().pow(-1).is_none()); + assert_eq!(dec("2").pow(200).unwrap().to_string().len(), 61); + assert!(dec("2").pow(i32::MAX).is_none()); + assert_eq!(dec("9").root(2).unwrap(), Rational::from_integer(3)); + assert_eq!(dec("0.25").root(2).unwrap(), dec("0.5")); + assert_eq!(dec("-8").root(3).unwrap(), Rational::from_integer(-2)); + assert!(dec("2").root(2).is_none()); + assert!(dec("-4").root(2).is_none()); + assert_eq!( + dec("8") + .pow_rational(&Rational::new(2, 3).unwrap()) + .unwrap(), + Rational::from_integer(4) + ); + assert_eq!( + dec("4") + .pow_rational(&Rational::new(-1, 2).unwrap()) + .unwrap(), + dec("0.5") + ); + } + + #[test] + fn rounding_family() { + assert_eq!(dec("2.5").floor(), Rational::from_integer(2)); + assert_eq!(dec("2.5").ceil(), Rational::from_integer(3)); + assert_eq!(dec("2.5").round(), Rational::from_integer(3)); + assert_eq!(dec("-2.5").round(), Rational::from_integer(-3)); + assert_eq!(dec("-2.5").trunc(), Rational::from_integer(-2)); + assert_eq!(dec("7").rem(&dec("2")).unwrap(), Rational::one()); + assert_eq!(dec("7.5").rem(&dec("2")).unwrap(), dec("1.5")); + assert_eq!( + dec("-7").rem(&dec("2")).unwrap(), + Rational::from_integer(-1) + ); + assert!(dec("1").rem(&Rational::zero()).is_none()); + } + + #[test] + fn double_conversion_is_correctly_rounded_and_enclosed() { + assert_eq!(dec("0.1").to_f64(), 0.1); + assert_eq!(dec("0.3").to_f64(), 0.3); + assert_eq!(Rational::new(1, 3).unwrap().to_f64(), 1.0 / 3.0); + assert_eq!( + Rational::from_f64(0.1).unwrap().to_string(), + "0.1000000000000000055511151231257827021181583404541015625" + ); + assert_eq!(Rational::from_f64(-2.5).unwrap(), dec("-2.5")); + assert!(Rational::from_f64(f64::INFINITY).is_none()); + assert_eq!(dec("0.5").to_f64_enclosure(), (0.5, 0.5)); + let (lo, hi) = dec("0.1").to_f64_enclosure(); + assert!(lo < hi); + assert_eq!(hi, lo.next_up()); + assert!(Rational::from_f64(lo).unwrap() < dec("0.1")); + assert!(Rational::from_f64(hi).unwrap() > dec("0.1")); + let huge = dec("1e400"); + assert_eq!(huge.to_f64(), f64::INFINITY); + assert_eq!(huge.to_f64_enclosure(), (f64::MAX, f64::INFINITY)); + assert_eq!(huge.neg().to_f64_enclosure(), (f64::NEG_INFINITY, f64::MIN)); + } + + #[test] + fn ordering_and_equality_across_representations() { + let big = Rational::from_integer(i128::MAX).add(&Rational::one()); + assert!(big > Rational::from_integer(i128::MAX)); + assert!(Rational::new(1, 3).unwrap() < dec("0.34")); + assert!(dec("-1e40") < Rational::from_integer(0)); + assert_eq!(dec("0.10"), dec("0.1")); + assert_ne!(dec("0.1"), Rational::from_f64(0.1).unwrap()); + use std::collections::HashSet; + let set: HashSet = [dec("0.1"), dec("0.10"), dec("1e-1")].into_iter().collect(); + assert_eq!(set.len(), 1); + } + + #[test] + fn approx_text_is_decimal_and_marked() { + assert_eq!(dec("0.3").to_approx_string(), "0.3"); + assert_eq!(dec("110").to_approx_string(), "110"); + assert_eq!( + Rational::new(1, 3).unwrap().to_approx_string(), + "≈0.3333333333333333" + ); + assert_eq!( + Rational::new(500_000, 3183).unwrap().to_approx_string(), + "≈157.08451146716934" + ); + assert_eq!( + Rational::new(-2, 3).unwrap().to_approx_string(), + "≈-0.6666666666666666" + ); + } + + #[test] + fn json_exactness_probe() { + assert!(dec("0.1").json_number_is_exact()); + assert!(dec("0.3").json_number_is_exact()); + assert!(dec("110").json_number_is_exact()); + assert!(dec("1e30").json_number_is_exact()); + assert!(!Rational::new(1, 3).unwrap().json_number_is_exact()); + assert!( + !dec("0.1000000000000000055511151231257827021181583404541015625") + .json_number_is_exact() + ); + assert!(!dec("0.30000000000000004000000001").json_number_is_exact()); + } + + #[test] + fn serde_round_trip() { + for r in [ + dec("0.1"), + Rational::new(-1, 3).unwrap(), + dec("1e50"), + Rational::zero(), + ] { + let json = serde_json::to_string(&r).unwrap(); + let back: Rational = serde_json::from_str(&json).unwrap(); + assert_eq!(back, r); + } + assert!(serde_json::from_str::(r#"["1","0"]"#).is_err()); + assert!(serde_json::from_str::(r#"["1","-2"]"#).is_err()); + } +} diff --git a/crates/sysmlv2-model/src/render.rs b/crates/sysmlv2-model/src/render.rs index 0d7c6c4..02517ff 100644 --- a/crates/sysmlv2-model/src/render.rs +++ b/crates/sysmlv2-model/src/render.rs @@ -279,7 +279,8 @@ fn truthy(v: &Value) -> bool { match v { Value::Boolean(b) => *b, Value::Integer(i) => *i != 0, - Value::Rational(f) => *f != 0.0, + Value::Rational(r) => !r.is_zero(), + Value::Real(f) => *f != 0.0, Value::String(s) => !s.is_empty(), Value::Sequence(items) => !items.is_empty(), Value::Indeterminate => false, @@ -318,9 +319,9 @@ impl ResolvedModel { fn bound_text(&mut self, e: ElementRef, name: &str) -> Option { match self.evaluate_chain(e, &[&qn(name)]) { Ok(Value::String(s)) => Some(s), - Ok(v @ (Value::Integer(_) | Value::Rational(_) | Value::Boolean(_))) => { - Some(self.render_value(&v)) - } + Ok( + v @ (Value::Integer(_) | Value::Rational(_) | Value::Real(_) | Value::Boolean(_)), + ) => Some(self.render_value(&v)), _ => None, } } @@ -383,6 +384,12 @@ impl ResolvedModel { /// Render the tree a `view` usage presents: its exposed elements bind /// the rendering's inputs. Returns the rendered nodes of the root. + /// + /// Rendering errors are messages rather than a type throughout this + /// module: each one names a specific thing the view's own text is + /// missing or has wrong, for a reader to act on, and every caller + /// passes it straight to one — a command-line message, a rejected + /// call in a host binding. pub fn render_view(&mut self, view: ElementRef) -> Result, String> { // Annotations (documentation, comments, textual representations) // are members too, but never a template's subject matter. @@ -398,7 +405,7 @@ impl ResolvedModel { .map(Value::Element) .collect(); let root = self.view_template_root(view)?; - self.render_root(root, Value::Sequence(exposed)) + self.render_root(root, &Value::Sequence(exposed)) } /// The `Root` usage of the rendering a view (or its definition) names. @@ -453,7 +460,7 @@ impl ResolvedModel { pub fn render_root( &mut self, root: ElementRef, - exposed: Value, + exposed: &Value, ) -> Result, String> { let kinds = self.kinds()?; let mut env: Vec<(String, Value)> = vec![("exposed".into(), exposed.clone())]; @@ -464,7 +471,7 @@ impl ResolvedModel { }; let mut first = true; for input in inputs { - let (Value::Element(e) | Value::Unbound(e)) = input else { + let (Value::Element(e) | Value::Unbound(e) | Value::UnboundMember(e)) = input else { continue; }; let Some(name) = self.bound_text(e, "name") else { diff --git a/crates/sysmlv2-model/src/semantic_memo.rs b/crates/sysmlv2-model/src/semantic_memo.rs new file mode 100644 index 0000000..a1ffd26 --- /dev/null +++ b/crates/sysmlv2-model/src/semantic_memo.rs @@ -0,0 +1,43 @@ +//! Context-independent semantic results tied to one resolved graph. Cached +//! lookups replay their import evidence; user graph rebuilds get fresh tables. +use crate::{eval::Dim, layered::LayeredMap, quantity::QuantityDims}; +use serde::{Deserialize, Serialize}; +#[derive(Clone, Serialize, Deserialize)] +pub(crate) struct Proven { + pub value: T, + pub imports: Vec, +} +pub(crate) type UnitKey = (usize, usize, String, bool); +#[derive(Clone, Default, Serialize, Deserialize)] +pub(crate) struct SemanticMemo { + pub types: LayeredMap<(usize, bool), Proven>>, + pub definitions: LayeredMap<(usize, bool), Proven>>, + pub units: LayeredMap, crate::rational::Rational)>>, +} +impl SemanticMemo { + pub fn valid(&self, n: usize, scopes: usize) -> bool { + self.types + .iter() + .chain(self.definitions.iter()) + .all(|(&(e, _), proof)| { + e < n + && proof.imports.iter().all(|&i| i < n) + && proof.value.as_ref().is_none_or(|v| v.valid(n)) + }) + && self.units.iter().all(|((scope, e, _, _), proof)| { + *scope < scopes + && *e < n + && proof.imports.iter().all(|&i| i < n) + && proof + .value + .0 + .iter() + .all(|d| d.elem < n && d.num != 0 && d.den > 0) + }) + } + pub fn freeze(&mut self) { + self.types.freeze(); + self.definitions.freeze(); + self.units.freeze(); + } +} diff --git a/crates/sysmlv2-model/src/structure.rs b/crates/sysmlv2-model/src/structure.rs index d836812..a93c273 100644 --- a/crates/sysmlv2-model/src/structure.rs +++ b/crates/sysmlv2-model/src/structure.rs @@ -95,6 +95,10 @@ const WRAP_NAME: &str = "__sysmlStructure__"; /// The id-normalized structural digest of exactly one member's text /// (top-level form, as the canonical formatter emits it). Errors name /// the first parse diagnostic or the member-count violation. +/// +/// The error is a message rather than a type because every caller shows +/// it and none branches on it: a digest either describes the text or the +/// text is not one member. pub fn member_structure_digest(member_text: &str) -> Result { let probe = format!("package {WRAP_NAME} {{\n{member_text}\n}}"); let parse = parse_source(&probe); diff --git a/crates/sysmlv2-parser/Cargo.toml b/crates/sysmlv2-parser/Cargo.toml index 6776550..75f5e00 100644 --- a/crates/sysmlv2-parser/Cargo.toml +++ b/crates/sysmlv2-parser/Cargo.toml @@ -22,8 +22,8 @@ default = ["json"] json = ["dep:sysmlv2-model", "dep:serde_json"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0", optional = true } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0", optional = true } # for tests/examples that build serde_json values directly serde_json = { workspace = true, optional = true } diff --git a/crates/sysmlv2-parser/examples/derived_correspondence.rs b/crates/sysmlv2-parser/examples/derived_correspondence.rs new file mode 100644 index 0000000..0ac9fb1 --- /dev/null +++ b/crates/sysmlv2-parser/examples/derived_correspondence.rs @@ -0,0 +1,129 @@ +//! Write `spec-refs/derived-correspondence.json`: for every (concrete +//! metaclass, property) the interchange schema declares, whether the +//! abstract syntax owns or derives it, the derivation layer's fidelity at +//! the passthrough level and under the closure policy, the interchange +//! shape, and — for derived rows — the XMI's type and multiplicity. The +//! table a per-language SDK generator consumes (plan §33i); a consumer +//! keys on `fidelity`, never on corpus fill rate. +//! +//! Usage: `cargo run --example derived_correspondence` from the workspace +//! root (reads `spec-refs/derived-properties.json` for the XMI facts). + +use serde_json::{Map, Value, json}; +use std::collections::HashMap; +use sysmlv2_parser::json::{ + ClosurePolicy, Derives, PropertyShape, derives, derives_under, property_catalog, +}; + +fn fidelity(f: Derives) -> &'static str { + match f { + Derives::NotDeclared => "not-declared", + Derives::NotComputed => "not-computed", + Derives::Passthrough => "passthrough", + Derives::Exact => "exact", + } +} + +fn shape(s: PropertyShape) -> &'static str { + match s { + PropertyShape::Array => "array", + PropertyShape::Boolean => "boolean", + PropertyShape::Nullable => "nullable", + PropertyShape::Scalar => "scalar", + PropertyShape::Enumeration => "enumeration", + PropertyShape::RequiredReference => "required-reference", + _ => "other", + } +} + +fn main() { + let root = sysmlv2_testkit::workspace_root(); + let census: Value = serde_json::from_str( + &std::fs::read_to_string(root.join("spec-refs/derived-properties.json")) + .expect("spec-refs/derived-properties.json"), + ) + .unwrap(); + // (property name) -> declaring records, for the XMI type and + // multiplicity of a derived row (matched by the nearest declaring + // metaclass the concrete carrier conforms to — the first declaring + // record when several). + let mut declaring: HashMap> = HashMap::new(); + for record in census["properties"].as_array().unwrap() { + let name = record["name"].as_str().unwrap().to_string(); + declaring.insert(name, record["declaring"].as_array().unwrap().clone()); + } + let closure = ClosurePolicy::Closure { + include_implied: true, + }; + let mut rows: Vec = Vec::new(); + for entry in property_catalog() { + let mut row = Map::new(); + row.insert("metaclass".into(), json!(entry.metaclass)); + row.insert("property".into(), json!(entry.property)); + row.insert("shape".into(), json!(shape(entry.shape))); + row.insert("owned".into(), json!(entry.owned)); + if !entry.owned { + row.insert( + "fidelity".into(), + json!(fidelity(derives(entry.metaclass, entry.property))), + ); + row.insert( + "fidelityUnderClosure".into(), + json!(fidelity(derives_under( + entry.metaclass, + entry.property, + closure + ))), + ); + if let Some(decls) = declaring.get(entry.property) { + // The nearest declaring metaclass: of those the row's + // metaclass conforms to, the one that conforms to all the + // others. A row with no conforming declarer gets no XMI + // facts rather than a wrong declarer's. + let conforming: Vec<&Value> = decls + .iter() + .filter(|d| { + d["metaclass"].as_str().is_some_and(|m| { + sysmlv2_parser::json::metaclass_conforms(entry.metaclass, m) + }) + }) + .collect(); + let decl = conforming.iter().copied().find(|d| { + let m = d["metaclass"].as_str().unwrap(); + conforming.iter().all(|o| { + sysmlv2_parser::json::metaclass_conforms( + m, + o["metaclass"].as_str().unwrap(), + ) + }) + }); + if let Some(d) = decl { + row.insert("type".into(), d["type"].clone()); + row.insert("multiplicity".into(), d["multiplicity"].clone()); + row.insert("ordered".into(), d["ordered"].clone()); + row.insert("declaredOn".into(), d["metaclass"].clone()); + } + } + } + rows.push(Value::Object(row)); + } + let out = json!({ + "source": "the interchange schema catalog (SysML.schema.json 20250201) joined with spec-refs/derived-properties.json", + "generator": "cargo run --example derived_correspondence", + "note": "key on `fidelity` (not-computed / passthrough / exact), never on corpus fill rate; `fidelityUnderClosure` is the fidelity with ClosurePolicy::Closure in force", + "rows": rows, + }); + let path = root.join("spec-refs/derived-correspondence.json"); + std::fs::write(&path, serde_json::to_string_pretty(&out).unwrap() + "\n").unwrap(); + let derived = out["rows"] + .as_array() + .unwrap() + .iter() + .filter(|r| r["owned"] == false) + .count(); + println!( + "wrote {} ({} rows, {derived} derived)", + path.display(), + out["rows"].as_array().unwrap().len() + ); +} diff --git a/crates/sysmlv2-parser/examples/evalstats.rs b/crates/sysmlv2-parser/examples/evalstats.rs index 121d510..b988cf8 100644 --- a/crates/sysmlv2-parser/examples/evalstats.rs +++ b/crates/sysmlv2-parser/examples/evalstats.rs @@ -29,6 +29,7 @@ fn main() { sysmlv2_parser::eval::EvalError::Type(_) => "type error".into(), sysmlv2_parser::eval::EvalError::Cycle(_) => "cycle".into(), sysmlv2_parser::eval::EvalError::DivisionByZero => "div0".into(), + sysmlv2_parser::eval::EvalError::Budget(_) => "budget".into(), }; *by_err.entry(key).or_default() += 1; } diff --git a/crates/sysmlv2-parser/examples/failstats.rs b/crates/sysmlv2-parser/examples/failstats.rs index 3939486..edfe1bf 100644 --- a/crates/sysmlv2-parser/examples/failstats.rs +++ b/crates/sysmlv2-parser/examples/failstats.rs @@ -22,7 +22,7 @@ fn collect(dir: &Path, out: &mut Vec) { fn main() { let root = std::env::args() .nth(1) - .unwrap_or("spec-refs/SysML-v2-Release".into()); + .unwrap_or_else(|| "spec-refs/SysML-v2-Release".into()); let mut files = Vec::new(); collect(Path::new(&root), &mut files); files.sort(); diff --git a/crates/sysmlv2-parser/examples/fullcheck.rs b/crates/sysmlv2-parser/examples/fullcheck.rs index f29a37f..e2b2c38 100644 --- a/crates/sysmlv2-parser/examples/fullcheck.rs +++ b/crates/sysmlv2-parser/examples/fullcheck.rs @@ -59,7 +59,7 @@ fn main() { any = true; let key = format!( "{t} @ {}: {}", - err.instance_path, + err.instance_path(), err.to_string().chars().take(90).collect::() ); *messages.entry(key).or_default() += 1; diff --git a/crates/sysmlv2-parser/examples/liftcheck.rs b/crates/sysmlv2-parser/examples/liftcheck.rs index 05d4e35..5e97ab6 100644 --- a/crates/sysmlv2-parser/examples/liftcheck.rs +++ b/crates/sysmlv2-parser/examples/liftcheck.rs @@ -27,7 +27,7 @@ fn collect(dir: &Path, out: &mut Vec) { fn main() { let root = std::env::args() .nth(1) - .unwrap_or("spec-refs/SysML-v2-Release".into()); + .unwrap_or_else(|| "spec-refs/SysML-v2-Release".into()); let only = std::env::args().nth(2); let mut files = Vec::new(); collect(Path::new(&root), &mut files); diff --git a/crates/sysmlv2-parser/examples/opensysmlcheck.rs b/crates/sysmlv2-parser/examples/opensysmlcheck.rs new file mode 100644 index 0000000..72bbbd8 --- /dev/null +++ b/crates/sysmlv2-parser/examples/opensysmlcheck.rs @@ -0,0 +1,55 @@ +//! Run the pinned external negative corpus against the full standard library +//! and print the per-file stage diagnostics as JSON: +//! `cargo run --release --example opensysmlcheck > report.json`. +//! The same stages and classification are gated by +//! `tests/opensysml.rs::opensysml_library_diagnostic_baseline`; this is the +//! human-readable report, and it still fails on any registered contract +//! regression. +#[path = "../tests/support/census.rs"] +mod census; + +use std::{collections::BTreeMap, fs, path::Path}; +use sysmlv2_parser::model::Model; + +fn main() { + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml"); + let library = sysmlv2_testkit::library_dir(); + assert!( + library.is_dir(), + "initialize the standard-library submodule first" + ); + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + let prepared = base.prepare_library().expect("prepared library"); + let mut files = Vec::new(); + sysmlv2_testkit::collect_files(&root, &mut files); + files.sort(); + let mut rows = BTreeMap::new(); + for path in files { + let name = path + .strip_prefix(&root) + .unwrap() + .to_string_lossy() + .into_owned(); + let source = fs::read_to_string(&path).unwrap(); + let mut model = Model::new(); + prepared.clone().install(&mut model).unwrap(); + model.add_source(&name, &source); + rows.insert(name, census::stage_diagnostics(&model)); + } + println!("{}", serde_json::to_string_pretty(&rows).unwrap()); + let static_contracts: serde_json::Value = serde_json::from_str(include_str!( + "../tests/fixtures/opensysml/static-contracts.json" + )) + .unwrap(); + let negative_contracts: serde_json::Value = serde_json::from_str(include_str!( + "../tests/fixtures/opensysml/negative-contracts.json" + )) + .unwrap(); + let missing = census::contract_failures(&rows, &static_contracts, &negative_contracts); + assert!( + missing.is_empty(), + "intended-rule regressions: {}", + missing.join(", ") + ); +} diff --git a/crates/sysmlv2-parser/src/lib.rs b/crates/sysmlv2-parser/src/lib.rs index fcaf73f..924bf4f 100644 --- a/crates/sysmlv2-parser/src/lib.rs +++ b/crates/sysmlv2-parser/src/lib.rs @@ -12,11 +12,14 @@ //! crate keeps the original `sysmlv2_parser::…` paths stable. See the //! workspace `README.md` for the workspace architecture. -pub use sysmlv2_syntax::{Diagnostic, Span}; +pub use sysmlv2_syntax::{Diagnostic, Diagnostics, Span}; pub use sysmlv2_syntax::{ast, diag, lexer, name, parser, print, span, token, visit}; #[cfg(feature = "json")] -pub use sysmlv2_model::{ambient, eval, full, ids, json, libcache, lift, model, quantity, render}; +pub use sysmlv2_model::{ + ambient, eval, full, ids, json, libcache, lift, loader, model, prepared, quantity, rational, + render, +}; /// Post-parse validation: body-context legality (syntax-level) and — with /// the `json` feature — model-level referential checks. @@ -25,8 +28,9 @@ pub mod check { #[cfg(feature = "json")] pub use sysmlv2_model::check::{ - ConstraintBinding, ConstraintCheck, ConstraintVerdict, check_constraints, - constraint_bindings, satisfaction_checks, validate_model, validate_model_with, - validate_semantics, validate_semantics_with, + ConstraintBinding, ConstraintCheck, ConstraintVerdict, + IMPLEMENTED_NORMATIVE_SEMANTIC_RULES, check_constraints, constraint_bindings, + satisfaction_checks, validate_model, validate_model_with, validate_semantics, + validate_semantics_with, }; } diff --git a/crates/sysmlv2-parser/tests/apollo.rs b/crates/sysmlv2-parser/tests/apollo.rs index 279fa53..6539f0e 100644 --- a/crates/sysmlv2-parser/tests/apollo.rs +++ b/crates/sysmlv2-parser/tests/apollo.rs @@ -62,7 +62,7 @@ fn apollo_parses_and_validates() { } } -/// Referential + semantic checks over the resolved model: zero findings +/// Referential + semantic checks pin the known upstream model defects. /// (the one pre-fix unresolved reference was the recursive-rollup chain, /// resolved since — see `tests/check.rs::recursive_rollup_chain_member_resolves`). #[test] @@ -70,23 +70,28 @@ fn apollo_checks_clean() { let files = apollo_or_skip!(); let model = apollo_model(&files); assert!(!model.has_errors()); - let findings: Vec<_> = validate_model(&model) + let findings = validate_model(&model) .into_iter() - .chain(validate_semantics(&model)) - .collect(); + .chain(validate_semantics(&model)); // The invocation-arity check flags exactly the model's three genuine // under-application defects: both // `calculateDeltaV` call sites (4 params, 3 arguments — `mf` never // bound) and the `ln` shim call (their `calc naturalLogarithm` - // declares two parameters). Nothing else may fire. + // declares two parameters). The dimensional defect is pinned separately. let (arity, rest): (Vec<_>, Vec<_>) = findings .into_iter() .partition(|(_, d)| d.message.contains("binds")); - assert!( - rest.is_empty(), - "{} non-arity findings, first: {:?}", - rest.len(), - rest[0].1 + // The LOI calculation adds speed squared to force / length because + // mu_Moon is declared as ISQ::force. A gravitational parameter needs + // length cubed / time squared. OpenSysML independently reports this. + assert_eq!( + rest.iter() + .map(|(unit, d)| (model.units()[*unit].name.as_str(), d.message.as_str())) + .collect::>(), + vec![( + "CalculationsPackage.sysml", + "expression combines incompatible quantity dimensions `L^2*T^-2` and `M*T^-2`" + )] ); let n_deltav = arity .iter() diff --git a/crates/sysmlv2-parser/tests/check.rs b/crates/sysmlv2-parser/tests/check.rs index 6e2f2fd..fc7623e 100644 --- a/crates/sysmlv2-parser/tests/check.rs +++ b/crates/sysmlv2-parser/tests/check.rs @@ -497,6 +497,42 @@ fn referential_unresolved_reference() { assert!(model_warnings("package P { part def V; part x : V; }").is_empty()); } +/// A `doc`, `comment`, `rep`, or `dependency` written with an +/// identification is an owned member of its namespace under that name, +/// so an `about` clause reaches it by local name, short name, or +/// qualified name — exactly like a type or feature member. +#[test] +fn referential_named_annotating_elements() { + assert!( + model_warnings( + "package P { + metadata def Note; + part def V { + doc vDoc /* the definition */ + comment named /* a named comment */ + rep inOCL language \"ocl\" /* self.x > 0 */ + comment about named /* local name */ + comment about vd /* short name */ + comment about inOCL /* textual representation */ + @Note about vDoc; + } + comment about V::vDoc /* qualified */ + comment about P::V::named /* fully qualified */ + dependency vDep from V to Note; + comment about vDep /* dependency */ + @Note about P::vDep; + }" + ) + .is_empty() + ); + // An annotating element owns no members, so nothing resolves through it. + let msgs = model_warnings( + "package P { part def V { doc vDoc /* … */ } comment about V::vDoc::x /* */ }", + ); + assert_eq!(msgs.len(), 1, "{msgs:#?}"); + assert!(msgs[0].contains("unresolved reference `V::vDoc::x`")); +} + #[test] fn referential_alias_target() { let msgs = model_warnings("package P { part def V; alias W for Vehicel; }"); @@ -558,7 +594,7 @@ fn expose_makes_members_referencable() { /// instead of binding the first declaration/import. Improvements should /// lower these numbers; semantic corrections require a deliberate update. /// -/// Ambiguity rose 47 -> 48 on the 2026-05 corpus, and the added finding +/// Ambiguity rose 47 -> 48 on the pinned corpus, and the added finding /// is ours, not the corpus's: correcting the individual-analysis /// example's typing made a second inheritance path visible, and we do /// not yet collapse a usage's re-declared feature onto the identically @@ -572,23 +608,114 @@ fn expose_makes_members_referencable() { /// ``` /// /// (95, 48, 2, 2) -> (66, 25, 2, 2) when inherited-member merges gained -/// *explicit*-redefinition shadowing (2026-08-03): a candidate that +/// *explicit*-redefinition shadowing: a candidate that /// transitively redefines another candidate wins instead of the pair /// reading as ambiguous, so diamonds like a subject redefinition seen /// beside the definition's original subject resolve — and the chain /// members reached through the formerly ambiguous features resolve /// with them (the 29-unresolved drop is entirely that cascade). /// -/// -> (66, 24, 2, 2) with *implicit* redefinition by name (2026-08-03, -/// the shape documented above): a usage owned by a type that strictly +/// -> (66, 24, 2, 2) with *implicit* redefinition by name (the shape +/// documented above): a usage owned by a type that strictly /// specializes another candidate's owning type shadows the same-named /// inherited feature without a spelled `:>>`. The remaining ambiguities /// are recursive-import multi-hits (several same-named declarations in /// unrelated containers made visible by `import ::**`) — genuine /// indistinguishability, not inheritance diamonds. /// +/// A user root declaration named like a standard-library root is silently +/// bypassed by resolution: root lookups keep the library declaration (the +/// two metaclasses do not overlap, so the earlier candidate stands), and +/// every qualified reference through the name lands in the library. The +/// referential check reports the collision at the user declaration's +/// name; resolution itself is unchanged. +#[test] +fn referential_root_shadows_library_root() { + const LIB: &str = "standard library package Requirements { requirement def Base; }"; + let shadowing = |user: &str| { + let mut model = Model::new(); + model.add_library_source("MiniLib.sysml", LIB); + model.add_source("t.sysml", user); + assert!(!model.has_errors(), "test source must parse cleanly"); + model + }; + + let src = "package Requirements {\n requirement def Speed;\n}\npackage Uses {\n \ + requirement s : Requirements::Speed;\n}\n"; + let model = shadowing(src); + let diags = validate_model(&model); + let msgs: Vec<&str> = diags.iter().map(|(_, d)| d.message.as_str()).collect(); + assert_eq!( + msgs, + [ + "root package `Requirements` shadows the standard library package `Requirements`; \ + references resolve to the library", + "unresolved reference `Requirements::Speed`", + ], + "{msgs:#?}" + ); + // Attributed to the user unit, at the declared name. + let (unit, d) = &diags[0]; + assert_eq!(*unit, 1); + assert_eq!( + &src[d.span.start as usize..d.span.end as usize], + "Requirements" + ); + // Resolution behavior is unchanged: the root name reaches the library. + let mut r = sysmlv2_parser::json::ResolvedModel::build(&model); + let pkg = r.resolve_qualified("Requirements").expect("resolves"); + assert!(r.is_library_element(pkg)); + assert!(r.resolve_qualified("Requirements::Speed").is_none()); + assert!(r.resolve_qualified("Requirements::Base").is_some()); + + // Any root declaration kind collides, not only packages. + let msgs = validate_model(&shadowing("part def Requirements;")) + .into_iter() + .map(|(_, d)| d.message) + .collect::>(); + assert_eq!( + msgs, + [ + "root declaration `Requirements` shadows the standard library package \ + `Requirements`; references resolve to the library" + ], + "{msgs:#?}" + ); + + // A same-kind user root makes the name ambiguous instead — the + // finding says so, alongside the per-reference ambiguity findings. + let msgs = validate_model(&shadowing( + "library package Requirements { requirement def Speed; }\n\ + package Uses { requirement s : Requirements::Speed; }\n", + )) + .into_iter() + .map(|(_, d)| d.message) + .collect::>(); + assert_eq!(msgs.len(), 2, "{msgs:#?}"); + assert_eq!( + msgs[0], + "root package `Requirements` shadows the standard library package `Requirements`; \ + references to the name are ambiguous" + ); + assert!(msgs[1].starts_with("ambiguous reference"), "{msgs:#?}"); + + // Nested packages and differently named roots never collide. + assert!( + validate_model(&shadowing( + "package Reqs { package Requirements { requirement def Speed; } \ + requirement s : Requirements::Speed; }" + )) + .is_empty() + ); + // Without a library there is nothing to shadow. + assert!(model_warnings("package Requirements { requirement def Speed; }").is_empty()); +} + /// -> (65, 24, 2, 2) after trigger-bearing accept payload names stopped -/// being lowered as unresolved type references (2026-08-14). +/// being lowered as unresolved type references. +/// -> (63, 24, 2, 2) once named documentation and comment elements +/// became members their namespace binds, so `comment about cmt` reaches +/// a `comment cmt /* … */` sibling. #[test] fn corpus_referential_ratchet() { let root = sysmlv2_testkit::corpus_root(); @@ -620,7 +747,7 @@ fn corpus_referential_ratchet() { .count(); assert_eq!( (unresolved, ambiguous, aliases, cycles), - (65, 24, 2, 2), + (63, 24, 2, 2), "referential ratchet moved — improvements should only lower these" ); } @@ -654,6 +781,168 @@ fn semantic_multiplicity_bounds() { assert_eq!(msgs.len(), 1, "{msgs:#?}"); } +#[test] +fn multiplicity_bounds_require_natural_values() { + for bound in ["\"two\"", "true", "1.5", "*..2"] { + let findings = sem_warnings(&format!("part p[{bound}];")); + assert!( + findings.iter().any(|m| m.contains("Natural number")), + "{bound}: {findings:?}" + ); + } + for bound in ["0..*", "2"] { + assert!( + sem_warnings(&format!("part p[{bound}];")).is_empty(), + "{bound}" + ); + } + assert!(!sem_warnings("attribute n = (1, 2); part p[n];").is_empty()); + assert!(sem_warnings("attribute n = 4 / 2; part p[n];").is_empty()); +} + +#[test] +fn usage_typing_respects_metaclass_inheritance_and_single_type_rules() { + for usage in [ + "attribute", + "port", + "action", + "state", + "calc", + "constraint", + "requirement", + "analysis", + "verification", + "use case", + "view", + "rendering", + ] { + let findings = sem_warnings(&format!("part def D; {usage} x : D;")); + assert!( + findings.iter().any(|m| m.contains("must be typed by")), + "{usage}: {findings:?}" + ); + } + assert!(!sem_warnings("attribute def D; occurrence x : D;").is_empty()); + assert!(sem_warnings("interface def I; connection x : I;").is_empty()); + assert!(sem_warnings("requirement def R; constraint x : R;").is_empty()); + assert!(sem_warnings("calc def C; action x : C;").is_empty()); + assert!(sem_warnings("metadata def M; item x : M;").is_empty()); + assert!( + sem_warnings("calc def C { in part x : ScalarValues::Real; return : ScalarValues::Real; }") + .is_empty() + ); + for kind in [ + "calc", + "constraint", + "requirement", + "case", + "analysis", + "verification", + "use case", + "view", + "viewpoint", + "rendering", + "enum", + ] { + let findings = sem_warnings(&format!("{kind} def A; {kind} def B; {kind} x : A, B;")); + assert!( + findings + .iter() + .any(|m| m.contains("one non-redundant type")), + "{kind}: {findings:?}" + ); + let findings = sem_warnings(&format!( + "{kind} def A; {kind} def B :> A; {kind} x : B, A;" + )); + if kind == "enum" { + assert!( + findings + .iter() + .any(|m| m.contains("validateDefinitionVariationSpecialization")), + "{findings:?}" + ); + } else { + assert!(findings.is_empty(), "redundant {kind}: {findings:?}"); + } + } +} + +#[test] +fn subsetting_cannot_widen_an_explicit_upper_bound() { + let declaration = "part def A { part x[2..3]; }"; + let bad = sem_warnings(&format!( + "{declaration} part def B :> A {{ part y[0..4] :> x; }}" + )); + assert_eq!(bad.len(), 1, "{bad:?}"); + assert!(bad[0].contains("subsetting multiplicity upper bound")); + let good = sem_warnings(&format!( + "{declaration} part def B :> A {{ part y[0..1] :> x; }}" + )); + assert!(good.is_empty(), "a subset may have fewer values: {good:?}"); +} + +#[test] +fn invocation_bindings_are_checked_by_name_and_position() { + let calc = "calc def F { in a; in b = 2; a + b }"; + for (args, expected) in [ + ("a = 1, a = 2", "more than once"), + ("1, a = 2", "more than once"), + ("typo = 1", "unknown parameter"), + ] { + let findings = sem_warnings(&format!("{calc} attribute result = F({args});")); + assert!( + findings.iter().any(|m| m.contains(expected)), + "{args}: {findings:?}" + ); + } + for args in ["a = 1", "b = 3, a = 1", "1", "1, b = 3"] { + assert!( + sem_warnings(&format!("{calc} attribute result = F({args});")).is_empty(), + "{args}" + ); + } +} + +#[test] +fn arithmetic_dimensions_are_checked_even_when_parameters_are_unbound() { + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + model.add_source( + "dimensions.sysml", + r#" + package Dimensions { + private import SI::*; + calc bad { + in v :> ISQ::speed; in mu :> ISQ::force; in r :> ISQ::length; + return result = v ** 2 + 2 * mu / r; + } + calc good { + in v :> ISQ::speed; in a :> ISQ::acceleration; in r :> ISQ::length; + return result = v ** 2 + 2 * a * r; + } + attribute badValue = 1 [m] + 1 [s]; + attribute zero = 1 [m] + 0; + attribute unknown; + attribute open = unknown + 1 [m]; + } + "#, + ); + assert!(!model.has_errors()); + let diagnostics = sysmlv2_parser::check::validate_semantics(&model); + let messages: Vec<_> = diagnostics + .iter() + .map(|(_, d)| d.message.as_str()) + .collect(); + assert_eq!(messages.len(), 2, "{messages:#?}"); + assert!( + messages + .iter() + .all(|m| m.contains("incompatible quantity dimensions")) + ); +} + #[test] fn semantic_self_and_circular_specialization() { let msgs = sem_warnings("package P { part def A :> A; }"); @@ -682,8 +971,8 @@ fn semantic_duplicate_specializations() { assert!(sem_warnings("package P { part def A; part def B; part x : A, B; }").is_empty()); } -/// Corpus gate: the semantic constraints must produce zero findings on the -/// conforming corpus (same policy as the body-context gate). +/// Corpus gate: every finding must be an adjudicated defect in the input, +/// rather than an implementation limitation or an unreviewed false positive. #[test] fn corpus_semantic_constraints_clean() { let mut model = Model::new(); @@ -695,16 +984,28 @@ fn corpus_semantic_constraints_clean() { model.add_source(f.file_name().unwrap().to_string_lossy().into_owned(), &src); } let diags = sysmlv2_parser::check::validate_semantics(&model); - // Zero findings. The single long-standing exception here was a + // The single long-standing exception here was a // corpus defect in `AnalysisIndividualExample.sysml`, where the // redefinition typed the wrong individual (the *analysis* def - // rather than the action def declared for it); the 2026-05 corpus - // corrects the typing, so the gate is unconditional again. + // rather than the action def declared for it); the pinned corpus + // corrects the typing. Dimensional inference reveals two independent + // defects, also reported by OpenSysML at d7d432ff4: + // - Total Temperature declares V : VolumeValue and Cp : DimensionOneValue, + // then adds V^2/(2*Cp) (L^6) to T_static (temperature). + // - The wheel expression adds 22/2*25.4 (dimensionless) to 110[mm]; the + // intended whole sum needs parentheses before its unit annotation. let msgs: Vec = diags .iter() .map(|(u, d)| format!("{} — {}", model.units()[*u].name, d.message)) .collect(); - assert_eq!(msgs.len(), 0, "semantic findings on the corpus: {msgs:#?}"); + assert_eq!( + msgs, + [ + "Turbojet Stage Analysis.sysml — expression combines incompatible quantity dimensions `L^6` and `Θ`", + "VehicleGeometryAndCoordinateFrames.sysml — expression combines incompatible quantity dimensions `1` and `L`", + ], + "unexpected semantic findings on the corpus" + ); } /// Constraint verdicts for one source (no library). @@ -763,6 +1064,191 @@ fn unbound_feature_comparisons_are_undecided() { assert_eq!(vs[0].1, Satisfied, "{vs:#?}"); } +/// A member read *through an unbound parameter* — a requirement's +/// `subject`, a calc parameter — is not the type's default: the default +/// belongs to the type and the argument bound later may override it, so +/// a definition-level constraint over the subject stays undecided +/// instead of accusing the type's defaults. A value the declaration +/// *fixes* to a literal holds for every argument and still decides, +/// and an ordinary usage still reads the defaults it inherits. +#[test] +fn defaults_read_through_an_unbound_subject_are_undecided() { + use sysmlv2_parser::check::ConstraintVerdict::*; + let vs = verdicts( + "package P { + part def Cartridge { attribute micron default = 5; } + part def Filter { + attribute ratedHours default = 40; + attribute portCount = 3; + part cartridge : Cartridge; + } + requirement def FitForService { + subject unit : Filter; + require constraint fromDefault { unit.ratedHours >= 250 } + require constraint fromFixed { unit.portCount == 6 } + require constraint throughChain { unit.cartridge.micron <= 1 } + } + part installed : Filter; + assert constraint onAUsage { installed.ratedHours == 40 } + }", + ); + let by_name = |n: &str| { + vs.iter() + .find(|(name, _)| name.as_deref() == Some(n)) + .unwrap_or_else(|| panic!("no constraint `{n}` in {vs:#?}")) + .1 + .clone() + }; + assert!(matches!(by_name("fromDefault"), Undecided(_)), "{vs:#?}"); + assert!(matches!(by_name("throughChain"), Undecided(_)), "{vs:#?}"); + assert_eq!(by_name("fromFixed"), Violated, "{vs:#?}"); + assert_eq!(by_name("onAUsage"), Satisfied, "{vs:#?}"); +} + +#[test] +fn unknown_receivers_do_not_commit_to_type_defaults() { + use sysmlv2_parser::check::ConstraintVerdict::*; + let vs = verdicts( + "package P { + part def Choice { attribute enabled default = false; } + part installed : Choice; + attribute externalDefault default = true; + calc def Identity { in x; return y = x; } + calc def Read { in x : Choice; return y = x.enabled; } + part def Device { + attribute ready default = false; + attribute intermediate = ready; + attribute enabled = intermediate; + attribute external = installed.enabled; + attribute externalScalar = externalDefault; + attribute fixed = true; + calc def LocalDefault { in x default = true; return y = x; } + calc def ReadReady { return y = ready; } + attribute localDefault = LocalDefault(); + attribute localUnknown = ReadReady(); + part choice : Choice; + part concrete : Choice = installed; + } + requirement def Eligibility { + subject unit : Device; + ref part requested : Choice; + ref part aliasUnit : Device = unit; + require constraint referenceDefault { requested.enabled } + require constraint fixedFormula { unit.enabled } + require constraint aliasFormula { aliasUnit.enabled } + require constraint conditionalDefault { + (if true ? requested else installed).enabled + } + require constraint returnedReference { Identity(requested).enabled } + require constraint argumentReference { Read(requested) } + require constraint nestedDefault { unit.choice.enabled } + require constraint nestedAlias { Identity(unit.choice).enabled } + require constraint fixedLiteral { unit.fixed } + require constraint localDefault { unit.localDefault } + require constraint localUnknown { unit.localUnknown } + require constraint concreteMember { not unit.concrete.enabled } + require constraint unrelatedReceiver { not unit.external } + require constraint unrelatedScalar { unit.externalScalar } + require constraint concreteConditional { + not (if false ? requested else installed).enabled + } + require constraint concreteArgument { not Read(installed) } + } + calc def Input { + in requested : Choice; + return result = requested.enabled; + assert constraint inputDefault { requested.enabled } + } + }", + ); + let unknown = [ + "referenceDefault", + "fixedFormula", + "aliasFormula", + "conditionalDefault", + "returnedReference", + "argumentReference", + "nestedDefault", + "nestedAlias", + "inputDefault", + "localUnknown", + ]; + assert_eq!(vs.len(), 17, "{vs:#?}"); + for (name, verdict) in &vs { + if unknown.contains(&name.as_deref().unwrap()) { + assert!( + matches!(verdict, Undecided(reason) if reason.contains("indeterminate")), + "{name:?}: {verdict:?}" + ); + } else { + assert_eq!(*verdict, Satisfied, "{name:?}"); + } + } +} + +#[test] +fn unknown_receiver_methods_follow_redefined_defaults() { + use sysmlv2_parser::check::ConstraintVerdict::*; + for declaration in ["attribute :>> ready", "attribute ready"] { + for value in ["default = true", "= true"] { + let vs = verdicts(&format!( + "package P {{ + part def Base {{ + attribute ready default = false; + calc def Read {{ attribute local = ready; return result = local; }} + attribute enabled = Read(); + }} + part def Specialized :> Base {{ {declaration} {value}; }} + requirement def R {{ + subject unit : Specialized; + require constraint direct {{ unit.ready }} + require constraint method {{ unit.enabled }} + }} + }}" + )); + assert_eq!(vs.len(), 2, "{vs:?}"); + for (_, verdict) in vs { + if value.starts_with("default") { + assert!( + matches!(verdict, Undecided(reason) if reason.contains("indeterminate")), + "{value}" + ); + } else { + assert_eq!(verdict, Satisfied, "{value}"); + } + } + } + } +} + +#[test] +fn unknown_receivers_do_not_taint_imported_concrete_values() { + use sysmlv2_parser::check::ConstraintVerdict::*; + let vs = verdicts( + "package Globals { + attribute flag default = true; + part def Child { attribute flag default = true; } + part installed : Child; + } + package P { + part def Device { + private import Globals::*; + attribute scalar = flag; + attribute nested = installed.flag; + } + requirement def R { + subject unit : Device; + require constraint scalar { unit.scalar } + require constraint nested { unit.nested } + } + }", + ); + assert_eq!(vs.len(), 2, "{vs:?}"); + for (_, verdict) in vs { + assert_eq!(verdict, Satisfied); + } +} + /// Corpus ratchet for constraint verdicts: a conforming corpus must have /// **zero violated**; the satisfied/undecided split moves only through /// deliberate evaluator improvements. @@ -787,12 +1273,12 @@ fn corpus_constraint_verdicts_ratchet() { assert_eq!( (sat, vio, und), // 80 → 90 when asserted constraints with *inherited* bodies - // (`assert c : Def;`) gained verdicts (2026-07-17); 90 → 116 when + // (`assert c : Def;`) gained verdicts; 90 → 116 when // satisfaction claims (`satisfy R by x;`) began expanding to // subject-bound verdicts — all 26 corpus expansions enter // undecided (their remaining parameters are unbound); the // evaluator/solver may promote them. Satisfied 7 → 4 when - // unbound-feature cardinality stopped fabricating (2026-07-23): + // unbound-feature cardinality stopped fabricating: // the three lost verdicts were `(1..size(xs)-1)->forAll` bodies // over unbound `[0..*]` collections, where the placeholder's // fabricated size of 1 emptied the range and made the forAll @@ -863,15 +1349,12 @@ fn semantic_invocation_arity() { // A defaulted tail is clean. let defaulted = "calc def G { in a; in b = 10; a + b }"; assert!(sem_warnings(&format!("package P {{ {defaulted} attribute x = G(1); }}")).is_empty()); - // Named arguments are not checked (they bind explicitly). - assert!( - sem_warnings(&format!( - "package P {{ {calc} attribute x = F(a = 1, b = 2); }}" - )) - .is_empty() - ); - // Zero-argument spellings are not checked (type-reference idioms). - assert!(sem_warnings(&format!("package P {{ {calc} attribute x = F(); }}")).is_empty()); + // Named and empty calls must not silently leave required inputs unbound. + for args in ["a = 1, b = 2", ""] { + let msgs = sem_warnings(&format!("package P {{ {calc} attribute x = F({args}); }}")); + assert_eq!(msgs.len(), 1, "{msgs:#?}"); + assert!(msgs[0].contains("never bound")); + } // Nested call sites are found. let msgs = sem_warnings(&format!( "package P {{ {calc} attribute x = 1 + F(1, 2) * 3; }}" @@ -1226,8 +1709,8 @@ fn nary_connector_binary_specialization() { "package N { part def P; connection def Tri { - end part a : P[*]; - end part b : P[*]; + end part a : P[1]; + end part b : P[1]; end part c : P[1]; } part ctx { @@ -1244,8 +1727,8 @@ fn nary_connector_binary_specialization() { "package N { part def P; connection def Tri { - end part a : P[*]; - end part b : P[*]; + end part a : P[1]; + end part b : P[1]; end part c : P[1]; } part ctx { diff --git a/crates/sysmlv2-parser/tests/closure_policy.rs b/crates/sysmlv2-parser/tests/closure_policy.rs new file mode 100644 index 0000000..303f834 --- /dev/null +++ b/crates/sysmlv2-parser/tests/closure_policy.rs @@ -0,0 +1,268 @@ +//! The closure policy on the standard corpus (plan §33h): the full form +//! with the inheritance and import closures materialized per element +//! stays schema-shaped and a superset of the passthrough form, and its +//! size is measured — the number INTEROP.md's "passthrough level" +//! paragraph is about. The `Reject` unresolved-reference policy must not +//! count the library members a closure lists (they are ids, not +//! unresolved spellings). + +#![cfg(feature = "json")] + +use std::collections::{HashMap, HashSet}; +use std::fs; +use sysmlv2_parser::full::{EmissionPolicy, UnresolvedReferencePolicy, resolved_to_full_json}; +use sysmlv2_parser::json::{ + CLOSURE_NAMES, ClosurePolicy, Derives, ResolvedModel, derives, is_owned_property, +}; +use sysmlv2_parser::model::Model; + +/// The serialized size, without materializing the document: the corpus +/// full form runs to hundreds of megabytes and only the count is read. +struct CountingWriter(usize); + +impl std::io::Write for CountingWriter { + fn write(&mut self, buf: &[u8]) -> std::io::Result { + self.0 += buf.len(); + Ok(buf.len()) + } + + fn flush(&mut self) -> std::io::Result<()> { + Ok(()) + } +} + +fn serialized_len(value: &serde_json::Value) -> usize { + let mut counter = CountingWriter(0); + serde_json::to_writer(&mut counter, value).unwrap(); + counter.0 +} + +/// Index an emitted array by element id, borrowing: the corpus full form +/// is hundreds of megabytes, and a copy per policy is gigabytes. +fn by_id(value: &serde_json::Value) -> HashMap<&str, &serde_json::Value> { + value + .as_array() + .unwrap() + .iter() + .map(|e| (e["@id"].as_str().unwrap(), e)) + .collect() +} + +/// A list of bare `{"@id": …}` references, or nothing if any entry +/// carries more than the id — then the values must be compared whole. +fn reference_ids(list: &[serde_json::Value]) -> Option> { + list.iter() + .map(|v| { + let object = v.as_object()?; + if object.len() != 1 { + return None; + } + object.get("@id")?.as_str() + }) + .collect() +} + +/// Whether `whole` holds every value in `part`. Reference lists compare +/// by id through a set: the corpus lists are long enough that scanning +/// the longer one per entry dominates the test. +fn contains_all(part: &[serde_json::Value], whole: &[serde_json::Value]) -> bool { + match (reference_ids(part), reference_ids(whole)) { + (Some(part_ids), Some(whole_ids)) => { + let whole_ids: HashSet<&str> = whole_ids.into_iter().collect(); + part_ids.iter().all(|id| whole_ids.contains(id)) + } + _ => part.iter().all(|x| whole.contains(x)), + } +} + +#[test] +fn corpus_closure_form_is_a_superset_and_measured() { + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return; + } + let files = sysmlv2_testkit::user_files(); + if files.is_empty() { + eprintln!("skipping: corpus model files not present"); + return; + } + let mut model = Model::new(); + model + .load_library_dir(&root.join("sysml.library")) + .expect("library loads"); + for path in files { + let src = fs::read_to_string(&path).unwrap(); + let name = path + .strip_prefix(&root) + .unwrap_or(&path) + .to_string_lossy() + .into_owned(); + model.add_source(name, &src); + } + let mut r = ResolvedModel::build(&model); + let emit = |r: &mut ResolvedModel, closures: ClosurePolicy| { + let t0 = std::time::Instant::now(); + let value = resolved_to_full_json( + r, + &model, + EmissionPolicy { + unresolved: UnresolvedReferencePolicy::Preserve, + closures, + }, + ) + .expect("the corpus emits under every policy"); + let bytes = serialized_len(&value); + (value, bytes, t0.elapsed()) + }; + let (passthrough, pass_bytes, pass_time) = emit(&mut r, ClosurePolicy::Passthrough); + let (explicit, explicit_bytes, explicit_time) = emit( + &mut r, + ClosurePolicy::Closure { + include_implied: false, + }, + ); + // Per element: the closure names are empty at the passthrough level + // and the inheritance-aware lists grow into supersets. The lengths + // the implied heritage is measured against outlive the two documents + // they come from — a third corpus document alongside them is + // gigabytes, so they are carried out and the documents dropped. + let implied_floor: HashMap; 2]> = { + let pass = by_id(&passthrough); + let closed = by_id(&explicit); + assert_eq!(pass.len(), closed.len()); + let mut closure_nonempty = 0usize; + let mut feature_grew = 0usize; + for (id, p) in &pass { + let c = &closed[id]; + let ty = p["@type"].as_str().unwrap(); + for name in CLOSURE_NAMES { + // `importedMembership` is owned on a MembershipImport: not a + // closure there. + if is_owned_property(ty, name) { + continue; + } + if let Some(v) = p.get(*name) { + assert!( + v.as_array().is_some_and(|a| a.is_empty()), + "{id}.{name} at passthrough" + ); + } + if c.get(*name) + .and_then(|v| v.as_array()) + .is_some_and(|a| !a.is_empty()) + { + closure_nonempty += 1; + } + } + // An exact name is the same under both policies: an owned rule + // routed through the policy by mistake would move here. + for (key, value) in p.as_object().unwrap() { + if key.starts_with('@') || CLOSURE_NAMES.contains(&key.as_str()) { + continue; + } + if derives(ty, key) == Derives::Exact { + assert_eq!(value, &c[key], "{id}.{key} moved under the closure policy"); + } + } + for name in ["feature", "featureMembership", "membership", "member"] { + let (Some(a), Some(b)) = ( + p.get(name).and_then(|v| v.as_array()), + c.get(name).and_then(|v| v.as_array()), + ) else { + continue; + }; + assert!( + b.len() >= a.len(), + "{id}.{name} shrank under the closure policy" + ); + assert!( + contains_all(a, b), + "{id}.{name} lost a value under the closure policy" + ); + if b.len() > a.len() { + feature_grew += 1; + } + } + } + eprintln!( + "closure values written: {closure_nonempty}; inheritance-aware lists that grew: {feature_grew}" + ); + assert!(closure_nonempty > 0); + assert!(feature_grew > 0); + closed + .iter() + .map(|(id, c)| { + let len = |name: &str| c.get(name).and_then(|v| v.as_array()).map(Vec::len); + ((*id).to_string(), [len("feature"), len("inheritedFeature")]) + }) + .collect() + }; + drop(passthrough); + drop(explicit); + let (implied, implied_bytes, implied_time) = emit( + &mut r, + ClosurePolicy::Closure { + include_implied: true, + }, + ); + eprintln!( + "full form: passthrough {pass_bytes} bytes ({pass_time:?}); closures over the written heritage {explicit_bytes} bytes ({explicit_time:?}, x{:.2}); with the implied heritage {implied_bytes} bytes ({implied_time:?}, x{:.2})", + explicit_bytes as f64 / pass_bytes as f64, + implied_bytes as f64 / pass_bytes as f64 + ); + // The implied heritage only adds. + let more = by_id(&implied); + for (id, floor) in &implied_floor { + let m = more[id.as_str()]; + for (name, b) in ["feature", "inheritedFeature"].iter().zip(floor) { + let (Some(b), Some(c2)) = (b, m.get(*name).and_then(|v| v.as_array())) else { + continue; + }; + assert!( + c2.len() >= *b, + "{id}.{name} shrank with the implied heritage" + ); + } + } +} + +/// The `Reject` policy counts unresolved spellings, not the library ids +/// a closure lists. +#[test] +fn reject_policy_ignores_library_closure_members() { + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return; + } + let mut model = Model::new(); + model + .load_library_dir(&root.join("sysml.library")) + .expect("library loads"); + model.add_source( + "m.sysml", + "package P { import ScalarValues::*; part def V; part v : V { attribute mass : Real; } }", + ); + let mut r = ResolvedModel::build(&model); + let value = resolved_to_full_json( + &mut r, + &model, + EmissionPolicy { + unresolved: UnresolvedReferencePolicy::Reject, + closures: ClosurePolicy::Closure { + include_implied: true, + }, + }, + ) + .expect("library closure members are ids, not unresolved spellings"); + let v = value + .as_array() + .unwrap() + .iter() + .find(|e| e["declaredName"] == "v") + .unwrap(); + // A part inherits the library `Parts::Part` members with the implied + // heritage on. + assert!(!v["inheritedFeature"].as_array().unwrap().is_empty()); +} diff --git a/crates/sysmlv2-parser/tests/derived_api.rs b/crates/sysmlv2-parser/tests/derived_api.rs new file mode 100644 index 0000000..1776fcb --- /dev/null +++ b/crates/sysmlv2-parser/tests/derived_api.rs @@ -0,0 +1,2299 @@ +//! The derived-property read API, family by family, against the +//! specification's definition of each property (KerML/SysML clause 8.3; +//! the OCL rules in `spec-refs/derived-properties.json`) rather than +//! against the emitter's current output. + +#![cfg(feature = "json")] + +use sysmlv2_parser::json::{ + ClosurePolicy, Derived, DerivedValue, Derives, ElementRef, Reference, ResolvedModel, + computed_names, derives, +}; +use sysmlv2_parser::model::Model; + +fn build(src: &str) -> ResolvedModel { + let mut model = Model::new(); + model.add_source("m.sysml", src); + assert!( + !model.has_errors(), + "test model must parse clean: {:?}", + model + .units() + .iter() + .flat_map(|u| u.diagnostics.iter()) + .collect::>() + ); + ResolvedModel::build(&model) +} + +fn elem(r: &mut ResolvedModel, r_qn: &str) -> ElementRef { + r.resolve_qualified(r_qn) + .unwrap_or_else(|| panic!("no element {r_qn}")) +} + +/// A single-valued composition or in-model reference. +fn one(r: &mut ResolvedModel, e: ElementRef, name: &str) -> Option { + match r.derived(e, name) { + Derived::Value(DerivedValue::Element(x)) + | Derived::Value(DerivedValue::Reference(Reference::Element(x))) => Some(x), + Derived::Value(DerivedValue::Null) => None, + other => panic!("{name}: expected a single in-model reference, got {other:?}"), + } +} + +/// A multi-valued composition, or a reference list whose every target is +/// in the model. +fn many(r: &mut ResolvedModel, e: ElementRef, name: &str) -> Vec { + match r.derived(e, name) { + Derived::Value(DerivedValue::Elements(v)) => v, + Derived::Value(DerivedValue::References(v)) => v + .into_iter() + .map(|x| match x { + Reference::Element(x) => x, + other => panic!("{name}: a target outside the model: {other:?}"), + }) + .collect(), + other => panic!("{name}: expected a reference list, got {other:?}"), + } +} + +fn refs(r: &mut ResolvedModel, e: ElementRef, name: &str) -> Vec { + match r.derived(e, name) { + Derived::Value(DerivedValue::References(v)) => v, + Derived::Value(DerivedValue::Reference(x)) => vec![x], + Derived::Value(DerivedValue::Null) => Vec::new(), + other => panic!("{name}: expected references, got {other:?}"), + } +} + +fn names(r: &mut ResolvedModel, v: &[ElementRef]) -> Vec { + v.iter() + .map(|&x| { + r.element_effective_name(x) + .unwrap_or_else(|| r.element_type(x).to_string()) + }) + .collect() +} + +#[test] +fn tri_state_distinguishes_undeclared_uncomputed_and_value() { + let mut r = build("package P { part def V { attribute mass; } }"); + let v = elem(&mut r, "P::V"); + // A Definition declares `ownedFeature`; a Package does not. + assert!(matches!(r.derived(v, "ownedFeature"), Derived::Value(_))); + let p = elem(&mut r, "P"); + assert_eq!(r.derived(p, "ownedFeature"), Derived::NotDeclared); + // An owned property is never answered as derived. + assert_eq!(r.derived(v, "declaredName"), Derived::NotDeclared); + // Declared but not yet computed by the layer. + let mass = elem(&mut r, "P::V::mass"); + assert_eq!(r.derived(mass, "mayTimeVary"), Derived::NotComputed); + // A name that is derived on Namespace and owned on MembershipImport. + assert_eq!( + derives("Package", "importedMembership"), + Derives::Passthrough + ); + assert_eq!( + derives("MembershipImport", "importedMembership"), + Derives::NotDeclared + ); + // Static fidelity. + assert_eq!(derives("PartDefinition", "ownedFeature"), Derives::Exact); + assert_eq!(derives("PartDefinition", "feature"), Derives::Passthrough); + assert_eq!(derives("PartDefinition", "nosuch"), Derives::NotDeclared); +} + +#[test] +fn element_family_follows_the_owning_relationship() { + // owner = owningRelationship.owningRelatedElement; owningMembership is + // the owning relationship when it is a Membership; owningNamespace is + // that membership's owner; ownedElement = ownedRelationship.ownedRelatedElement. + let mut r = build( + "package P { + part def V { attribute mass; } + part def W :> V; + }", + ); + let p = elem(&mut r, "P"); + let v = elem(&mut r, "P::V"); + let mass = elem(&mut r, "P::V::mass"); + assert_eq!(one(&mut r, mass, "owner"), Some(v)); + assert_eq!(one(&mut r, v, "owner"), Some(p)); + // The unit's root Namespace owns the package and has no owner itself. + let root = one(&mut r, p, "owner").expect("the document root owns P"); + assert_eq!(r.element_type(root), "Namespace"); + assert_eq!(one(&mut r, root, "owner"), None); + assert_eq!(one(&mut r, root, "owningMembership"), None); + let om = one(&mut r, mass, "owningMembership").expect("owning membership"); + assert_eq!(r.element_type(om), "FeatureMembership"); + assert_eq!(one(&mut r, mass, "owningNamespace"), Some(v)); + // The memberships are V's owned elements' carriers; ownedElement lists + // the elements those relationships own, mass included. + let owned = many(&mut r, v, "ownedElement"); + assert!(owned.contains(&mass)); + // A relationship owned directly by its related element has no owning + // relationship, hence no owner per the specification. + let w = elem(&mut r, "P::W"); + let sub = r + .owned_relationships(w) + .into_iter() + .find(|&x| r.element_type(x) == "Subclassification") + .expect("W owns its Subclassification"); + assert_eq!(one(&mut r, sub, "owner"), None); + assert_eq!(one(&mut r, sub, "owningMembership"), None); + assert!(matches!( + r.derived(v, "isLibraryElement"), + Derived::Value(DerivedValue::Bool(false)) + )); + // The specific side owns its Subclassification and is its owningType / + // owningClassifier. + assert_eq!(one(&mut r, sub, "owningType"), Some(w)); + assert_eq!(one(&mut r, sub, "owningClassifier"), Some(w)); +} + +#[test] +fn library_element_follows_library_packages_not_units() { + // isLibraryElement = libraryNamespace() <> null: a `library package` + // in an ordinary unit makes its contents library elements. + let mut r = build( + "library package L { part def T; } + package P { part def U; }", + ); + let t = elem(&mut r, "L::T"); + let u = elem(&mut r, "P::U"); + assert_eq!( + r.derived(t, "isLibraryElement"), + Derived::Value(DerivedValue::Bool(true)) + ); + assert_eq!( + r.derived(u, "isLibraryElement"), + Derived::Value(DerivedValue::Bool(false)) + ); + assert!(!r.is_library_element(t), "not from a library unit"); +} + +#[test] +fn standalone_relationship_has_no_owning_type() { + // KerML spells a standalone specialization as a member. + let mut model = Model::new(); + model.add_source( + "m.kerml", + "package P { + classifier A; classifier B; + specialization S subclassifier B specializes A; + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let s = r + .elements_of_metaclass("Subclassification") + .into_iter() + .find(|&x| !r.is_library_element(x)) + .expect("the standalone specialization"); + assert_eq!(one(&mut r, s, "owningType"), None); + assert_eq!(one(&mut r, s, "owningClassifier"), None); + // It rides a membership: owner is P. + let p = elem(&mut r, "P"); + assert_eq!(one(&mut r, s, "owner"), Some(p)); +} + +#[test] +fn namespace_family_selects_membership_kinds() { + let mut r = build( + "package P { + part def V { attribute mass; } + alias M for V; + import V::*; + part x : V; + }", + ); + let p = elem(&mut r, "P"); + let v = elem(&mut r, "P::V"); + let x = elem(&mut r, "P::x"); + // ownedMembership: every owned Membership, aliases included; ownedMember: + // the owned members of the *owning* memberships only. + let ms = many(&mut r, p, "ownedMembership"); + assert_eq!(ms.len(), 3, "V, the alias, x"); + let alias = ms + .iter() + .copied() + .find(|&m| r.membership_is_alias(m)) + .expect("alias membership listed"); + let om = many(&mut r, p, "ownedMember"); + assert_eq!(names(&mut r, &om), ["V", "x"]); + // member = membership.memberElement: the alias contributes its target. + let members = many(&mut r, p, "member"); + assert_eq!(members, [v, v, x], "V, the alias's target V, x"); + assert!(r.membership_member(alias) == Some(v)); + // ownedImport: the Import relationships. + let imports = many(&mut r, p, "ownedImport"); + assert_eq!(imports.len(), 1); + assert_eq!(r.element_type(imports[0]), "NamespaceImport"); + assert_eq!(one(&mut r, imports[0], "importOwningNamespace"), Some(p)); + assert_eq!(one(&mut r, imports[0], "importedElement"), Some(v)); + // A membership's namespace and owned member. + let vm = one(&mut r, v, "owningMembership").unwrap(); + assert_eq!(one(&mut r, vm, "membershipOwningNamespace"), Some(p)); + assert_eq!(one(&mut r, vm, "ownedMemberElement"), Some(v)); + assert_eq!( + r.derived(vm, "ownedMemberFeature"), + Derived::NotDeclared, + "an OwningMembership is not a FeatureMembership" + ); +} + +#[test] +fn type_and_feature_family_use_feature_memberships_only() { + let mut r = build( + "package P { + part def V { + attribute mass; + part def Nested; + variant part alt; + } + part v : V { part w; } + }", + ); + let v = elem(&mut r, "P::V"); + let mass = elem(&mut r, "P::V::mass"); + // ownedFeature reads the FeatureMembership kinds: the nested definition + // (an OwningMembership) and the variant (a VariantMembership — an + // OwningMembership, not a FeatureMembership, though its member is a + // feature) do not count. + let of = many(&mut r, v, "ownedFeature"); + assert_eq!(names(&mut r, &of), ["mass"]); + let fms = many(&mut r, v, "ownedFeatureMembership"); + assert_eq!(fms.len(), 1); + assert_eq!(one(&mut r, fms[0], "ownedMemberFeature"), Some(mass)); + assert_eq!(one(&mut r, fms[0], "owningType"), Some(v)); + // ownedMember still lists all three owning memberships' members. + assert_eq!(many(&mut r, v, "ownedMember").len(), 3); + // Feature side. + assert_eq!(one(&mut r, mass, "owningType"), Some(v)); + assert_eq!(one(&mut r, mass, "owningFeatureMembership"), Some(fms[0])); + assert_eq!(one(&mut r, mass, "owningDefinition"), Some(v)); + assert_eq!(one(&mut r, mass, "owningUsage"), None); + assert_eq!(one(&mut r, mass, "endOwningType"), None); + let vu = elem(&mut r, "P::v"); + let w = elem(&mut r, "P::v::w"); + assert_eq!(one(&mut r, w, "owningUsage"), Some(vu)); + assert_eq!(one(&mut r, w, "owningDefinition"), None); + // A package-owned usage has no owning type. + assert_eq!(one(&mut r, vu, "owningType"), None); + assert_eq!(one(&mut r, vu, "owningFeatureMembership"), None); +} + +#[test] +fn end_owning_type_needs_an_end_feature_membership() { + let mut r = build( + "package P { + part def A; part def B; + connection def C { end a : A; end b : B; } + }", + ); + let c = elem(&mut r, "P::C"); + let a = elem(&mut r, "P::C::a"); + assert_eq!(one(&mut r, a, "endOwningType"), Some(c)); + assert_eq!(one(&mut r, a, "owningType"), Some(c)); + let fm = one(&mut r, a, "owningFeatureMembership").unwrap(); + assert_eq!(r.element_type(fm), "EndFeatureMembership"); +} + +#[test] +fn passthrough_names_answer_the_owned_side() { + // `feature` and `featureMembership` union the inherited memberships in + // the specification; at the passthrough level they answer the owned + // side, exactly as the full form does. + let mut r = build( + "package P { + part def Base { attribute x; } + part def Sub :> Base { attribute y; } + }", + ); + let sub = elem(&mut r, "P::Sub"); + let f = many(&mut r, sub, "feature"); + assert_eq!(names(&mut r, &f), ["y"]); + assert_eq!(derives("PartDefinition", "feature"), Derives::Passthrough); + assert_eq!( + many(&mut r, sub, "featureMembership"), + many(&mut r, sub, "ownedFeatureMembership") + ); + // The exact inherited view is the accessor, not the passthrough name. + let inh = r.inherited_features(sub, false); + assert_eq!(names(&mut r, &inh), ["x"]); +} + +#[test] +fn chain_targets_ride_owning_memberships() { + // `first a.b` owns its synthesized chain feature through an + // OwningMembership (SysML.xtext `TransitionSourceMember`), so the + // chain feature is an owned member and that membership its owning + // membership. + let mut r = build( + "package P { + part def V { part a { part b; } } + state def S { + part v : V; + state s2; + transition first v.a then s2; + } + }", + ); + let s = elem(&mut r, "P::S"); + let transitions = r.elements_of_metaclass("TransitionUsage"); + let t = transitions + .into_iter() + .find(|&t| one(&mut r, t, "owner") == Some(s)) + .expect("the transition"); + let owned = many(&mut r, t, "ownedMember"); + let chain = owned + .iter() + .copied() + .find(|&f| r.element_type(f) == "Feature") + .expect("the source chain feature is an owned member"); + let m = one(&mut r, chain, "owningMembership").expect("owning membership"); + assert_eq!(r.element_type(m), "OwningMembership"); + assert_eq!(one(&mut r, m, "ownedMemberElement"), Some(chain)); + assert!(many(&mut r, t, "member").contains(&chain)); +} + +#[test] +fn membership_import_imports_the_member() { + let mut r = build( + "package P { + package L { part def T; } + package U { import L::T; } + }", + ); + let u = elem(&mut r, "P::U"); + let t = elem(&mut r, "P::L::T"); + let imports = many(&mut r, u, "ownedImport"); + assert_eq!(imports.len(), 1); + assert_eq!(r.element_type(imports[0]), "MembershipImport"); + assert_eq!(one(&mut r, imports[0], "importedElement"), Some(t)); +} + +#[test] +fn kind_filtered_compositions_are_conformance_inclusive() { + // `ownedPart = ownedUsage->selectByKind(PartUsage)` and friends: a part + // is also an item and an occurrence; a state is an action; a + // requirement is a constraint. Nested* mirror owned* on usages. + let mut r = build( + "package P { + part def V { + attribute mass; + part wheel; + port p; + ref item cargo; + action a; + state s; + constraint c; + requirement req; + } + part v : V { part w; } + }", + ); + let v = elem(&mut r, "P::V"); + let list = |r: &mut ResolvedModel, e, n: &str| -> Vec { + let items = many(r, e, n); + names(r, &items) + }; + assert_eq!(list(&mut r, v, "ownedPart"), ["wheel"]); + assert_eq!( + list(&mut r, v, "ownedItem"), + ["wheel", "cargo"], + "a part is an item" + ); + assert!( + list(&mut r, v, "ownedOccurrence").len() >= 5, + "parts, ports, items, actions, states are occurrences: {:?}", + list(&mut r, v, "ownedOccurrence") + ); + assert_eq!(list(&mut r, v, "ownedAttribute"), ["mass"]); + assert_eq!(list(&mut r, v, "ownedPort"), ["p"]); + assert_eq!( + list(&mut r, v, "ownedAction"), + ["a", "s"], + "a state is an action" + ); + assert_eq!(list(&mut r, v, "ownedState"), ["s"]); + assert_eq!( + list(&mut r, v, "ownedConstraint"), + ["c", "req"], + "a requirement is a constraint" + ); + assert_eq!(list(&mut r, v, "ownedRequirement"), ["req"]); + // Definitions declare owned*, usages declare nested*. + assert_eq!(r.derived(v, "nestedPart"), Derived::NotDeclared); + let vu = elem(&mut r, "P::v"); + assert_eq!(list(&mut r, vu, "nestedPart"), ["w"]); + assert_eq!(r.derived(vu, "ownedPart"), Derived::NotDeclared); + // Static fidelity: exact over an exact base, passthrough over `usage`. + assert_eq!(derives("PartDefinition", "ownedPart"), Derives::Exact); + assert_eq!(derives("ActionDefinition", "action"), Derives::Passthrough); + assert_eq!(derives("PartUsage", "nestedPart"), Derives::Exact); +} + +#[test] +fn definition_back_references_follow_the_declared_type() { + // `partDefinition` is the usage's definitions that are PartDefinitions + // (through itemDefinition / occurrenceDefinition), `attributeDefinition` + // its DataType definitions; a single-valued one takes the first match. + let mut r = build( + "package P { + part def V; + attribute def Mass; + part v : V; + attribute m : Mass; + action def Go; + action go : Go; + }", + ); + let v = elem(&mut r, "P::v"); + let vd = elem(&mut r, "P::V"); + assert_eq!(many(&mut r, v, "definition"), [vd]); + assert_eq!(many(&mut r, v, "occurrenceDefinition"), [vd]); + assert_eq!(many(&mut r, v, "itemDefinition"), [vd]); + assert_eq!(many(&mut r, v, "partDefinition"), [vd]); + let m = elem(&mut r, "P::m"); + let md = elem(&mut r, "P::Mass"); + assert_eq!(many(&mut r, m, "attributeDefinition"), [md]); + assert_eq!(r.derived(m, "partDefinition"), Derived::NotDeclared); + let go = elem(&mut r, "P::go"); + let god = elem(&mut r, "P::Go"); + assert_eq!(many(&mut r, go, "actionDefinition"), [god]); + assert_eq!(derives("ActionUsage", "actionDefinition"), Derives::Exact); + // A composition over a passthrough base is passthrough; the same + // name on FlowDefinition is another property (`associationEnd`). + assert_eq!(derives("FlowUsage", "flowEnd"), Derives::Passthrough); + assert_eq!(derives("FlowDefinition", "flowEnd"), Derives::NotComputed); +} + +#[test] +fn direction_and_end_filters() { + let mut r = build( + "package P { + action def A { in item x; out item y; inout item z; item w; } + connection def C { end e1 : A; end e2 : A; } + }", + ); + let a = elem(&mut r, "P::A"); + let list = |r: &mut ResolvedModel, e, n: &str| -> Vec { + let items = many(r, e, n); + names(r, &items) + }; + assert_eq!(list(&mut r, a, "directedFeature"), ["x", "y", "z"]); + // Feature order, per the OCL — `inout` is not moved after the one-way + // features. + assert_eq!(list(&mut r, a, "input"), ["x", "z"]); + assert_eq!(list(&mut r, a, "output"), ["y", "z"]); + let mut r2 = build("package Q { action def B { inout item z; in item x; out item y; } }"); + let b = elem(&mut r2, "Q::B"); + let items = many(&mut r2, b, "input"); + assert_eq!(names(&mut r2, &items), ["z", "x"]); + let items = many(&mut r2, b, "output"); + assert_eq!(names(&mut r2, &items), ["z", "y"]); + assert_eq!(list(&mut r, a, "directedUsage"), ["x", "y", "z"]); + let c = elem(&mut r, "P::C"); + assert_eq!(list(&mut r, c, "ownedEndFeature"), ["e1", "e2"]); + assert_eq!(list(&mut r, c, "endFeature"), ["e1", "e2"]); + assert_eq!( + derives("ConnectionDefinition", "endFeature"), + Derives::Passthrough + ); +} + +#[test] +fn type_closes_over_typing_features() { + // Feature::type walks the typing features: a feature typed only + // through subsetting, redefinition or a chain inherits its target's + // types, so the definition back-references follow. + let mut r = build( + "package P { + part def V; + part v : V; + part w :> v; + part x :>> w; + part y : V { part z :> v; } + }", + ); + let vd = elem(&mut r, "P::V"); + for qn in ["P::v", "P::w", "P::x", "P::y::z"] { + let f = elem(&mut r, qn); + assert_eq!(many(&mut r, f, "type"), [vd], "{qn}"); + assert_eq!(many(&mut r, f, "partDefinition"), [vd], "{qn}"); + } +} + +#[test] +fn a_composition_is_not_computed_where_its_base_is_another_property() { + // `action` on a StateSubactionMembership is a single required + // reference (the owned member), not `usage->selectByKind(ActionUsage)`: + // a membership-side name, exact there. + assert_eq!( + derives("StateSubactionMembership", "action"), + Derives::Exact + ); + assert_eq!( + derives("RequirementConstraintMembership", "ownedConstraint"), + Derives::Exact + ); + assert_eq!(derives("ActionDefinition", "action"), Derives::Passthrough); + let mut r = build( + "package P { + state def S { state s1; entry action a; } + }", + ); + let m = r + .elements_of_metaclass("StateSubactionMembership") + .into_iter() + .find(|&x| !r.is_library_element(x)) + .expect("the entry membership"); + assert!(matches!( + r.derived(m, "action"), + Derived::Value(DerivedValue::Element(_)) + )); + // Compositions over the owned relationships are exact. + assert_eq!(derives("PartDefinition", "ownedDisjoining"), Derives::Exact); + assert_eq!(derives("PartUsage", "nestedEnumeration"), Derives::Exact); + assert_eq!(derives("PortUsage", "portDefinition"), Derives::Exact); + assert_eq!( + derives("ConjugatedPortTyping", "portDefinition"), + Derives::NotComputed + ); +} + +#[test] +fn annotation_family_reads_both_shapes() { + // This toolkit emits the `about` shape: the annotating element owns + // the Annotation, which names the annotated element. + let mut r = build( + "package P { + part def V; + comment C about V /* hi */ + doc /* on P */ + }", + ); + let p = elem(&mut r, "P"); + let v = elem(&mut r, "P::V"); + let c = elem(&mut r, "P::C"); + let ann = many(&mut r, c, "annotation"); + assert_eq!(ann.len(), 1); + assert_eq!(r.element_type(ann[0]), "Annotation"); + assert_eq!(many(&mut r, c, "ownedAnnotatingRelationship"), ann); + assert!(many(&mut r, c, "ownedAnnotation").is_empty()); + assert_eq!(many(&mut r, c, "annotatedElement"), [v]); + // The Annotation's own ends. + assert_eq!(one(&mut r, ann[0], "annotatingElement"), Some(c)); + assert_eq!(one(&mut r, ann[0], "owningAnnotatingElement"), Some(c)); + assert_eq!(one(&mut r, ann[0], "ownedAnnotatingElement"), None); + assert_eq!(one(&mut r, ann[0], "owningAnnotatedElement"), None); + // `annotatedElement` is owned on Annotation, derived on the + // annotating element. + assert_eq!(r.derived(ann[0], "annotatedElement"), Derived::NotDeclared); + assert_eq!(one(&mut r, c, "owningAnnotatingRelationship"), None); + // An annotating element with no Annotation annotates its owner. + let doc = r + .elements_of_metaclass("Documentation") + .into_iter() + .find(|&x| !r.is_library_element(x)) + .expect("the doc"); + assert!(many(&mut r, doc, "annotation").is_empty()); + assert_eq!(many(&mut r, doc, "annotatedElement"), [p]); + assert_eq!(one(&mut r, doc, "documentedElement"), Some(p)); + // `representedElement` is a TextualRepresentation property. + assert_eq!(r.derived(doc, "representedElement"), Derived::NotDeclared); +} + +#[test] +fn text_multiplicity_reference_and_conjugator() { + let mut r = build( + "package P { + requirement def R { doc /* must hold */ doc /* and also */ } + part def V { part w[2]; ref part x; } + port def Q; part p2 : ~Q; + }", + ); + let req = elem(&mut r, "P::R"); + assert_eq!( + r.derived(req, "text"), + Derived::Value(DerivedValue::Strings(vec![ + "must hold ".into(), + "and also ".into() + ])) + ); + let w = elem(&mut r, "P::V::w"); + let m = one(&mut r, w, "multiplicity").expect("w[2] has a multiplicity"); + assert_eq!(r.element_type(m), "MultiplicityRange"); + let x = elem(&mut r, "P::V::x"); + assert_eq!( + r.derived(x, "isReference"), + Derived::Value(DerivedValue::Bool(true)) + ); + assert_eq!( + r.derived(w, "isReference"), + Derived::Value(DerivedValue::Bool(false)) + ); + // A conjugated port definition owns its PortConjugation. + let cpd = r + .elements_of_metaclass("ConjugatedPortDefinition") + .into_iter() + .find(|&x| !r.is_library_element(x)) + .expect("`~Q` synthesizes a conjugated port definition"); + let c = one(&mut r, cpd, "ownedConjugator").expect("the conjugator"); + assert_eq!(r.element_type(c), "PortConjugation"); + let orig = one(&mut r, cpd, "originalPortDefinition").expect("original"); + assert_eq!(r.element_type(orig), "PortDefinition"); +} + +fn string(r: &mut ResolvedModel, e: ElementRef, name: &str) -> Option { + match r.derived(e, name) { + Derived::Value(DerivedValue::Str(s)) => Some(s), + Derived::Value(DerivedValue::Null) => None, + other => panic!("{name}: expected a string, got {other:?}"), + } +} + +/// `Element::name` / `shortName` / `qualifiedName` per KerML 8.2.3.5: an +/// unnamed feature is named by the feature it redefines (recursively), +/// references, or chains to; `qualifiedName` falls back to the short name +/// where `name` does not. +#[test] +fn names_follow_the_naming_feature() { + let mut r = build( + "package P { + part def Tank { attribute mass = 1; } + part base { part tank : Tank; part : Tank; part <'fuel tank'> ft : Tank; } + part actual :> base { + part :>> tank { attribute :>> mass = 2; } + part :>> spare; + part :>> ft; + part aka :>> tank; + part :>> ft; + } + }", + ); + let tank = elem(&mut r, "P::actual::tank"); + assert_eq!(string(&mut r, tank, "name").as_deref(), Some("tank")); + assert_eq!(string(&mut r, tank, "shortName"), None); + assert_eq!( + string(&mut r, tank, "qualifiedName").as_deref(), + Some("P::actual::tank") + ); + let mass = elem(&mut r, "P::actual::tank::mass"); + assert_eq!(string(&mut r, mass, "name").as_deref(), Some("mass")); + assert_eq!( + string(&mut r, mass, "qualifiedName").as_deref(), + Some("P::actual::tank::mass") + ); + // A naming feature with only a short name: `name` stays null, + // `shortName` is the naming feature's, and `qualifiedName` uses it. + let spare = elem(&mut r, "P::actual::spare"); + assert_eq!(string(&mut r, spare, "name"), None); + assert_eq!(string(&mut r, spare, "shortName").as_deref(), Some("spare")); + assert_eq!( + string(&mut r, spare, "qualifiedName").as_deref(), + Some("P::actual::spare") + ); + // Both names come from the naming feature. + let ft = elem(&mut r, "P::actual::ft"); + assert_eq!(string(&mut r, ft, "name").as_deref(), Some("ft")); + assert_eq!( + string(&mut r, ft, "shortName").as_deref(), + Some("fuel tank") + ); + // Declaring either name makes both names the declared ones (KerML + // `effectiveName()`: `if declaredShortName <> null or declaredName <> + // null then declaredName …`): no short name from the naming feature + // beside a declared name, and no name beside a declared short name. + let aka = elem(&mut r, "P::actual::aka"); + assert_eq!(string(&mut r, aka, "name").as_deref(), Some("aka")); + assert_eq!(string(&mut r, aka, "shortName"), None); + let x = elem(&mut r, "P::actual::x"); + assert_eq!(string(&mut r, x, "name"), None); + assert_eq!(string(&mut r, x, "shortName").as_deref(), Some("x")); + assert_eq!( + string(&mut r, x, "qualifiedName").as_deref(), + Some("P::actual::x") + ); + // The public accessors agree with the spec names; the lookup name + // keeps the declared-or-short-or-written notion. + assert_eq!(r.element_effective_name(spare), None); + assert_eq!(r.element_short_name(spare).as_deref(), Some("spare")); + assert_eq!(r.element_lookup_name(spare).as_deref(), Some("spare")); + assert_eq!(r.element_declared_short_name(spare), None); +} + +/// Implied positional names: the members whose owned feature implicitly +/// redefines a library feature take that feature's name — connector ends, +/// succession ends, return parameters, subjects, invocation arguments. +#[test] +fn implied_positional_names() { + let mut r = build( + "package P { + part def Tank; + part a : Tank; part b : Tank; + connection c connect a to b; + action def A { + action x; action y; + succession first x then y; + } + calc def Sum { in p; in q; return : Tank; } + attribute total = Sum(1, 2); + calc def Gap { in : Tank; in q; return : Tank; } + attribute gapped = Gap(1, 2); + calc def Both { inout m; in n; return : Tank; } + attribute both = Both(1, 2); + requirement def R { subject : Tank; } + use case def U { actor : Tank; } + }", + ); + let c = elem(&mut r, "P::c"); + let ends = many(&mut r, c, "ownedEndFeature"); + assert_eq!(ends.len(), 2); + assert_eq!(string(&mut r, ends[0], "name").as_deref(), Some("source")); + assert_eq!(string(&mut r, ends[1], "name").as_deref(), Some("target")); + assert_eq!( + string(&mut r, ends[1], "qualifiedName").as_deref(), + Some("P::c::target") + ); + // Succession ends. + let a = elem(&mut r, "P::A"); + let succession = many(&mut r, a, "ownedFeature") + .into_iter() + .find(|&f| r.element_type(f) == "SuccessionAsUsage") + .expect("succession"); + let ends = many(&mut r, succession, "ownedEndFeature"); + assert_eq!( + string(&mut r, ends[0], "name").as_deref(), + Some("earlierOccurrence") + ); + assert_eq!( + string(&mut r, ends[1], "name").as_deref(), + Some("laterOccurrence") + ); + // The unnamed return parameter and subject. + let sum = elem(&mut r, "P::Sum"); + let ret = many(&mut r, sum, "ownedFeature") + .into_iter() + .find(|&f| string(&mut r, f, "name").as_deref() == Some("result")) + .expect("return parameter named result"); + assert_eq!( + string(&mut r, ret, "qualifiedName").as_deref(), + Some("P::Sum::result") + ); + let req = elem(&mut r, "P::R"); + assert!( + many(&mut r, req, "ownedFeature") + .into_iter() + .any(|f| string(&mut r, f, "name").as_deref() == Some("subj")) + ); + // Positional invocation arguments take the callee's `in` parameter + // names, in order. + let total = elem(&mut r, "P::total"); + let invocation = many(&mut r, total, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "InvocationExpression") + .expect("invocation"); + let args: Vec = many(&mut r, invocation, "ownedFeature") + .into_iter() + .filter_map(|f| string(&mut r, f, "name")) + .collect(); + assert_eq!(args, vec!["p".to_string(), "q".to_string()]); + // An unnamed input parameter holds its position; `inout` counts. + let arg_names = |r: &mut ResolvedModel, owner: &str| -> Vec> { + let e = elem(r, owner); + let invocation = many(r, e, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "InvocationExpression") + .expect("invocation"); + many(r, invocation, "ownedFeature") + .into_iter() + .map(|f| string(r, f, "name")) + .collect() + }; + let gapped = arg_names(&mut r, "P::gapped"); + assert!(gapped.contains(&Some("q".to_string()))); + assert!(!gapped.contains(&Some("p".to_string()))); + assert_eq!(gapped.iter().flatten().count(), 1); + let both: Vec = arg_names(&mut r, "P::both").into_iter().flatten().collect(); + assert_eq!(both, vec!["m".to_string(), "n".to_string()]); + // An actor parameter's reference carries no name. + let u = elem(&mut r, "P::U"); + let actor = many(&mut r, u, "ownedFeature") + .into_iter() + .find(|&f| r.element_type(f) == "PartUsage") + .expect("actor parameter"); + assert_eq!(string(&mut r, actor, "name"), None); +} + +/// `qualifiedName` is null for an element without an `owningNamespace` +/// — a chain feature owned by its ReferenceSubsetting, an expression +/// owned by a FeatureValue — even when it has a name. +#[test] +fn qualified_name_needs_a_membership_chain() { + let mut r = build( + "package P { + part def Tank { attribute mass; } + part t : Tank; part t2 : Tank; + attribute m = t.mass; + connection c connect t.mass to t.mass; + connection d connect t to t2; + }", + ); + let c = elem(&mut r, "P::c"); + let end = many(&mut r, c, "ownedEndFeature")[0]; + // The end references a chain feature it owns through the + // ReferenceSubsetting; the chain is named by its last link but has + // no owning namespace. + let chain = many(&mut r, end, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "Feature" || r.element_type(e) == "ReferenceUsage") + .expect("chain feature"); + assert_eq!(string(&mut r, chain, "name").as_deref(), Some("mass")); + assert_eq!(string(&mut r, chain, "qualifiedName"), None); + assert_eq!(r.element_qualified_name(chain), None); + // The reference spelling joins the lookup names, not the + // specification's: an end of `connect t to t2` is `P::d::source` by + // its implied positional name but was written under no name at all. + let d = elem(&mut r, "P::d"); + let end = many(&mut r, d, "ownedEndFeature")[0]; + assert_eq!( + string(&mut r, end, "qualifiedName").as_deref(), + Some("P::d::source") + ); + assert_eq!(r.element_lookup_name(end), None); + assert_eq!(r.element_reference_spelling(end), None); +} + +/// A reference-typed property reports a target outside the model instead +/// of dropping it: an unresolved spelling by its text, an id the model +/// does not hold as external. +#[test] +fn references_outside_the_model_are_reported() { + let mut r = build( + "package P { + attribute m : Real; + comment about Base::Anything /* c */ + import ISQ::mass; + part def T { attribute a; part sub; } + part t : T; + attribute x = t.sub; + connection c connect t.a to t.sub; + }", + ); + let m = elem(&mut r, "P::m"); + assert_eq!( + refs(&mut r, m, "type"), + vec![Reference::Unresolved("Real".to_string())] + ); + // The comment's target and the import's target never resolved. + let p = elem(&mut r, "P"); + let comment = many(&mut r, p, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "Comment") + .expect("comment"); + assert_eq!( + refs(&mut r, comment, "annotatedElement"), + vec![Reference::Unresolved("Base::Anything".to_string())] + ); + let import = many(&mut r, p, "ownedImport")[0]; + assert_eq!( + refs(&mut r, import, "importedElement"), + vec![Reference::Unresolved("ISQ::mass".to_string())] + ); + // `member` lists non-owning memberships' targets too (none here + // outside the model). + assert!( + refs(&mut r, p, "member") + .iter() + .all(|x| x.element().is_some()) + ); + // A feature chain: `chainingFeature` in order, `featureTarget` the + // last link, `self` for an unchained feature. + let t = elem(&mut r, "P::t"); + assert_eq!(one(&mut r, t, "featureTarget"), Some(t)); + let c = elem(&mut r, "P::c"); + let end = many(&mut r, c, "ownedEndFeature")[1]; + let chain = many(&mut r, end, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "ReferenceUsage" || r.element_type(e) == "Feature") + .expect("chain feature"); + let links = many(&mut r, chain, "chainingFeature"); + assert_eq!(names(&mut r, &links), vec!["t", "sub"]); + let sub = elem(&mut r, "P::T::sub"); + assert_eq!(one(&mut r, chain, "featureTarget"), Some(sub)); + let chainings = many(&mut r, chain, "ownedFeatureChaining"); + assert_eq!(chainings.len(), 2); + assert_eq!(one(&mut r, chainings[0], "featureChained"), Some(chain)); + // The value helpers. + let v = r.derived(chain, "chainingFeature"); + if let Derived::Value(v) = v { + assert_eq!(v.elements(), links); + assert_eq!(v.element(), None); + } +} + +/// The implied relationships are relationship elements of the model once +/// asked for: the library specializations of each kind (SysML Tables +/// 31/32) and a variant's specialization of its variation. They are +/// listed by the relationship families, owned by their specific side, +/// and carry the endpoint families like any relationship — while the +/// explicit graph the resolver and lints iterate stays as built. None +/// exist for a model whose library bases are unknown. +#[test] +fn implied_relationships_are_materialized_on_demand() { + let src = "package P { + part def V; + part def W :> V; + enum def Color { red; green; } + part v : V; + part w :> v; + part def Box { variant part small : V; variant part sized : Box; } + variation part vb : Box { variant part tiny : V; } + attribute c : Color; + }"; + // Without a library or a name table: nothing, not even the variant + // specializations, so `isImpliedIncluded = false` holds. + let mut r = build(src); + let red = elem(&mut r, "P::Color::red"); + assert!(r.implied_relationships(red).is_empty()); + assert_eq!(many(&mut r, red, "ownedSpecialization"), Vec::new()); + assert_eq!(refs(&mut r, red, "type"), Vec::new()); + // With the bases known. + let mut r = build(src); + let mut names = std::collections::HashMap::new(); + names.insert( + uuid::Uuid::new_v4().to_string(), + vec!["Parts".to_string(), "Part".to_string()], + ); + r.set_library_names(&names); + let explicit: Vec = r.user_elements().collect(); + let typings_before = r.elements_of_metaclass("FeatureTyping"); + let red = elem(&mut r, "P::Color::red"); + let implied = r.implied_relationships(red); + assert_eq!(implied.len(), 1); + let typing = implied[0]; + assert!(r.is_implied(typing)); + assert_eq!(r.element_type(typing), "FeatureTyping"); + let color = elem(&mut r, "P::Color"); + assert_eq!(one(&mut r, typing, "owningType"), Some(red)); + assert_eq!(one(&mut r, typing, "owningFeature"), Some(red)); + let (source, target) = r.relationship_ends(typing); + assert_eq!(source, vec![Reference::Element(red)]); + assert_eq!(target, vec![Reference::Element(color)]); + assert_eq!( + refs(&mut r, typing, "relatedElement"), + vec![Reference::Element(red), Reference::Element(color)] + ); + assert_eq!(one(&mut r, typing, "owner"), None); + assert_eq!( + r.element_properties(typing) + .get("isImplied") + .and_then(|v| v.as_bool()), + Some(true) + ); + // The relationship families list it; the navigation accessor keeps + // the explicit graph; `type` and the definition back-references follow + // it. + assert_eq!(many(&mut r, red, "ownedSpecialization"), vec![typing]); + assert_eq!(many(&mut r, red, "ownedTyping"), vec![typing]); + assert_eq!(r.owned_relationships(red), Vec::new()); + assert_eq!(many(&mut r, red, "type"), vec![color]); + assert_eq!(one(&mut r, red, "enumerationDefinition"), Some(color)); + // A variant of a variation definition is typed by it — unless it + // already is; a variant of a variation usage subsets it. + let small = elem(&mut r, "P::Box::small"); + let boxdef = elem(&mut r, "P::Box"); + let rels = r.implied_relationships(small); + assert_eq!(rels.len(), 1); + assert_eq!(r.element_type(rels[0]), "FeatureTyping"); + assert_eq!( + r.relationship_ends(rels[0]).1, + vec![Reference::Element(boxdef)] + ); + let sized = elem(&mut r, "P::Box::sized"); + assert!(r.implied_relationships(sized).is_empty()); + let tiny = elem(&mut r, "P::vb::tiny"); + let vb = elem(&mut r, "P::vb"); + let rels = r.implied_relationships(tiny); + assert_eq!(rels.len(), 1); + assert_eq!(r.element_type(rels[0]), "Subsetting"); + assert_eq!(r.relationship_ends(rels[0]).1, vec![Reference::Element(vb)]); + // The explicit specialization stays where it was, first in the list. + let w = elem(&mut r, "P::w"); + let subs = many(&mut r, w, "ownedSubsetting"); + assert_eq!(subs.len(), 1); + assert!(!r.is_implied(subs[0])); + // The element iteration is unchanged by the materialization. + let after: Vec = r.user_elements().collect(); + assert_eq!(after, explicit); + assert_eq!(r.elements_of_metaclass("FeatureTyping"), typings_before); + // Ids are the emitter's: uuid5(OID, "/implied0"). + let expected = uuid::Uuid::new_v5( + &uuid::Uuid::NAMESPACE_OID, + format!("{}/implied0", r.element_id(red)).as_bytes(), + ); + assert_eq!(r.element_id(typing), expected); +} + +/// The checks read the explicit model: validating after the layer +/// materialized the implied relationships reports what validating before +/// did. +#[test] +fn materialization_does_not_change_the_checks() { + let src = "package P { + part def V; + enum def Color { red; green; } + connection def C { end part a : V; } + attribute c : Color; + }"; + let mut model = Model::new(); + model.add_source("m.sysml", src); + let mut r = ResolvedModel::build(&model); + let mut names = std::collections::HashMap::new(); + names.insert( + uuid::Uuid::new_v4().to_string(), + vec!["Connections".to_string(), "Connection".to_string()], + ); + r.set_library_names(&names); + let before = sysmlv2_parser::check::validate_model_with(&mut r, &model); + let red = elem(&mut r, "P::Color::red"); + assert!(!r.implied_relationships(red).is_empty()); + let c = elem(&mut r, "P::C"); + assert!(!many(&mut r, c, "ownedSubclassification").is_empty()); + let after = sysmlv2_parser::check::validate_model_with(&mut r, &model); + assert_eq!( + format!("{before:?}"), + format!("{after:?}"), + "diagnostics must not depend on the implied relationships" + ); +} + +/// With a library name table, the Tables 31/32 specializations target +/// the named library elements, which are outside the model. +#[test] +fn library_specializations_through_a_name_table() { + let mut r = build("package P { part def V; part v : V; part w :> v; }"); + let part_id = uuid::Uuid::new_v4(); + let parts_id = uuid::Uuid::new_v4(); + let mut names = std::collections::HashMap::new(); + names.insert( + part_id.to_string(), + vec!["Parts".to_string(), "Part".to_string()], + ); + names.insert( + parts_id.to_string(), + vec!["Parts".to_string(), "parts".to_string()], + ); + r.set_library_names(&names); + let v = elem(&mut r, "P::V"); + let sub = many(&mut r, v, "ownedSubclassification"); + assert_eq!(sub.len(), 1); + assert_eq!( + r.relationship_ends(sub[0]).1, + vec![Reference::External(part_id)] + ); + assert_eq!(one(&mut r, sub[0], "owningClassifier"), Some(v)); + // A usage typed but not subsetted still gets its implied subsetting; + // one that subsets explicitly does not (anti-redundancy). + let usage = elem(&mut r, "P::v"); + let subs = many(&mut r, usage, "ownedSubsetting"); + assert_eq!(subs.len(), 1); + assert_eq!( + r.relationship_ends(subs[0]).1, + vec![Reference::External(parts_id)] + ); + let w = elem(&mut r, "P::w"); + assert!( + many(&mut r, w, "ownedSubsetting") + .iter() + .all(|&s| !r.is_implied(s)) + ); +} + +/// `source`/`target` (the navigation accessor — owned in the abstract +/// syntax) and the derived `relatedElement` for the relationship kinds. +#[test] +fn relationship_endpoints() { + let mut r = build( + "package Q { part def Z; } + package P { + import Q::*; + part def V :> Z; + part v : V; + alias vv for v; + dependency v to V; + comment about v /* c */ + }", + ); + let p = elem(&mut r, "P"); + let v_def = elem(&mut r, "P::V"); + let z = elem(&mut r, "Q::Z"); + let v = elem(&mut r, "P::v"); + let sub = many(&mut r, v_def, "ownedSubclassification")[0]; + assert_eq!( + refs(&mut r, sub, "relatedElement"), + vec![Reference::Element(v_def), Reference::Element(z)] + ); + // Memberships: owner → member; an alias's member is its target. + let alias = many(&mut r, p, "ownedMembership") + .into_iter() + .find(|&m| r.membership_is_alias(m)) + .expect("alias"); + assert_eq!( + r.relationship_ends(alias), + (vec![Reference::Element(p)], vec![Reference::Element(v)]) + ); + assert_eq!(r.derived(alias, "source"), Derived::NotDeclared); + // An import: owner → imported namespace. + let import = many(&mut r, p, "ownedImport")[0]; + let q = elem(&mut r, "Q"); + assert_eq!(r.relationship_ends(import).1, vec![Reference::Element(q)]); + // A dependency: clients → suppliers. + let dep = many(&mut r, p, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "Dependency") + .expect("dependency"); + assert_eq!( + r.relationship_ends(dep), + (vec![Reference::Element(v)], vec![Reference::Element(v_def)]) + ); + assert_eq!( + refs(&mut r, dep, "relatedElement"), + vec![Reference::Element(v), Reference::Element(v_def)] + ); + // An annotation: annotating → annotated. + let comment = many(&mut r, p, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "Comment") + .expect("comment"); + let annotation = many(&mut r, comment, "annotation")[0]; + assert_eq!( + r.relationship_ends(annotation), + ( + vec![Reference::Element(comment)], + vec![Reference::Element(v)] + ) + ); +} + +/// Connector and flow ends at the passthrough level: the owned end +/// features, the features they reference, and a flow's source output / +/// target input features. +#[test] +fn connector_and_flow_ends() { + let mut r = build( + "package P { + part def T { port p; attribute a; } + part x : T; part y : T; + connection c connect x.p to y.p; + flow f from x.a to y.a; + attribute z = x.a; + }", + ); + let c = elem(&mut r, "P::c"); + let ends = many(&mut r, c, "connectorEnd"); + assert_eq!(ends.len(), 2); + assert_eq!(ends, many(&mut r, c, "ownedEndFeature")); + // The related features are the chain features the ends reference. + let related = refs(&mut r, c, "relatedFeature"); + assert_eq!(related.len(), 2); + assert_eq!(refs(&mut r, c, "sourceFeature"), vec![related[0].clone()]); + assert_eq!(refs(&mut r, c, "targetFeature"), vec![related[1].clone()]); + assert_eq!( + derives("ConnectionUsage", "targetFeature"), + Derives::Passthrough + ); + // Another property of the same name on an expression is not this one + // (the accessed feature, exact). + assert_eq!( + derives("FeatureChainExpression", "targetFeature"), + Derives::Exact + ); + let f = elem(&mut r, "P::f"); + let flow_ends = many(&mut r, f, "flowEnd"); + assert_eq!(flow_ends.len(), 2); + assert!(flow_ends.iter().all(|&e| r.element_type(e) == "FlowEnd")); + let out = one(&mut r, f, "sourceOutputFeature").expect("source output feature"); + let inp = one(&mut r, f, "targetInputFeature").expect("target input feature"); + assert_eq!(one(&mut r, out, "owningType"), Some(flow_ends[0])); + assert_eq!(one(&mut r, inp, "owningType"), Some(flow_ends[1])); +} + +/// `member` lists a non-owning membership's unresolved target by its +/// spelling; `qualifiedName` needs every owner named. +#[test] +fn members_and_qualified_names_through_unnamed_owners() { + let mut r = build( + "package P { + alias thing for Nope::thing; + part { part child; } + }", + ); + let p = elem(&mut r, "P"); + assert!(refs(&mut r, p, "member").contains(&Reference::Unresolved("Nope::thing".to_string()))); + let child = r + .elements_of_metaclass("PartUsage") + .into_iter() + .find(|&e| r.element_name(e) == Some("child")) + .expect("child"); + assert_eq!(string(&mut r, child, "name").as_deref(), Some("child")); + assert_eq!(string(&mut r, child, "qualifiedName"), None); +} + +// ---- M33f: behavior, expression, requirement and view structure ---- + +/// States and transitions: the sub-actions by membership kind; the +/// transition's trigger, guard, effect, succession, source and target. +#[test] +fn state_and_transition_structure() { + let mut r = build( + "package P { + item def Signal; + state def Machine { + entry action e1; + do action d1; + exit action x1; + state s1; + state s2 { entry action inner; } + transition t1 first s1 accept sig : Signal if true do action eff then s2; + transition t2 first s2 then s1; + } + }", + ); + let m = elem(&mut r, "P::Machine"); + let e1 = elem(&mut r, "P::Machine::e1"); + let d1 = elem(&mut r, "P::Machine::d1"); + let x1 = elem(&mut r, "P::Machine::x1"); + assert_eq!(one(&mut r, m, "entryAction"), Some(e1)); + assert_eq!(one(&mut r, m, "doAction"), Some(d1)); + assert_eq!(one(&mut r, m, "exitAction"), Some(x1)); + let s2 = elem(&mut r, "P::Machine::s2"); + assert_eq!(one(&mut r, s2, "doAction"), None); + assert!(one(&mut r, s2, "entryAction").is_some()); + // The membership-side `action` is the owned member. + let entry_membership = many(&mut r, m, "ownedFeatureMembership") + .into_iter() + .find(|&fm| r.element_type(fm) == "StateSubactionMembership") + .expect("state subaction membership"); + assert_eq!(one(&mut r, entry_membership, "action"), Some(e1)); + assert_eq!( + derives("StateSubactionMembership", "action"), + Derives::Exact + ); + let t1 = elem(&mut r, "P::Machine::t1"); + let s1 = elem(&mut r, "P::Machine::s1"); + let triggers = many(&mut r, t1, "triggerAction"); + assert_eq!(triggers.len(), 1); + assert_eq!(r.element_type(triggers[0]), "AcceptActionUsage"); + let guards = many(&mut r, t1, "guardExpression"); + assert_eq!(guards.len(), 1); + assert!( + r.element_type(guards[0]).ends_with("Boolean") + || r.element_type(guards[0]).contains("Expression") + ); + let effects = many(&mut r, t1, "effectAction"); + assert_eq!(names(&mut r, &effects), vec!["eff"]); + let succession = one(&mut r, t1, "succession").expect("succession"); + assert_eq!(r.element_type(succession), "SuccessionAsUsage"); + assert_eq!(one(&mut r, t1, "source"), Some(s1)); + assert_eq!(one(&mut r, t1, "target"), Some(s2)); + // The transition-feature membership's own reference. + let tfm = many(&mut r, t1, "ownedFeatureMembership") + .into_iter() + .find(|&fm| r.element_type(fm) == "TransitionFeatureMembership") + .expect("transition feature membership"); + assert_eq!(one(&mut r, tfm, "transitionFeature"), Some(triggers[0])); + let t2 = elem(&mut r, "P::Machine::t2"); + assert_eq!(many(&mut r, t2, "triggerAction"), Vec::new()); + assert_eq!(one(&mut r, t2, "source"), Some(s2)); + assert_eq!(one(&mut r, t2, "target"), Some(s1)); +} + +/// Control and communication actions: arguments and bodies by input +/// parameter position, per the specification's `inputParameter(i)` / +/// `argument(i)` with the parameter-membership default direction. +#[test] +fn control_and_communication_actions() { + let mut r = build( + "package P { + item def Msg; + attribute x : Boolean; + part def Peer { port p; } + part peer : Peer; + action def A { + action i1 if x { action thenA; } else { action elseA; } + action w1 while x { action bodyW; } until x; + action f1 for i in 1..3 { action bodyF; } + action s1 send 1 via peer.p to peer; + action a1 accept m : Msg via peer.p; + action g1 assign x := true; + action k1 terminate peer; + } + }", + ); + let i1 = elem(&mut r, "P::A::i1"); + let cond = one(&mut r, i1, "ifArgument").expect("if argument"); + assert!(r.element_type(cond).contains("Expression")); + let then_a = one(&mut r, i1, "thenAction").expect("then"); + assert_eq!(r.element_type(then_a), "ActionUsage"); + let else_a = one(&mut r, i1, "elseAction").expect("else"); + assert_ne!(then_a, else_a); + let w1 = elem(&mut r, "P::A::w1"); + assert!(one(&mut r, w1, "whileArgument").is_some()); + assert!(one(&mut r, w1, "bodyAction").is_some()); + assert!(one(&mut r, w1, "untilArgument").is_some()); + let f1 = elem(&mut r, "P::A::f1"); + let var = one(&mut r, f1, "loopVariable").expect("loop variable"); + assert_eq!(r.element_name(var), Some("i")); + let seq = one(&mut r, f1, "seqArgument").expect("sequence"); + assert!(r.element_type(seq).contains("Expression")); + assert!(one(&mut r, f1, "bodyAction").is_some()); + let s1 = elem(&mut r, "P::A::s1"); + assert!(one(&mut r, s1, "payloadArgument").is_some()); + assert!(one(&mut r, s1, "senderArgument").is_some()); + assert!(one(&mut r, s1, "receiverArgument").is_some()); + let a1 = elem(&mut r, "P::A::a1"); + let payload = one(&mut r, a1, "payloadParameter").expect("payload parameter"); + assert_eq!(r.element_name(payload), Some("m")); + assert_eq!(one(&mut r, a1, "payloadArgument"), None); + assert!(one(&mut r, a1, "receiverArgument").is_some()); + let g1 = elem(&mut r, "P::A::g1"); + assert!(one(&mut r, g1, "targetArgument").is_some()); + assert!(one(&mut r, g1, "valueExpression").is_some()); + let k1 = elem(&mut r, "P::A::k1"); + assert!(one(&mut r, k1, "terminatedOccurrenceArgument").is_some()); + // Positions are exact: an unspelled direction counts as `in`. + assert_eq!(derives("IfActionUsage", "thenAction"), Derives::Exact); + assert_eq!( + derives("SendActionUsage", "receiverArgument"), + Derives::Exact + ); +} + +/// References through subsetting: perform/exhibit/include/event +/// dereference to the chain target, else the usage itself; expressions +/// know their result, function, instantiated type, arguments and +/// referents; multiplicity ranges their bounds. +#[test] +fn perform_and_expression_structure() { + let mut r = build( + "package P { + action def A { in p; in q; return : Real; } + action a : A; + part def Car { action drive; } + part car : Car; + action def Use { + perform action pa ::> car.drive; + perform action lone; + action computed = A(1, 2); + action named = A(q = 2, p = 1); + } + calc def F { in n; return : Real; } + attribute v = F(3); + attribute w = v.x; + part items[2..5]; + part one[1]; + use case def U { include use case inc; } + }", + ); + let pa = elem(&mut r, "P::Use::pa"); + let drive = elem(&mut r, "P::Car::drive"); + assert_eq!(one(&mut r, pa, "performedAction"), Some(drive)); + assert_eq!(one(&mut r, pa, "eventOccurrence"), Some(drive)); + let lone = elem(&mut r, "P::Use::lone"); + assert_eq!(one(&mut r, lone, "performedAction"), Some(lone)); + let u = elem(&mut r, "P::U"); + let inc = elem(&mut r, "P::U::inc"); + assert_eq!(many(&mut r, u, "includedUseCase"), vec![inc]); + // Functions and expressions. + let f = elem(&mut r, "P::F"); + let ret = one(&mut r, f, "result").expect("return parameter"); + assert_eq!(string(&mut r, ret, "name").as_deref(), Some("result")); + assert_eq!(derives("Function", "result"), Derives::Passthrough); + let v = elem(&mut r, "P::v"); + let invocation = many(&mut r, v, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "InvocationExpression") + .expect("invocation"); + assert_eq!(one(&mut r, invocation, "instantiatedType"), Some(f)); + assert_eq!(one(&mut r, invocation, "result"), None); + let args = many(&mut r, invocation, "argument"); + assert_eq!(args.len(), 1); + assert_eq!(r.element_type(args[0]), "LiteralInteger"); + // Named arguments are matched by the callee's parameter, not position. + let named = elem(&mut r, "P::Use::named"); + let call = many(&mut r, named, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "InvocationExpression") + .expect("invocation"); + let args = many(&mut r, call, "argument"); + let literals: Vec = args + .iter() + .map(|&a| { + r.element_properties(a) + .get("value") + .map(|v| v.to_string()) + .unwrap_or_default() + }) + .collect(); + assert_eq!(literals, vec!["1", "2"]); + // A feature reference expression's referent, a chain expression's + // target feature. + let w = elem(&mut r, "P::w"); + let chain = many(&mut r, w, "ownedElement") + .into_iter() + .find(|&e| r.element_type(e) == "FeatureChainExpression") + .expect("chain expression"); + assert!(refs(&mut r, chain, "targetFeature").len() == 1); + assert_eq!( + derives("FeatureChainExpression", "targetFeature"), + Derives::Exact + ); + // Multiplicity bounds. + let items = elem(&mut r, "P::items"); + let range = one(&mut r, items, "multiplicity").expect("range"); + let bounds = many(&mut r, range, "bound"); + assert_eq!(bounds.len(), 2); + assert_eq!(one(&mut r, range, "lowerBound"), Some(bounds[0])); + assert_eq!(one(&mut r, range, "upperBound"), Some(bounds[1])); + let one_ = elem(&mut r, "P::one"); + let range = one(&mut r, one_, "multiplicity").expect("range"); + assert_eq!(one(&mut r, range, "lowerBound"), None); + assert!(one(&mut r, range, "upperBound").is_some()); + // Feature values. + let fv = r + .owned_relationships(v) + .into_iter() + .find(|&e| r.element_type(e) == "FeatureValue") + .expect("feature value"); + assert_eq!(one(&mut r, fv, "featureWithValue"), Some(v)); + assert_eq!(one(&mut r, fv, "value"), Some(invocation)); +} + +/// Requirements, cases and views: subjects, actors, stakeholders, +/// objectives, required and assumed constraints, framed concerns, +/// verified and satisfied requirements, renderings and conditions. +#[test] +fn requirement_case_and_view_structure() { + let mut r = build( + "package P { + part def Vehicle; + part def Person; + concern def Safety { stakeholder driver : Person; } + requirement def R { + subject v : Vehicle; + actor user : Person; + stakeholder owner : Person; + require constraint c1 { true } + assume constraint c2 { true } + frame concern sf : Safety; + } + requirement r1 : R; + part car : Vehicle { satisfy r1 by car; } + verification def V { + objective { verify r1; } + } + rendering def Tree; + rendering asTree : Tree; + view def VD { render asTree; filter @Safety; } + view v1 : VD { expose P::*; } + package Q { filter @Safety; } + viewpoint def VP { frame concern sfv : Safety; } + }", + ); + let rd = elem(&mut r, "P::R"); + let v = elem(&mut r, "P::R::v"); + let user = elem(&mut r, "P::R::user"); + let owner = elem(&mut r, "P::R::owner"); + let c1 = elem(&mut r, "P::R::c1"); + let c2 = elem(&mut r, "P::R::c2"); + let sf = elem(&mut r, "P::R::sf"); + assert_eq!(one(&mut r, rd, "subjectParameter"), Some(v)); + assert_eq!(many(&mut r, rd, "actorParameter"), vec![user]); + assert_eq!(many(&mut r, rd, "stakeholderParameter"), vec![owner]); + // Framed concerns are required constraints (FramedConcernMembership + // is a RequirementConstraintMembership of kind requirement). + assert_eq!(many(&mut r, rd, "requiredConstraint"), vec![c1, sf]); + assert_eq!(many(&mut r, rd, "assumedConstraint"), vec![c2]); + assert_eq!(many(&mut r, rd, "framedConcern"), vec![sf]); + assert_eq!( + derives("RequirementDefinition", "requiredConstraint"), + Derives::Exact + ); + assert_eq!( + derives("RequirementDefinition", "framedConcern"), + Derives::Passthrough + ); + // The membership-side references. + let memberships = many(&mut r, rd, "ownedFeatureMembership"); + let subject_m = memberships + .iter() + .copied() + .find(|&m| r.element_type(m) == "SubjectMembership") + .unwrap(); + assert_eq!(one(&mut r, subject_m, "ownedSubjectParameter"), Some(v)); + let constraint_m = memberships + .iter() + .copied() + .find(|&m| r.element_type(m) == "RequirementConstraintMembership") + .unwrap(); + assert_eq!(one(&mut r, constraint_m, "ownedConstraint"), Some(c1)); + assert_eq!(one(&mut r, constraint_m, "referencedConstraint"), Some(c1)); + let concern_m = memberships + .iter() + .copied() + .find(|&m| r.element_type(m) == "FramedConcernMembership") + .unwrap(); + assert_eq!(one(&mut r, concern_m, "referencedConcern"), Some(sf)); + // Satisfaction and verification. + let r1 = elem(&mut r, "P::r1"); + let car = elem(&mut r, "P::car"); + let satisfy = many(&mut r, car, "ownedFeature") + .into_iter() + .find(|&f| r.element_type(f) == "SatisfyRequirementUsage") + .expect("satisfy"); + assert_eq!(one(&mut r, satisfy, "satisfiedRequirement"), Some(r1)); + assert_eq!(one(&mut r, satisfy, "assertedConstraint"), Some(r1)); + assert_eq!(one(&mut r, satisfy, "satisfyingFeature"), Some(car)); + let vd = elem(&mut r, "P::V"); + let objective = one(&mut r, vd, "objectiveRequirement").expect("objective"); + assert_eq!(r.element_type(objective), "RequirementUsage"); + assert_eq!(many(&mut r, vd, "verifiedRequirement"), vec![r1]); + let verification_m = many(&mut r, objective, "ownedFeatureMembership") + .into_iter() + .find(|&m| r.element_type(m) == "RequirementVerificationMembership") + .expect("verification membership"); + assert_eq!(one(&mut r, verification_m, "verifiedRequirement"), Some(r1)); + assert_eq!( + derives("RequirementVerificationMembership", "verifiedRequirement"), + Derives::Exact + ); + // Views. + let view_def = elem(&mut r, "P::VD"); + let as_tree = elem(&mut r, "P::asTree"); + assert_eq!(one(&mut r, view_def, "viewRendering"), Some(as_tree)); + let rendering_m = many(&mut r, view_def, "ownedFeatureMembership") + .into_iter() + .find(|&m| r.element_type(m) == "ViewRenderingMembership") + .expect("rendering membership"); + assert_eq!( + one(&mut r, rendering_m, "referencedRendering"), + Some(as_tree) + ); + assert_eq!(many(&mut r, view_def, "viewCondition").len(), 1); + let q = elem(&mut r, "P::Q"); + let conditions = many(&mut r, q, "filterCondition"); + assert_eq!(conditions.len(), 1); + let filter_m = many(&mut r, q, "ownedMembership") + .into_iter() + .find(|&m| r.element_type(m) == "ElementFilterMembership") + .expect("filter membership"); + assert_eq!(one(&mut r, filter_m, "condition"), Some(conditions[0])); + let v1 = elem(&mut r, "P::v1"); + let exposed = many(&mut r, v1, "exposedElement"); + assert!(exposed.contains(&car)); + let vp = elem(&mut r, "P::VP"); + let sfv = elem(&mut r, "P::VP::sfv"); + assert_eq!(many(&mut r, vp, "framedConcern"), vec![sfv]); +} + +/// Membership identity strings and the typing residue: member ids and +/// names, enumerated values, conjugation, association ends, payload +/// types, individual definitions. +#[test] +fn membership_strings_and_typing_residue() { + let mut r = build( + "package P { + enum def Color { red; green; } + port def Pt; + part def Node { port in_ : Pt; port out_ : ~Pt; } + connection def Link { end part a : Node; end part b : Node; } + individual part def Earth :> Node; + part earth : Earth; + alias colour for Color; + }", + ); + let p = elem(&mut r, "P"); + let color = elem(&mut r, "P::Color"); + let red = elem(&mut r, "P::Color::red"); + let green = elem(&mut r, "P::Color::green"); + assert_eq!(many(&mut r, color, "enumeratedValue"), vec![red, green]); + let memberships = many(&mut r, p, "ownedMembership"); + let color_m = memberships + .iter() + .copied() + .find(|&m| one(&mut r, m, "ownedMemberElement") == Some(color)) + .unwrap(); + assert_eq!( + string(&mut r, color_m, "ownedMemberElementId"), + Some(r.element_id(color).to_string()) + ); + assert_eq!( + string(&mut r, color_m, "memberElementId"), + Some(r.element_id(color).to_string()) + ); + assert_eq!( + string(&mut r, color_m, "ownedMemberName").as_deref(), + Some("Color") + ); + assert_eq!(string(&mut r, color_m, "ownedMemberShortName"), None); + let alias = memberships + .iter() + .copied() + .find(|&m| r.membership_is_alias(m)) + .unwrap(); + assert_eq!( + string(&mut r, alias, "memberElementId"), + Some(r.element_id(color).to_string()) + ); + let green_m = many(&mut r, color, "ownedMembership") + .into_iter() + .find(|&m| one(&mut r, m, "ownedVariantUsage") == Some(green)) + .expect("variant membership"); + assert_eq!( + string(&mut r, green_m, "ownedMemberShortName").as_deref(), + Some("g") + ); + // Conjugation. + let pt = elem(&mut r, "P::Pt"); + let conj = one(&mut r, pt, "conjugatedPortDefinition").expect("conjugated definition"); + assert_eq!(r.element_type(conj), "ConjugatedPortDefinition"); + assert!(matches!( + r.derived(conj, "isConjugated"), + Derived::Value(DerivedValue::Bool(true)) + )); + assert!(matches!( + r.derived(pt, "isConjugated"), + Derived::Value(DerivedValue::Bool(false)) + )); + let conjugator = one(&mut r, conj, "ownedPortConjugator").expect("port conjugation"); + assert_eq!( + one(&mut r, conjugator, "conjugatedPortDefinition"), + Some(conj) + ); + // Association ends. + let link = elem(&mut r, "P::Link"); + let ends = many(&mut r, link, "connectionEnd"); + assert_eq!(ends.len(), 2); + assert_eq!(many(&mut r, link, "associationEnd"), ends); + // Individual definitions. + let earth = elem(&mut r, "P::earth"); + let earth_def = elem(&mut r, "P::Earth"); + assert_eq!(one(&mut r, earth, "individualDefinition"), Some(earth_def)); +} + +/// A kind test on a target outside the model passes: the reference is +/// reported as it is rather than dropped (the typing constraints of a +/// well-formed model make the test hold wherever it resolved). +#[test] +fn kind_tests_pass_unknowable_targets() { + let mut r = build( + "package P { + attribute m : Real; + part p : Lib::Part; + action perform_it { perform Lib::doIt; } + }", + ); + let m = elem(&mut r, "P::m"); + assert_eq!( + refs(&mut r, m, "definition"), + vec![Reference::Unresolved("Real".to_string())] + ); + assert_eq!( + refs(&mut r, m, "attributeDefinition"), + vec![Reference::Unresolved("Real".to_string())] + ); + let p = elem(&mut r, "P::p"); + assert_eq!( + refs(&mut r, p, "partDefinition"), + vec![Reference::Unresolved("Lib::Part".to_string())] + ); + let act = elem(&mut r, "P::perform_it"); + let perform = many(&mut r, act, "ownedFeature") + .into_iter() + .find(|&f| r.element_type(f) == "PerformActionUsage") + .expect("perform"); + assert_eq!( + refs(&mut r, perform, "performedAction"), + vec![Reference::Unresolved("Lib::doIt".to_string())] + ); +} + +/// Review follow-ups: an accept's trigger is not an input parameter and +/// stands in for the payload argument; a trigger invocation's +/// instantiated type and argument; constructor arguments by the type's +/// features; the positional fallback for a callee whose parameters are +/// inherited; the operator function by name table; `input` agrees with +/// `inputParameter(i)`. +#[test] +fn parameters_after_review() { + let mut r = build( + "package P { + item def Msg; + part def Peer { port p; } + part peer : Peer; + part def Car { attribute mass; } + calc def F { in n; return : Real; } + calc def G :> F; + action def A { + action a2 accept m : Msg at 1 via peer.p; + action i1 if true { action thenA; } + } + attribute c = new Car(mass = 1); + attribute g = G(3); + attribute s = 1 + 2; + alias thing for Nope::thing; + part e : Lib::Earth; + }", + ); + // The accept: the trigger is not counted, so `via` is the receiver. + let a2 = elem(&mut r, "P::A::a2"); + let receiver = one(&mut r, a2, "receiverArgument").expect("receiver"); + assert!(r.element_type(receiver).contains("Expression")); + let trigger = one(&mut r, a2, "payloadArgument").expect("trigger as payload argument"); + assert_eq!(r.element_type(trigger), "TriggerInvocationExpression"); + let inputs = many(&mut r, a2, "input"); + assert!( + inputs + .iter() + .all(|&f| r.element_type(f) != "TriggerInvocationExpression") + ); + assert_eq!(inputs.len(), 2); + // The trigger's own argument and instantiated type. + let args = many(&mut r, trigger, "argument"); + assert_eq!(args.len(), 1); + assert_eq!(r.element_type(args[0]), "LiteralInteger"); + assert_eq!(refs(&mut r, trigger, "instantiatedType"), Vec::new()); + // `input` on an if node agrees with `ifArgument`/`thenAction`. + let i1 = elem(&mut r, "P::A::i1"); + let inputs = many(&mut r, i1, "input"); + assert_eq!(inputs.len(), 2); + assert_eq!(one(&mut r, i1, "thenAction"), Some(inputs[1])); + assert_eq!(many(&mut r, i1, "parameter"), inputs); + // A constructor's arguments follow the type's features. + let c = elem(&mut r, "P::c"); + let ctor = many(&mut r, c, "ownedElement") + .into_iter() + .find(|&x| r.element_type(x) == "ConstructorExpression") + .expect("constructor"); + let args = many(&mut r, ctor, "argument"); + assert_eq!(args.len(), 1); + assert_eq!(r.element_type(args[0]), "LiteralInteger"); + // A callee whose parameters are inherited: the positional fallback. + let g = elem(&mut r, "P::g"); + let call = many(&mut r, g, "ownedElement") + .into_iter() + .find(|&x| r.element_type(x) == "InvocationExpression") + .expect("invocation"); + assert_eq!(many(&mut r, call, "argument").len(), 1); + assert_eq!( + derives("InvocationExpression", "argument"), + Derives::Passthrough + ); + // An operator's function: null without a library, external through a + // name table. + let s = elem(&mut r, "P::s"); + let plus = many(&mut r, s, "ownedElement") + .into_iter() + .find(|&x| r.element_type(x) == "OperatorExpression") + .expect("operator expression"); + assert_eq!(refs(&mut r, plus, "instantiatedType"), Vec::new()); + let plus_id = uuid::Uuid::new_v4(); + let at_id = uuid::Uuid::new_v4(); + let mut names = std::collections::HashMap::new(); + names.insert( + plus_id.to_string(), + vec!["DataFunctions".to_string(), "+".to_string()], + ); + names.insert( + at_id.to_string(), + vec!["Triggers".to_string(), "TriggerAt".to_string()], + ); + r.set_library_names(&names); + assert_eq!( + refs(&mut r, plus, "instantiatedType"), + vec![Reference::External(plus_id)] + ); + assert_eq!( + refs(&mut r, trigger, "instantiatedType"), + vec![Reference::External(at_id)] + ); + // An unresolved member's id is the dangling id the wire spells; an + // individual definition outside the model cannot pass its property + // test. + let p = elem(&mut r, "P"); + let alias = many(&mut r, p, "ownedMembership") + .into_iter() + .find(|&m| r.membership_is_alias(m)) + .expect("alias"); + let expected = uuid::Uuid::new_v5( + &uuid::Uuid::NAMESPACE_OID, + "unresolved:Nope::thing".as_bytes(), + ) + .to_string(); + assert_eq!(string(&mut r, alias, "memberElementId"), Some(expected)); + let e = elem(&mut r, "P::e"); + assert_eq!(refs(&mut r, e, "individualDefinition"), Vec::new()); + // The owned/derived split. + assert_eq!(derives("Specialization", "source"), Derives::NotDeclared); + assert!(sysmlv2_parser::json::is_owned_property( + "Specialization", + "source" + )); + assert!(!sysmlv2_parser::json::is_owned_property( + "TransitionUsage", + "source" + )); +} + +/// Chains through the transition, verification and rendering references. +#[test] +fn chained_references_in_behavior_and_cases() { + let mut r = build( + "package P { + requirement def R; + part sys { requirement r2 : R; } + state def M { + state s1; + state s2 { state inner; } + transition t3 first s1 then s2.inner; + transition t4 first s2.inner then s1; + } + verification def V { objective { verify sys.r2; verify sys.r2; } } + rendering def Tree; + part views { rendering asTree : Tree; } + view def VD { render views.asTree; } + }", + ); + let inner = elem(&mut r, "P::M::s2::inner"); + let s1 = elem(&mut r, "P::M::s1"); + let t3 = elem(&mut r, "P::M::t3"); + assert_eq!(one(&mut r, t3, "source"), Some(s1)); + assert_eq!(one(&mut r, t3, "target"), Some(inner)); + let t4 = elem(&mut r, "P::M::t4"); + assert_eq!(one(&mut r, t4, "source"), Some(inner)); + assert_eq!(one(&mut r, t4, "target"), Some(s1)); + let r2 = elem(&mut r, "P::sys::r2"); + let v = elem(&mut r, "P::V"); + assert_eq!(many(&mut r, v, "verifiedRequirement"), vec![r2]); + let vd = elem(&mut r, "P::VD"); + let as_tree = elem(&mut r, "P::views::asTree"); + assert_eq!(one(&mut r, vd, "viewRendering"), Some(as_tree)); +} + +// ---- M33g: type operations, association types, featuring, evaluability ---- + +/// Unioning, intersecting and differencing types and their relationship +/// ends; an association's related, source and target types. +#[test] +fn type_operations_and_association_types() { + let mut model = Model::new(); + model.add_source( + "m.kerml", + "package P { + classifier A; classifier B; classifier C; + classifier U unions A, B; + classifier I intersects A, B; + classifier D differences A, B; + assoc L { end feature a : A; end feature b : B; end feature c : C; } + }", + ); + assert!( + !model.has_errors(), + "{:?}", + model + .units() + .iter() + .flat_map(|u| u.diagnostics.iter()) + .collect::>() + ); + let mut r = ResolvedModel::build(&model); + let a = elem(&mut r, "P::A"); + let b = elem(&mut r, "P::B"); + let c = elem(&mut r, "P::C"); + let u = elem(&mut r, "P::U"); + assert_eq!(many(&mut r, u, "unioningType"), vec![a, b]); + assert_eq!(many(&mut r, u, "intersectingType"), Vec::new()); + let unionings = many(&mut r, u, "ownedUnioning"); + assert_eq!(unionings.len(), 2); + assert_eq!(one(&mut r, unionings[0], "typeUnioned"), Some(u)); + let i = elem(&mut r, "P::I"); + assert_eq!(many(&mut r, i, "intersectingType"), vec![a, b]); + let d = elem(&mut r, "P::D"); + assert_eq!(many(&mut r, d, "differencingType"), vec![a, b]); + let l = elem(&mut r, "P::L"); + assert_eq!(many(&mut r, l, "relatedType"), vec![a, b, c]); + assert_eq!(one(&mut r, l, "sourceType"), Some(a)); + assert_eq!(many(&mut r, l, "targetType"), vec![b, c]); + assert_eq!(derives("Association", "relatedType"), Derives::Passthrough); + assert_eq!(derives("Classifier", "unioningType"), Derives::Exact); +} + +/// A connector's default featuring type: the innermost type featuring +/// every related feature, through the owning types of the chains' first +/// links. +#[test] +fn default_featuring_type() { + let mut r = build( + "package P { + part def Wheel { port hub; } + part def Axle { port end_; } + part def Car { + part w : Wheel; + part ax : Axle; + connection c1 connect w to ax; + connection c2 connect w.hub to ax.end_; + part inner { part x; part y; connection c3 connect x to y; } + } + part car : Car; + connection top connect car.w to car.ax; + }", + ); + let car_def = elem(&mut r, "P::Car"); + let c1 = elem(&mut r, "P::Car::c1"); + assert_eq!(one(&mut r, c1, "defaultFeaturingType"), Some(car_def)); + let c2 = elem(&mut r, "P::Car::c2"); + assert_eq!(one(&mut r, c2, "defaultFeaturingType"), Some(car_def)); + let inner = elem(&mut r, "P::Car::inner"); + let c3 = elem(&mut r, "P::Car::inner::c3"); + assert_eq!(one(&mut r, c3, "defaultFeaturingType"), Some(inner)); + // Related features at the top level are featured by nothing in the + // model: no common featuring type. + let top = elem(&mut r, "P::top"); + assert_eq!(one(&mut r, top, "defaultFeaturingType"), None); + assert_eq!( + derives("ConnectionUsage", "defaultFeaturingType"), + Derives::Passthrough + ); +} + +/// Model-level evaluability: literals and metadata access are evaluable; +/// a reference to an unfeatured feature is; one to a featured feature is +/// not; an invocation is only when its function is a library function. +#[test] +fn model_level_evaluability() { + let mut r = build( + "package P { + attribute a; + attribute b = a; + attribute lit = 1; + part def T { attribute q; attribute rq = q; } + calc def F { in n; return : Real; } + attribute call = F(1); + attribute op = 1 + 2; + attribute chain = a + b; + }", + ); + let evaluable = |r: &mut ResolvedModel, owner: &str| -> bool { + let e = elem(r, owner); + let value = r + .owned_relationships(e) + .into_iter() + .find(|&x| r.element_type(x) == "FeatureValue") + .and_then(|fv| one(r, fv, "value")) + .expect("value"); + matches!(r.derived(value, "isModelLevelEvaluable"), Derived::Value(DerivedValue::Bool(b)) if b) + }; + assert!(evaluable(&mut r, "P::lit")); + assert!(evaluable(&mut r, "P::b")); + assert!(!evaluable(&mut r, "P::T::rq")); + assert!(!evaluable(&mut r, "P::call")); + // Without a library the operator's function is unknown: not evaluable. + assert!(!evaluable(&mut r, "P::op")); + // With a name table naming the library function, it is. + let plus_id = uuid::Uuid::new_v4(); + let mut names = std::collections::HashMap::new(); + names.insert( + plus_id.to_string(), + vec!["DataFunctions".to_string(), "+".to_string()], + ); + r.set_library_names(&names); + assert!(evaluable(&mut r, "P::op")); + assert!(evaluable(&mut r, "P::chain")); + assert_eq!( + derives("OperatorExpression", "isModelLevelEvaluable"), + Derives::Passthrough + ); +} + +// ---- M33h: the closures and the inheritance-aware switch ---- + +/// The four closure names answer through the resolver's walks whatever +/// the policy; under the closure policy the inheritance-aware families +/// switch to their specification definition. +#[test] +fn closures_and_the_inheritance_aware_switch() { + use sysmlv2_parser::json::{ClosurePolicy, derives_under}; + let mut r = build( + "package P { + part def V { attribute mass; port p; } + part def W :> V { attribute extra; } + package Q { part q; } + package R { import Q::*; } + package S { private import Q::*; } + part def T { import Q::*; attribute own; } + part def U :> T; + }", + ); + let w = elem(&mut r, "P::W"); + let mass = elem(&mut r, "P::V::mass"); + let p = elem(&mut r, "P::V::p"); + let extra = elem(&mut r, "P::W::extra"); + // Passthrough: the families answer the owned side; the closures answer. + assert_eq!(many(&mut r, w, "feature"), vec![extra]); + assert_eq!(many(&mut r, w, "inheritedFeature"), vec![mass, p]); + let inherited = many(&mut r, w, "inheritedMembership"); + assert_eq!(inherited.len(), 2); + assert!( + inherited + .iter() + .all(|&m| r.element_type(m) == "FeatureMembership") + ); + assert_eq!( + many(&mut r, mass, "featuringType"), + vec![elem(&mut r, "P::V")] + ); + let rpkg = elem(&mut r, "P::R"); + let q = elem(&mut r, "P::Q::q"); + let imported = many(&mut r, rpkg, "importedMembership"); + assert_eq!(imported.len(), 1); + assert_eq!(one(&mut r, imported[0], "ownedMemberElement"), Some(q)); + assert_eq!(many(&mut r, rpkg, "membership"), Vec::new()); + assert_eq!(derives("PartDefinition", "feature"), Derives::Passthrough); + // A private import imports for its owner (it is the re-export through + // heritage that private excludes). + let spkg = elem(&mut r, "P::S"); + assert_eq!(many(&mut r, spkg, "importedMembership"), imported); + // A feature arriving through an import inside a type is a member, + // not a feature: `feature` selects by membership kind. + let t = elem(&mut r, "P::T"); + let u = elem(&mut r, "P::U"); + let own = elem(&mut r, "P::T::own"); + // The closure policy. + r.set_closure_policy(ClosurePolicy::Closure { + include_implied: false, + }); + assert_eq!(many(&mut r, w, "feature"), vec![extra, mass, p]); + let memberships = many(&mut r, w, "featureMembership"); + assert_eq!(memberships.len(), 3); + assert_eq!(many(&mut r, w, "ownedFeature"), vec![extra]); + assert_eq!(many(&mut r, rpkg, "membership"), imported); + assert_eq!(refs(&mut r, rpkg, "member"), vec![Reference::Element(q)]); + assert_eq!(many(&mut r, t, "feature"), vec![own]); + assert!(refs(&mut r, t, "member").contains(&Reference::Element(q))); + assert_eq!(many(&mut r, u, "feature"), vec![own]); + assert_eq!(many(&mut r, u, "inheritedFeature"), vec![own]); + // A Type's membership unions its imported and inherited memberships. + let u_memberships = many(&mut r, u, "membership"); + assert!(u_memberships.contains(&imported[0])); + assert!(refs(&mut r, u, "member").contains(&Reference::Element(own))); + // The written-heritage tier stays passthrough; the closure with the + // implied heritage is the specification's value, except for the three + // approximations. + let written = ClosurePolicy::Closure { + include_implied: false, + }; + let full = ClosurePolicy::Closure { + include_implied: true, + }; + assert_eq!( + derives_under("PartDefinition", "feature", written), + Derives::Passthrough + ); + assert_eq!( + derives_under("PartDefinition", "feature", full), + Derives::Exact + ); + assert_eq!( + derives_under("PartDefinition", "inheritedMembership", full), + Derives::Exact + ); + assert_eq!( + derives_under("OperatorExpression", "isModelLevelEvaluable", full), + Derives::Passthrough + ); + // Without a library the implied heritage adds nothing. + r.set_closure_policy(full); + assert_eq!(many(&mut r, w, "feature"), vec![extra, mass, p]); + r.set_closure_policy(written); + assert!(!r.closure_truncated(w)); + r.set_closure_policy(ClosurePolicy::Passthrough); + assert_eq!(many(&mut r, w, "feature"), vec![extra]); +} + +/// A heritage deeper than the resolver's budget is reported, never +/// presented as a complete closure. +#[test] +fn a_deep_heritage_reports_truncation() { + use sysmlv2_parser::json::ClosurePolicy; + let mut src = String::from("package P { part def D0 { attribute a0; }"); + for i in 1..=26 { + src.push_str(&format!( + " part def D{i} :> D{} {{ attribute a{i}; }}", + i - 1 + )); + } + src.push('}'); + let mut r = build(&src); + let deep = elem(&mut r, "P::D26"); + r.set_closure_policy(ClosurePolicy::Closure { + include_implied: false, + }); + assert!(r.closure_truncated(deep)); + let shallow = elem(&mut r, "P::D3"); + assert!(!r.closure_truncated(shallow)); + assert_eq!(many(&mut r, shallow, "feature").len(), 4); + // The import walk has the same budget. + let mut src = String::from("package P { package I0 { part x; }"); + for i in 1..=26 { + src.push_str(&format!(" package I{i} {{ public import I{}::*; }}", i - 1)); + } + src.push('}'); + let mut r = build(&src); + let deep = elem(&mut r, "P::I26"); + r.set_closure_policy(ClosurePolicy::Closure { + include_implied: false, + }); + assert!(r.closure_truncated(deep)); + let shallow = elem(&mut r, "P::I3"); + assert!(!r.closure_truncated(shallow)); +} + +/// Review follow-ups for the evaluability walk and the association types. +#[test] +fn evaluability_after_review() { + let mut r = build( + "package P { + part def Car { attribute mass; } + attribute c = new Car(mass = 1); + attribute c2 = new Car(mass = F(1)); + calc def F { in n; return : Real = n; } + calc def G { in n; n + 1 } + constraint def K { true } + part p { calc cu : F; constraint k : K; attribute kv = 1; } + attribute a; + attribute b = a; + attribute w = 1 + b; + attribute call = F(1); + attribute z = 1 + call; + connection def L { end part x : Car; end part y : Car; } + }", + ); + let value_of = |r: &mut ResolvedModel, owner: &str| -> ElementRef { + let e = elem(r, owner); + r.owned_relationships(e) + .into_iter() + .find(|&x| r.element_type(x) == "FeatureValue") + .and_then(|fv| one(r, fv, "value")) + .expect("value") + }; + let is_evaluable = |r: &mut ResolvedModel, e: ElementRef| -> bool { + matches!(r.derived(e, "isModelLevelEvaluable"), Derived::Value(DerivedValue::Bool(b)) if b) + }; + // A constructor with arguments is evaluable when they are. + let ctor = value_of(&mut r, "P::c"); + assert_eq!(r.element_type(ctor), "ConstructorExpression"); + assert!(is_evaluable(&mut r, ctor)); + let ctor2 = value_of(&mut r, "P::c2"); + assert!(!is_evaluable(&mut r, ctor2)); + // Calculation and constraint usages never are. + let cu = elem(&mut r, "P::p::cu"); + assert!(!is_evaluable(&mut r, cu)); + let k = elem(&mut r, "P::p::k"); + assert!(!is_evaluable(&mut r, k)); + // A user function is not a model-level evaluable function. + let f = elem(&mut r, "P::F"); + assert!(!is_evaluable(&mut r, f)); + let g = elem(&mut r, "P::G"); + assert!(!is_evaluable(&mut r, g)); + // Through the valuation branch, with the library function named. + let plus_id = uuid::Uuid::new_v4(); + let mut names = std::collections::HashMap::new(); + names.insert( + plus_id.to_string(), + vec!["DataFunctions".to_string(), "+".to_string()], + ); + r.set_library_names(&names); + let w = value_of(&mut r, "P::w"); + assert!(is_evaluable(&mut r, w)); + let z = value_of(&mut r, "P::z"); + assert!(!is_evaluable(&mut r, z)); + // A binary association over one type relates it twice. + let l = elem(&mut r, "P::L"); + let car = elem(&mut r, "P::Car"); + assert_eq!(many(&mut r, l, "relatedType"), vec![car, car]); + assert_eq!(one(&mut r, l, "sourceType"), Some(car)); + assert_eq!(many(&mut r, l, "targetType"), vec![car]); +} + +/// `computable_names(metaclass)` is `computed_names()` filtered by the +/// static gate, in the same order, and every name it lists is answered +/// with a value on an element of that metaclass — the memoized plan the +/// full-form emitter iterates agrees with the static answer per name. +#[test] +fn computable_names_are_the_computed_names_the_gate_admits() { + let mut r = build( + "package P { + part def Car { part engine; attribute mass; } + part car : Car { part :>> engine; } + calc def Area { in x; return : Real = x; } + connection def Link { end a; end b; } + }", + ); + let mut targets: Vec = [ + "P", + "P::Car", + "P::car", + "P::car::engine", + "P::Area", + "P::Link", + ] + .into_iter() + .map(|qn| elem(&mut r, qn)) + .collect(); + // A membership metaclass reaches the member-side arm through the plan. + let engine = elem(&mut r, "P::car::engine"); + targets.push(one(&mut r, engine, "owningMembership").expect("owning membership")); + for e in targets { + let ty = r.element_type(e); + let expected: Vec<&str> = computed_names() + .filter(|n| matches!(derives(ty, n), Derives::Passthrough | Derives::Exact)) + .collect(); + // A runtime spelling of the metaclass reaches the same plan. + let spelled: String = ty.to_owned(); + let plan = r.computable_names(spelled.as_str()); + assert_eq!(plan.as_ref(), expected.as_slice(), "{ty}"); + for name in plan.iter() { + assert!( + matches!(r.derived(e, name), Derived::Value(_)), + "{ty}::{name} is planned but not answered" + ); + } + // Names outside the plan are refused with the static answer. + for name in computed_names().filter(|n| !plan.contains(n)) { + let refusal = match derives(ty, name) { + Derives::NotDeclared => Derived::NotDeclared, + Derives::NotComputed => Derived::NotComputed, + admitted => panic!("{ty}::{name} is admitted ({admitted:?}) but not planned"), + }; + assert_eq!(r.derived(e, name), refusal, "{ty}::{name}"); + } + // A name outside the derived catalog is declared nowhere. + assert_eq!(r.derived(e, "noSuchProperty"), Derived::NotDeclared, "{ty}"); + // The plan is the passthrough gate's: a closure policy changes + // fidelity, never which names are answered. + r.set_closure_policy(ClosurePolicy::Closure { + include_implied: true, + }); + assert_eq!( + r.computable_names(ty).as_ref(), + expected.as_slice(), + "{ty} under closure" + ); + r.set_closure_policy(ClosurePolicy::Passthrough); + } + // A metaclass outside the catalog has no computable names. + assert!(r.computable_names("NoSuchMetaclass").is_empty()); +} diff --git a/crates/sysmlv2-parser/tests/derived_correspondence.rs b/crates/sysmlv2-parser/tests/derived_correspondence.rs new file mode 100644 index 0000000..283dd8f --- /dev/null +++ b/crates/sysmlv2-parser/tests/derived_correspondence.rs @@ -0,0 +1,81 @@ +//! The committed correspondence table (`spec-refs/derived-correspondence.json`, +//! written by `cargo run --example derived_correspondence`) is fresh: its +//! rows are the property catalog's, and every derived row's fidelities +//! are what `derives`/`derives_under` answer today. A change to the +//! layer's tables that is not followed by a regeneration fails here. + +#![cfg(feature = "json")] + +use std::collections::BTreeSet; +use sysmlv2_parser::json::{ + ClosurePolicy, Derives, PropertyShape, derives, derives_under, property_catalog, +}; + +fn fidelity(f: Derives) -> &'static str { + match f { + Derives::NotDeclared => "not-declared", + Derives::NotComputed => "not-computed", + Derives::Passthrough => "passthrough", + Derives::Exact => "exact", + } +} + +#[test] +fn committed_correspondence_table_is_fresh() { + let path = sysmlv2_testkit::workspace_root().join("spec-refs/derived-correspondence.json"); + let table: serde_json::Value = + serde_json::from_str(&std::fs::read_to_string(&path).expect("the committed table")) + .unwrap(); + let rows = table["rows"].as_array().unwrap(); + let committed: BTreeSet<(String, String, bool, String)> = rows + .iter() + .map(|r| { + ( + r["metaclass"].as_str().unwrap().to_string(), + r["property"].as_str().unwrap().to_string(), + r["owned"].as_bool().unwrap(), + r["shape"].as_str().unwrap().to_string(), + ) + }) + .collect(); + let current: BTreeSet<(String, String, bool, String)> = property_catalog() + .map(|e| { + let shape = match e.shape { + PropertyShape::Array => "array", + PropertyShape::Boolean => "boolean", + PropertyShape::Nullable => "nullable", + PropertyShape::Scalar => "scalar", + PropertyShape::Enumeration => "enumeration", + PropertyShape::RequiredReference => "required-reference", + _ => "other", + }; + ( + e.metaclass.to_string(), + e.property.to_string(), + e.owned, + shape.to_string(), + ) + }) + .collect(); + assert_eq!( + committed, current, + "the catalog rows changed: rerun `cargo run --example derived_correspondence`" + ); + let closure = ClosurePolicy::Closure { + include_implied: true, + }; + for r in rows.iter().filter(|r| r["owned"] == false) { + let m = r["metaclass"].as_str().unwrap(); + let p = r["property"].as_str().unwrap(); + assert_eq!( + r["fidelity"].as_str(), + Some(fidelity(derives(m, p))), + "{m}.{p}: fidelity changed — rerun `cargo run --example derived_correspondence`" + ); + assert_eq!( + r["fidelityUnderClosure"].as_str(), + Some(fidelity(derives_under(m, p, closure))), + "{m}.{p}: fidelity under the closure policy changed" + ); + } +} diff --git a/crates/sysmlv2-parser/tests/derived_parity.rs b/crates/sysmlv2-parser/tests/derived_parity.rs new file mode 100644 index 0000000..2588088 --- /dev/null +++ b/crates/sysmlv2-parser/tests/derived_parity.rs @@ -0,0 +1,329 @@ +//! Parity between the derived-property read API and the full-form +//! emitter over the standard corpus: for every user element and every +//! name the read API computes, the API's answer must equal the value the +//! emitter writes for the same `@id`. +//! +//! The emitter now *projects* the layer for most computed names, so for +//! those the gate compares the layer with itself and the corpus baseline +//! (`full_baseline.rs`) is the real guard. It still compares independently +//! wherever the emitter keeps its own derivation — every unprojected +//! element (implied relationships, a lift failure, an id collision) and +//! the names the emitter deliberately retains (`name`, `qualifiedName`, +//! `featureTarget`, `annotatedElement` and its narrowings, `shortName`). +//! `ALLOWED` records the divergences those comparisons expose; a +//! divergence not listed there fails the gate with a per-(metaclass, +//! name) count and one example. + +#![cfg(feature = "json")] + +use serde_json::Value; +use std::collections::{BTreeMap, HashMap}; +use std::fs; +use sysmlv2_parser::full::{EmissionPolicy, UnresolvedReferencePolicy, resolved_to_full_json}; +use sysmlv2_parser::json::{ + CLOSURE_NAMES, ClosurePolicy, Derived, DerivedValue, Reference, ResolvedModel, computed_names, + is_owned_property, +}; +use sysmlv2_parser::model::Model; + +/// Names on which the read API and the emitter are known to differ, with +/// the justification. An entry excuses a mismatch only when its predicate +/// over `(element, metaclass, api value, emitter value)` holds, so each +/// excuse is as narrow as the divergence it names. +type Excuse = fn(&Value, &str, &Value, &Value) -> bool; +const ALLOWED: &[(&str, &str, Excuse)] = &[ + // A required reference the layer cannot fill — an enumeration usage + // whose definition did not resolve, an expression with no return + // parameter, a transition whose source is no action, a reference + // whose target is not of the required kind: the read API answers + // null, the full form the catalog's self-reference placeholder. Only + // the names whose specification can yield null are excused, so a + // layer answering null where the element itself is the value + // (`performedAction` of an unreferenced perform) is still caught. + ( + "*", + "required-reference placeholder: null in the API, self-reference on the wire", + |el, _, api, emitter| api.is_null() && emitter.get("@id") == el.get("@id"), + ), +]; + +/// The names the placeholder excuse applies to. +const MAY_BE_NULL: &[&str] = &[ + "assertedConstraint", + "bodyAction", + "enumerationDefinition", + "eventOccurrence", + "exhibitedState", + "ifArgument", + "instantiatedType", + "loopVariable", + "payloadArgument", + "performedAction", + "referencedConcern", + "referencedConstraint", + "referencedElement", + "referencedRendering", + "referent", + "result", + "satisfiedRequirement", + "satisfyingFeature", + "seqArgument", + "source", + "subjectParameter", + "succession", + "target", + "thenAction", + "useCaseIncluded", + "verifiedRequirement", + "whileArgument", +]; + +/// A reference as the wire spells it: an unresolved spelling becomes the +/// emitter's deterministic dangling id. +fn reference(r: &Reference, id: &dyn Fn(sysmlv2_parser::json::ElementRef) -> Value) -> Value { + let wrap = |s: String| { + Value::Object( + [("@id".to_string(), Value::String(s))] + .into_iter() + .collect(), + ) + }; + match r { + Reference::Element(e) => id(*e), + Reference::External(u) => wrap(u.to_string()), + Reference::Unresolved(s) => wrap( + uuid::Uuid::new_v5( + &uuid::Uuid::NAMESPACE_OID, + format!("unresolved:{s}").as_bytes(), + ) + .to_string(), + ), + other => panic!("unhandled reference {other:?}"), + } +} + +fn to_json(r: &ResolvedModel, v: &DerivedValue) -> Value { + let id = |e| { + Value::Object( + [( + "@id".to_string(), + Value::String(r.element_id(e).to_string()), + )] + .into_iter() + .collect(), + ) + }; + match v { + DerivedValue::Null => Value::Null, + DerivedValue::Bool(b) => Value::Bool(*b), + DerivedValue::Str(s) => Value::String(s.clone()), + DerivedValue::Element(e) => id(*e), + DerivedValue::Elements(es) => Value::Array(es.iter().map(|&e| id(e)).collect()), + DerivedValue::Reference(r) => reference(r, &id), + DerivedValue::References(rs) => { + Value::Array(rs.iter().map(|r| reference(r, &id)).collect()) + } + DerivedValue::Strings(ss) => { + Value::Array(ss.iter().map(|s| Value::String(s.clone())).collect()) + } + // `DerivedValue` is non-exhaustive: a new variant must fail the + // gate loudly rather than compare as something else. + other => panic!("unhandled derived value {other:?}"), + } +} + +#[test] +fn corpus_read_api_matches_full_form() { + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return; + } + let files = sysmlv2_testkit::user_files(); + if files.is_empty() { + eprintln!("skipping: corpus model files not present"); + return; + } + let mut model = Model::new(); + model + .load_library_dir(&root.join("sysml.library")) + .expect("library loads"); + for path in files { + let src = fs::read_to_string(&path).unwrap(); + // Unit names salt the root ids: two corpus files share a basename, + // so name units by their corpus-relative path to keep ids unique. + let name = path + .strip_prefix(&root) + .unwrap_or(&path) + .to_string_lossy() + .into_owned(); + model.add_source(name, &src); + } + // Without unresolved-reference recovery: the recovery annotations are + // an emission policy, not model content, and would inflate + // `ownedElement` on the referencing elements. + let t0 = std::time::Instant::now(); + let full = sysmlv2_parser::full::model_to_full_json_with(&model, false); + // The compact form: a key the full form writes that the compact form + // already carries is an owned property, never a derived one. + let compact = sysmlv2_parser::json::model_to_compact_json(&model); + let owned_keys: HashMap<&str, &Value> = compact + .as_array() + .unwrap() + .iter() + .map(|el| (el["@id"].as_str().unwrap(), el)) + .collect(); + let emitted = t0.elapsed(); + let mut by_id: HashMap<&str, &Value> = HashMap::new(); + let mut duplicate_ids = 0usize; + for el in full.as_array().unwrap() { + if by_id.insert(el["@id"].as_str().unwrap(), el).is_some() { + duplicate_ids += 1; + } + } + let t0 = std::time::Instant::now(); + let mut r = ResolvedModel::build(&model); + let built = t0.elapsed(); + // The four closure names are empty at the passthrough level by + // design; the read API answers them (over the written heritage + // under its default policy), so they are compared against an + // emission under the closure policy. + let closed = resolved_to_full_json( + &mut r, + &model, + EmissionPolicy { + unresolved: UnresolvedReferencePolicy::LegacyDanglingId, + closures: ClosurePolicy::Closure { + include_implied: false, + }, + }, + ) + .expect("the corpus emits under the closure policy"); + let closed_by_id: HashMap<&str, &Value> = closed + .as_array() + .unwrap() + .iter() + .map(|el| (el["@id"].as_str().unwrap(), el)) + .collect(); + let names: Vec<&str> = computed_names().collect(); + let type_of = |v: &Value| -> String { + v.get("@id") + .and_then(Value::as_str) + .and_then(|id| by_id.get(id)) + .map(|el| el["@type"].as_str().unwrap_or("?").to_string()) + .unwrap_or_else(|| "?".into()) + }; + + // (metaclass, name) -> (mismatches, compared, first example) + let mut report: BTreeMap<(String, String), (usize, usize, String)> = BTreeMap::new(); + let mut missing_elements = 0usize; + let mut skipped_duplicates = 0usize; + let mut per_name: BTreeMap<&str, std::time::Duration> = BTreeMap::new(); + let elements: Vec<_> = r.user_elements().collect(); + // Ids that occur more than once in the payload cannot be matched to a + // model element (an id-scheme collision between same-named units). + let mut seen_ids: HashMap = HashMap::new(); + for e in &elements { + *seen_ids.entry(r.element_id(*e).to_string()).or_default() += 1; + } + for e in elements { + let id = r.element_id(e).to_string(); + if seen_ids[&id] > 1 { + skipped_duplicates += 1; + continue; + } + let Some(el) = by_id.get(id.as_str()) else { + missing_elements += 1; + continue; + }; + let ty = r.element_type(e).to_string(); + for &name in &names { + let el = if CLOSURE_NAMES.contains(&name) { + closed_by_id.get(id.as_str()).copied().unwrap_or(el) + } else { + *el + }; + let t0 = std::time::Instant::now(); + let d = r.derived(e, name); + *per_name.entry(name).or_default() += t0.elapsed(); + let entry = + report + .entry((ty.clone(), name.to_string())) + .or_insert((0, 0, String::new())); + let Derived::Value(v) = d else { + // The emitter writing a key the read API calls undeclared + // is a catalog / derived-name table regression — unless the + // compact form spells the property, or it is one of the + // three owned properties the emitter completes from what the + // compact form spells (a relationship's `source`/`target` + // from its ends, a ConjugatedPortTyping's + // `conjugatedPortDefinition` from its `type`). + let owned_here = owned_keys + .get(id.as_str()) + .is_some_and(|c| c.get(name).is_some()) + || (matches!(name, "source" | "target" | "conjugatedPortDefinition") + && is_owned_property(&ty, name)); + if el.get(name).is_some() && !owned_here && matches!(d, Derived::NotDeclared) { + entry.1 += 1; + entry.0 += 1; + if entry.2.is_empty() { + entry.2 = format!("{id}: api=NotDeclared, emitter writes the key"); + } + } + continue; + }; + let got = to_json(&r, &v); + entry.1 += 1; + let Some(expected) = el.get(name).cloned() else { + // A value the emitter never writes cannot silently equal + // an API `Null`. + entry.0 += 1; + if entry.2.is_empty() { + entry.2 = format!("{id}: api={got}, emitter does not write the key"); + } + continue; + }; + if got != expected { + if ALLOWED.iter().any(|(n, _, pred)| { + (*n == name || (*n == "*" && MAY_BE_NULL.contains(&name))) + && pred(el, &ty, &got, &expected) + }) { + continue; + } + entry.0 += 1; + if entry.2.is_empty() { + entry.2 = format!( + "{id}: api={got} emitter={expected} (emitter value type: {})", + type_of(&expected) + ); + } + } + } + } + assert_eq!(missing_elements, 0, "every user element is emitted"); + eprintln!( + "emit {emitted:?}, build {built:?}; {duplicate_ids} duplicate payload ids, {skipped_duplicates} model elements skipped for them" + ); + let mut slow: Vec<(&str, std::time::Duration)> = per_name.into_iter().collect(); + slow.sort_by_key(|(_, d)| std::cmp::Reverse(*d)); + eprintln!( + "read-API time by name (top 6): {:?}", + slow.iter().take(6).collect::>() + ); + let bad: Vec = report + .iter() + .filter(|(_, (m, _, _))| *m > 0) + .map(|((ty, name), (m, n, ex))| format!(" {ty}.{name}: {m}/{n} differ, e.g. {ex}")) + .collect(); + let compared: usize = report.values().map(|(_, n, _)| n).sum(); + eprintln!( + "compared {compared} (element, name) values over {} (metaclass, name) pairs", + report.len() + ); + assert!( + bad.is_empty(), + "read API and full-form emitter disagree on {} (metaclass, name) pairs:\n{}", + bad.len(), + bad.join("\n") + ); +} diff --git a/crates/sysmlv2-parser/tests/distinguishability.rs b/crates/sysmlv2-parser/tests/distinguishability.rs new file mode 100644 index 0000000..47aa5ef --- /dev/null +++ b/crates/sysmlv2-parser/tests/distinguishability.rs @@ -0,0 +1,415 @@ +//! `validateNamespaceDistinguishibility` over inherited members: an owned +//! member reusing an inherited name without redefining it, and a type +//! inheriting one name from two places. Every rejection has a legal +//! neighbor, and the implied redefinitions the specification grants +//! (parameters, ends, objectives, metadata body usages) stay silent. +use sysmlv2_parser::{check, json::ResolvedModel, model::Model}; + +const RULE: &str = "[validateNamespaceDistinguishibility]"; + +fn findings(src: &str) -> Vec { + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + let unit = model.add_source("d.sysml", src); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + let mut r = ResolvedModel::build(&model); + check::validate_semantics_with(&mut r, &model) + .into_iter() + .map(|(_, d)| d.message) + .filter(|m| m.contains(RULE)) + .collect() +} + +fn kerml_findings(src: &str) -> Vec { + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + let unit = model.add_source("d.kerml", src); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + let mut r = ResolvedModel::build(&model); + check::validate_semantics_with(&mut r, &model) + .into_iter() + .map(|(_, d)| d.message) + .filter(|m| m.contains(RULE)) + .collect() +} + +#[test] +fn owned_usage_reusing_an_inherited_name_is_reported() { + let out = findings( + "package P { + private import ScalarValues::*; + attribute def SwitchStatus { attribute downlinkPort : Real; } + attribute def M1SwitchStatus :> SwitchStatus { attribute downlinkPort : Real[6]; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0] + .starts_with("`downlinkPort` duplicates the inherited member name from `SwitchStatus`"), + "{out:?}" + ); +} + +#[test] +fn redefinition_and_subsetting_are_the_legal_spellings() { + for spelling in [ + "attribute :>> downlinkPort : Real[6];", + "attribute downlinkPort :>> downlinkPort : Real[6];", + "attribute downlinkPort :> downlinkPort : Real[6];", + ] { + let out = findings(&format!( + "package P {{ + private import ScalarValues::*; + attribute def SwitchStatus {{ attribute downlinkPort : Real; }} + attribute def M1SwitchStatus :> SwitchStatus {{ {spelling} }} + }}" + )); + assert!(out.is_empty(), "{spelling}: {out:?}"); + } +} + +#[test] +fn short_names_share_the_name_space() { + let out = findings( + "package P { + private import ScalarValues::*; + attribute def SwitchStatus { attribute downlinkPort : Real; } + attribute def M1SwitchStatus :> SwitchStatus { attribute port6 : Real[6]; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!(out[0].contains("`downlinkPort` duplicates"), "{out:?}"); +} + +#[test] +fn a_usage_typed_by_the_offending_definition_inherits_both() { + let out = findings( + "package P { + private import ScalarValues::*; + attribute def SwitchStatus { attribute downlinkPort : Real; } + attribute def M1SwitchStatus :> SwitchStatus { attribute downlinkPort : Real[6]; } + attribute def LanStatus { attribute m1 : M1SwitchStatus; } + }", + ); + assert_eq!(out.len(), 2, "{out:?}"); + assert!( + out.iter().any(|m| m.starts_with( + "`downlinkPort` is inherited from both `M1SwitchStatus` and `SwitchStatus`" + )), + "{out:?}" + ); +} + +#[test] +fn distinct_metaclasses_are_distinguishable() { + // An item usage and an attribute usage neither conform to the other + // (KerML `Membership::isDistinguishableFrom`). + let out = findings( + "package P { + private import ScalarValues::*; + part def A { attribute x : Real; } + part def B :> A { item x; } + }", + ); + assert!(out.is_empty(), "{out:?}"); +} + +#[test] +fn kerml_features_collide_too() { + let out = kerml_findings( + "package P { + classifier A { feature x; } + classifier B specializes A { feature x; } + classifier C specializes A { feature redefines x; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0].contains("`x` duplicates the inherited member name from `A`"), + "{out:?}" + ); +} + +#[test] +fn library_heritage_alone_is_silent() { + let out = findings( + "package P { + private import ScalarValues::*; + part def Vehicle { part engine : Engine; attribute mass : Real; } + part def Engine; + part def Car :> Vehicle { part :>> engine; attribute :>> mass = 1200.0; } + part car : Car; + action def Drive { in speed : Real; out done : Boolean; } + action def DriveFast :> Drive { in speed : Real; out done : Boolean; } + state def Running { entry action init; do action run; exit action stop; } + calc def Area { in w : Real; in h : Real; return area : Real = w * h; } + calc def SquareArea :> Area { in w : Real; in h : Real; return area : Real = w * w; } + }", + ); + assert!(out.is_empty(), "{out:?}"); +} + +#[test] +fn implied_redefinitions_are_not_collisions() { + // Interface ends reuse `BinaryInterface`'s end names positionally, a + // case objective redefines `Case::obj`, and a metadata body usage is + // an owned redefinition by the grammar. + let out = findings( + "package P { + private import ScalarValues::*; + private import ModelingMetadata::*; + port def StagingPort; + interface def StagingInterface { + end source : StagingPort; + end target : ~StagingPort; + } + part def Stage { port p : StagingPort; port q : ~StagingPort; } + part def Rocket { + part a : Stage; + part b : Stage; + interface : StagingInterface connect a.p to b.q; + @Rationale { text = \"staged for mass\"; } + } + requirement def Objective; + analysis def Study { + subject s : Rocket; + objective obj : Objective; + } + }", + ); + assert!(out.is_empty(), "{out:?}"); +} + +#[test] +fn sibling_redefinitions_along_a_chain_are_removed_level_by_level() { + // `Thermal::'packet data field'` redefines `Packets::'packet data + // field'`; each owns a `'secondary header'` redefining `'header'`. The + // nearer one removes the farther one at its own level, so a third + // level redefining the nearer field inherits exactly one. + let out = findings( + "package Packets { + private import ScalarValues::*; + attribute 'packet data field' { + attribute 'header' : Real; + attribute 'secondary header' redefines 'header'; + } + part def Packet { attribute redefines 'packet data field'; } + part def ThermalPacket :> Packet { + attribute 'packet data field' redefines Packets::'packet data field' { + attribute 'secondary header' redefines 'header'; + } + } + part packet3 : ThermalPacket { + attribute 'special data field' redefines 'packet data field' { + attribute 'more' : Real; + } + } + }", + ); + assert!(out.is_empty(), "{out:?}"); +} + +#[test] +fn library_only_diamonds_are_left_to_the_specialization_error() { + // `individual def X :> anAttributeDef` inherits `self` from both + // `DataValue` and `Occurrence`; the class-specialization error already + // names the cause, and the pair is not echoed. + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + model.add_source( + "d.sysml", + "package P { attribute def TipTilt; individual def Zero :> TipTilt; }", + ); + let mut r = ResolvedModel::build(&model); + let all: Vec = check::validate_semantics_with(&mut r, &model) + .into_iter() + .map(|(_, d)| d.message) + .collect(); + assert!( + all.iter() + .any(|m| m.contains("[validateClassSpecialization]")), + "{all:?}" + ); + assert!(!all.iter().any(|m| m.contains(RULE)), "{all:?}"); +} + +#[test] +fn two_unrelated_bases_supplying_one_name_collide_deterministically() { + let src = "package P { + private import ScalarValues::*; + part def A { attribute x : Real; attribute y : Real; } + part def B { attribute x : Real; attribute y : Real; } + part def C :> A, B; + }"; + let out = findings(src); + assert_eq!(out.len(), 2, "{out:?}"); + assert!( + out[0].starts_with("`x` is inherited from both `A` and `B`"), + "{out:?}" + ); + assert!( + out[1].starts_with("`y` is inherited from both `A` and `B`"), + "{out:?}" + ); + assert_eq!(findings(src), out, "order must not depend on hashing"); +} + +#[test] +fn a_chain_names_the_nearest_declaring_type() { + let out = findings( + "package P { + private import ScalarValues::*; + part def A { attribute x : Real; } + part def B :> A { attribute x : Real; } + part def C :> B { attribute x : Real; } + part c : C; + }", + ); + assert_eq!(out.len(), 3, "{out:?}"); + assert!(out.contains(&"`x` duplicates the inherited member name from `A` — redefine it (`:>>`) or rename it [validateNamespaceDistinguishibility]".to_string()), "{out:?}"); + assert!(out.contains(&"`x` duplicates the inherited member name from `B` — redefine it (`:>>`) or rename it [validateNamespaceDistinguishibility]".to_string()), "{out:?}"); + assert!( + out.iter() + .any(|m| m.starts_with("`x` is inherited from both")), + "{out:?}" + ); +} + +#[test] +fn subsetting_at_the_definition_also_clears_its_usages() { + let out = findings( + "package P { + private import ScalarValues::*; + attribute def SwitchStatus { attribute downlinkPort : Real; } + attribute def M1SwitchStatus :> SwitchStatus { attribute downlinkPort :> downlinkPort : Real[6]; } + attribute m1 : M1SwitchStatus; + }", + ); + assert!(out.is_empty(), "{out:?}"); +} + +#[test] +fn owned_members_of_usages_and_nested_definitions_are_checked() { + let out = findings( + "package P { + private import ScalarValues::*; + part def A { attribute x : Real; part def N; } + part a : A { attribute x : Real; } + part def B :> A { part def N; } + }", + ); + assert_eq!(out.len(), 2, "{out:?}"); + assert!( + out.iter() + .any(|m| m + .starts_with("`x` duplicates the inherited member name from `A` — redefine it")), + "{out:?}" + ); + assert!(out.iter().any(|m| m == "`N` duplicates the inherited member name from `A` — rename it [validateNamespaceDistinguishibility]"), "{out:?}"); +} + +#[test] +fn protected_members_inherit_and_private_ones_do_not() { + let out = findings( + "package P { + private import ScalarValues::*; + part def A { protected attribute x : Real; private attribute y : Real; } + part def B :> A { attribute x : Real; attribute y : Real; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!(out[0].starts_with("`x` duplicates"), "{out:?}"); +} + +#[test] +fn names_reexported_through_a_base_import_collide() { + let out = findings( + "package P { + package Q { attribute def W; } + part def A { public import Q::*; } + part def B :> A { attribute def W; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0].starts_with("`W` duplicates the inherited member name from `Q`"), + "{out:?}" + ); +} + +#[test] +fn parameters_redefine_positionally_only_under_behaviors() { + let out = findings( + "package P { + private import ScalarValues::*; + action def Act { in x : Real; } + action def Act2 :> Act { in x : Real; } + part def A { in attribute x : Real; } + part def B :> A { in attribute x : Real; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0].starts_with("`x` duplicates the inherited member name from `A`"), + "{out:?}" + ); +} + +#[test] +fn library_features_collide_with_user_usages_and_kerml_features() { + // The usage is typed by `B`, so its own body inherits both `portions` + // too — the same second finding a usage typed by any offending + // definition carries. + let out = findings( + "package P { + part def B { part portions : B; } + }", + ); + assert_eq!(out.len(), 2, "{out:?}"); + assert!( + out[0].starts_with("`portions` duplicates the inherited member name from `Occurrence`"), + "{out:?}" + ); + assert!( + out[1].starts_with("`portions` is inherited from both `B` and `Occurrence`"), + "{out:?}" + ); + let out = kerml_findings( + "package P { + private import Occurrences::Occurrence; + classifier Y specializes Occurrence { feature portions; } + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0].starts_with("`portions` duplicates the inherited member name from `Occurrence`"), + "{out:?}" + ); +} + +#[test] +fn a_diamond_reaching_both_sibling_redefinitions_collides() { + // `Mid2`'s `s` removes `Mid1`'s at `Mid2`'s own level, but `Leaf` also + // reaches `Mid1` directly and inherits both. + let out = findings( + "package P { + private import ScalarValues::*; + part def Base { attribute h : Real; } + part def Mid1 :> Base { attribute s :>> h; } + part def Mid2 :> Mid1 { attribute s :>> h; } + part def Leaf :> Mid2, Mid1; + part def Straight :> Mid2; + }", + ); + assert_eq!(out.len(), 1, "{out:?}"); + assert!( + out[0].starts_with("`s` is inherited from both `Mid1` and `Mid2`"), + "{out:?}" + ); +} diff --git a/crates/sysmlv2-parser/tests/eval.rs b/crates/sysmlv2-parser/tests/eval.rs index 9199048..600802a 100644 --- a/crates/sysmlv2-parser/tests/eval.rs +++ b/crates/sysmlv2-parser/tests/eval.rs @@ -6,6 +6,7 @@ use sysmlv2_parser::eval::{EvalError, Value}; use sysmlv2_parser::json::ResolvedModel; use sysmlv2_parser::model::Model; +use sysmlv2_parser::rational::Rational; /// Evaluate `expr` as `attribute result = ;` inside a package with /// `decls` alongside it. @@ -33,16 +34,244 @@ fn int(i: i128) -> Value { Value::Integer(i) } +fn rat(n: i128, d: i128) -> Value { + Value::Rational(Rational::new(n, d).unwrap()) +} + +#[test] +fn unknown_member_provenance_survives_value_operations() { + let decls = " + part def Child { attribute flag default = false; } + part def SpecializedChild :> Child { attribute :>> flag; } + part def Parent { part child : SpecializedChild; part children : Child[0..*]; } + part installed : Child; + requirement def R { subject unit : Parent; } + calc def Identity { in x; return result = x; } + "; + for expr in [ + "R::unit.child.flag", + "Identity(R::unit.child).flag", + "(if true ? R::unit.child else installed).flag", + "(R::unit.child, installed)#(1).flag", + "R::unit.child#(1).flag", + "(R::unit.child, installed)->forAll { in x; x.flag }", + "size(R::unit.children) == 1", + "notEmpty(R::unit.children)", + ] { + let value = eval_with(decls, expr); + // forAll includes an independently false concrete item, so it + // can refute even with an unknown item in the same collection. + let expected = if expr.contains("forAll") { + Value::Boolean(false) + } else { + Value::Indeterminate + }; + assert_eq!(value, Ok(expected), "{expr}"); + } + assert_eq!( + eval_with(decls, "(R::unit.child, installed).flag"), + Ok(Value::Sequence(vec![ + Value::Indeterminate, + Value::Boolean(false) + ])) + ); + assert_eq!(eval_with(decls, "size(R::unit.child)"), Ok(int(1))); + assert_eq!( + eval_with(decls, "Identity(installed).flag"), + Ok(Value::Boolean(false)) + ); +} + +#[test] +fn library_calls_preserve_unknown_receiver_members() { + let mut model = Model::new(); + let lib = model.add_library_source( + "library.sysml", + "package L { + calc def Read { in x; return result = x.child.flag; } + calc def LocalDefault { in x default = true; return result = x; } + }", + ); + assert!(lib.diagnostics.is_empty(), "{:?}", lib.diagnostics); + let user = model.add_source( + "t.sysml", + "package P { + part def Child { attribute flag default = false; } + part def Parent { + part child : Child; + attribute independent = L::LocalDefault(); + } + requirement def R { subject unit : Parent; } + part installed : Parent; + attribute unknownResult = L::Read(R::unit); + attribute knownResult = L::Read(installed); + attribute localDefault = R::unit.independent; + }", + ); + assert!(user.diagnostics.is_empty(), "{:?}", user.diagnostics); + let mut r = ResolvedModel::build(&model); + for (name, expected) in [ + ("unknownResult", Value::Indeterminate), + ("knownResult", Value::Boolean(false)), + ("localDefault", Value::Boolean(true)), + ] { + let e = r.resolve_qualified(&format!("P::{name}")).unwrap(); + assert_eq!(r.evaluate(e), Ok(expected), "{name}"); + } +} + +#[test] +fn unknown_receivers_agree_across_evaluation_entry_points() { + use sysmlv2_parser::ast::{Name, QualifiedName}; + let mut model = Model::new(); + model.add_source( + "t.sysml", + "package P { + part def Child { attribute flag default = false; } + part def Parent { part child : Child; attribute flag default = false; } + requirement def R { + subject unit : Parent; + ref part aliasUnit : Parent = unit; + } + part installed : Parent; + }", + ); + let mut r = ResolvedModel::build(&model); + let member = |value: &str| QualifiedName { + is_global: false, + segments: vec![Name { + value: value.into(), + span: Default::default(), + }], + span: Default::default(), + }; + for name in ["P::R::unit", "P::R::aliasUnit"] { + let root = r.resolve_qualified(name).unwrap(); + assert_eq!( + r.evaluate_chain(root, &[&member("child"), &member("flag")]), + Ok(Value::Indeterminate) + ); + assert_eq!( + r.evaluate_qualified(&format!("{name}::flag")), + Ok(Value::Indeterminate) + ); + } + let installed = r.resolve_qualified("P::installed").unwrap(); + assert_eq!( + r.evaluate_chain(installed, &[&member("child"), &member("flag")]), + Ok(Value::Boolean(false)) + ); +} + +#[test] +fn statement_calculations_never_return_unexecuted_initializers() { + for statement in [ + "assign i := i / 2;", + "loop { assign i := i / 2; } until i <= 1;", + "while i > 1 { assign i := i / 2; }", + "if i > 1 { assign i := 1; }", + "for x in (1, 2) { assign i := x; }", + "action update { assign i := 1; }", + ] { + let decl = format!( + "calc def Halve {{ in n; attribute i = n; {statement} return result = i; }} + calc halve : Halve;" + ); + for expression in ["Halve(9)", "halve(9)", "Halve::result", "Halve::i"] { + let result = eval_with(&decl, expression); + assert!( + matches!(&result, Err(EvalError::Unsupported(reason)) if reason.contains("statement execution")), + "{statement} / {expression}: {result:?}" + ); + } + let mut model = Model::new(); + model.add_source("t.sysml", &decl); + let mut resolved = ResolvedModel::build(&model); + let calc = resolved.resolve_qualified("Halve").unwrap(); + // Solver clients must not inline the return expression either. + assert!(resolved.calc_body(calc).is_none()); + } + assert_eq!( + eval_with( + "calc half { in n; attribute i = n / 2; return result = i; }", + "half(9)" + ), + Ok(rat(9, 2)) + ); +} + +#[test] +fn calculation_arguments_cannot_bind_a_parameter_twice() { + let decl = "calc f { in x; in y; x + y }"; + for expr in ["f(x = 1, x = 2, y = 3)", "f(1, x = 2, y = 3)"] { + let value = eval_with(decl, expr); + assert!( + matches!(&value, Err(EvalError::Type(m)) if m.contains("bound more than once")), + "{expr}: {value:?}" + ); + } + assert_eq!(eval_with(decl, "f(y = 3, x = 2)"), Ok(int(5))); +} + +#[test] +fn calculation_defaults_and_missing_inputs_do_not_capture_caller_parameters() { + let declarations = "calc f { in x; x } calc g { in x; f() }"; + assert!( + matches!(eval_with(declarations, "g(9)"), Err(EvalError::Unresolved(m)) if m.contains("unbound parameter `x`")) + ); + assert_eq!( + eval_with("calc f { in x = 2; x } calc g { in x; f() }", "g(9)"), + Ok(int(2)) + ); + assert_eq!( + eval_with( + "calc f { in x = y; in y = 3; x + y } calc g { in y; f() }", + "g(9)" + ), + Ok(int(6)) + ); + assert_eq!( + eval_with("calc f { in x; in y = x + 1; x + y }", "f(4)"), + Ok(int(9)) + ); + assert_eq!( + eval_with("calc f { in x; x + 1 } calc g { in x; f(2) + x }", "g(9)"), + Ok(int(12)) + ); +} + +#[test] +fn lambdas_and_constructors_do_not_ignore_invalid_bindings_or_statements() { + assert!( + matches!(eval("(1, 2)->collect { in x; in y; x }"), Err(EvalError::Type(m)) if m.contains("lambda expects")) + ); + assert!( + matches!(eval("(1, 2)->collect { in x; assign x := 9; x }"), Err(EvalError::Unsupported(m)) if m.contains("statement execution")) + ); + assert!(matches!( + eval_with( + "attribute y = 7;", + "(1, 2)->collect { in x; attribute y = x + 1; y }" + ), + Err(EvalError::Unsupported(_)) + )); + for expression in ["new P(x = 1, x = 2)", "new P(1, x = 2)"] { + assert!( + matches!(eval_with("part def P { attribute x; }", expression), Err(EvalError::Type(m)) if m.contains("bound more than once")) + ); + } +} + #[test] fn arithmetic_and_precedence() { assert_eq!(eval("1 + 2 * 3"), Ok(int(7))); assert_eq!(eval("(1 + 2) * 3"), Ok(int(9))); assert_eq!(eval("2 ** 10"), Ok(int(1024))); // KFL `IntegerFunctions::'/'` returns Rational: true division. - assert_eq!(eval("7 / 2"), Ok(Value::Rational(3.5))); - assert_eq!(eval("7.0 / 2"), Ok(Value::Rational(3.5))); - assert_eq!(eval("9 ** (1/2)"), Ok(Value::Rational(3.0))); - assert_eq!(eval("ln(exp(2.0))"), Ok(Value::Rational(2.0))); + assert_eq!(eval("7 / 2"), Ok(rat(7, 2))); + assert_eq!(eval("7.0 / 2"), Ok(rat(7, 2))); + assert_eq!(eval("9 ** (1/2)"), Ok(int(3))); + assert_eq!(eval("ln(exp(2.0))"), Ok(Value::Real(2.0))); assert_eq!(eval("7 % 3"), Ok(int(1))); assert_eq!(eval("-5 + 3"), Ok(int(-2))); assert_eq!(eval("1 / 0"), Err(EvalError::DivisionByZero)); @@ -88,7 +317,7 @@ fn feature_references_and_cycles() { #[test] fn intrinsics() { assert_eq!(eval("sum((1, 2, 3))"), Ok(int(6))); - assert_eq!(eval("sum((1, 2.5))"), Ok(Value::Rational(3.5))); + assert_eq!(eval("sum((1, 2.5))"), Ok(rat(7, 2))); assert_eq!(eval("product(2..4)"), Ok(int(24))); assert_eq!(eval("size((7, 8))"), Ok(int(2))); assert_eq!(eval("isEmpty(null)"), Ok(Value::Boolean(true))); @@ -109,9 +338,9 @@ fn intrinsics() { assert_eq!(eval("ToInteger(\"42\")"), Ok(int(42))); // TrigFunctions / RationalFunctions / NumericalFunctions / // ComplexFunctions-on-reals. - assert_eq!(eval("sin(0)"), Ok(Value::Rational(0.0))); - assert_eq!(eval("cos(0)"), Ok(Value::Rational(1.0))); - assert_eq!(eval("rat(1, 4)"), Ok(Value::Rational(0.25))); + assert_eq!(eval("sin(0)"), Ok(Value::Real(0.0))); + assert_eq!(eval("cos(0)"), Ok(Value::Real(1.0))); + assert_eq!(eval("rat(1, 4)"), Ok(rat(1, 4))); assert_eq!(eval("isZero(0)"), Ok(Value::Boolean(true))); assert_eq!(eval("isUnit(2)"), Ok(Value::Boolean(false))); assert_eq!(eval("re(7)"), Ok(int(7))); @@ -511,10 +740,7 @@ fn quantity_brackets() { eval_with(units, "3 * (10 [mm])"), Ok(Value::Quantity(Box::new(int(30)), unit_probe("mm"))) ); - assert_eq!( - eval_with(units, "30 [mm] / (10 [mm])"), - Ok(Value::Rational(3.0)) - ); + assert_eq!(eval_with(units, "30 [mm] / (10 [mm])"), Ok(int(3))); // Different units never mix silently — `kg` vs `mm` is an error, not // `false` (no unit conversion happens either way). assert!(matches!( @@ -582,10 +808,14 @@ fn user_defined_calculations() { ), Ok(int(55)) ); - assert!(matches!( - eval_with("calc def Loop { in n; Loop(n) }", "Loop(1)"), - Err(EvalError::Cycle(_)) - )); + // A non-terminating recursion exhausts the call-depth budget — not + // the stack, and not the feature-value cycle guard, which sees a new + // invocation each time. + let loop_calc = eval_with("calc def Loop { in n; Loop(n) }", "Loop(1)"); + assert!( + matches!(&loop_calc, Err(EvalError::Budget(m)) if m.contains("calculation calls")), + "{loop_calc:?}" + ); // Wrong arguments error cleanly. assert!(matches!( eval_with(calc, "Torque(1, 2, 3)"), @@ -770,7 +1000,7 @@ fn unit_normalization() { assert_eq!( eval_with(units, "(10 [m]) / (5 [m/s])"), Ok(Value::Quantity( - Box::new(Value::Rational(2.0)), + Box::new(int(2)), unit_probe_with(units, "s") )) ); @@ -778,7 +1008,7 @@ fn unit_normalization() { assert_eq!( eval_with(units, "2 / (4 [s])"), Ok(Value::Quantity( - Box::new(Value::Rational(0.5)), + Box::new(rat(1, 2)), // `m/(m*s)` cancels to the reciprocal second. unit_probe_with(units, "m/(m*s)") )) @@ -788,21 +1018,21 @@ fn unit_normalization() { assert_eq!( eval_with(units, "(9 [m**2]) ** (1/2)"), Ok(Value::Quantity( - Box::new(Value::Rational(3.0)), + Box::new(int(3)), unit_probe_with(units, "m") )) ); assert_eq!( eval_with(units, "sqrt(9 [m**2])"), Ok(Value::Quantity( - Box::new(Value::Rational(3.0)), + Box::new(int(3)), unit_probe_with(units, "m") )) ); // Full cancellation leaves a plain number. assert_eq!( eval_with(units, "(6 [m/s]) * (2 [s]) / (4 [m])"), - Ok(Value::Rational(3.0)) + Ok(int(3)) ); // Base units stay distinct — normalization is erasure, not conversion. assert!(matches!( @@ -833,7 +1063,7 @@ fn unit_spelling_expansion() { assert_eq!( eval_with(units, "(2 ['m⋅s⁻¹']) ** 2 + 1 ['m³⋅s⁻²'] / (1 [m])"), Ok(Value::Quantity( - Box::new(Value::Rational(5.0)), + Box::new(int(5)), unit_probe_with(units, "m**2/s**2"), )) ); @@ -965,14 +1195,14 @@ fn quantity_brackets_convert_and_take_vectors() { assert_eq!( eval_with(units, "(2 [min]) [s]"), Ok(Value::Quantity( - Box::new(Value::Rational(120.0)), + Box::new(int(120)), unit_probe_with(units, "s") )) ); assert_eq!( eval_with(units, "(120 [s]) [min]"), Ok(Value::Quantity( - Box::new(Value::Rational(2.0)), + Box::new(int(2)), unit_probe_with(units, "min") )) ); @@ -981,10 +1211,7 @@ fn quantity_brackets_convert_and_take_vectors() { assert_eq!( eval_with(units, "((2, 3) [min]) [s]"), Ok(Value::Quantity( - Box::new(Value::Sequence(vec![ - Value::Rational(120.0), - Value::Rational(180.0), - ])), + Box::new(Value::Sequence(vec![int(120), int(180),])), unit_probe_with(units, "s") )) ); @@ -1010,7 +1237,7 @@ fn quantity_brackets_convert_and_take_vectors() { Ok(Value::Quantity( Box::new(Value::Sequence(vec![ int(0), - Value::Quantity(Box::new(Value::Rational(7.5)), unit_probe_with(units, "m")), + Value::Quantity(Box::new(rat(15, 2)), unit_probe_with(units, "m")), int(0), ])), unit_probe_with(units, "f") @@ -1050,7 +1277,7 @@ fn unit_conversion_via_measurement_references() { assert_eq!( eval_with(units, "30 [min] + 30 [s]"), Ok(Value::Quantity( - Box::new(Value::Rational(30.5)), + Box::new(rat(61, 2)), unit_probe_with(units, "min") )) ); @@ -1068,15 +1295,12 @@ fn unit_conversion_via_measurement_references() { assert_eq!( eval_with(units, "2 [km] * (2 [m])"), Ok(Value::Quantity( - Box::new(Value::Rational(4000.0)), + Box::new(int(4000)), unit_probe_with(units, "m**2") )) ); // Division cancels dimensions across scales. - assert_eq!( - eval_with(units, "1 [km] / (500 [m])"), - Ok(Value::Rational(2.0)) - ); + assert_eq!(eval_with(units, "1 [km] / (500 [m])"), Ok(int(2))); // Different dimensions are still a type error — conversion applies // only within one dimension. assert!(matches!( @@ -1104,14 +1328,14 @@ fn bracket_over_quantity() { assert_eq!( eval_with(units, "(90 [s]) [min]"), Ok(Value::Quantity( - Box::new(Value::Rational(1.5)), + Box::new(rat(3, 2)), unit_probe_with(units, "min") )) ); assert_eq!( eval_with(units, "(1.5 [min]) [s]"), Ok(Value::Quantity( - Box::new(Value::Rational(90.0)), + Box::new(int(90)), unit_probe_with(units, "s") )) ); @@ -1133,10 +1357,7 @@ fn bracket_over_quantity() { ); // The motivating idiom: dividing by an annotated quantity keeps the // whole expression computable (`100 [kg] / rho [kg]` cancels). - assert_eq!( - eval_with(units, "100 [kg] / (50 [m] [kg])"), - Ok(Value::Rational(2.0)) - ); + assert_eq!(eval_with(units, "100 [kg] / (50 [m] [kg])"), Ok(int(2))); } /// Classification operators (KFL BaseFunctions): `istype` walks the @@ -1272,7 +1493,7 @@ fn performed_actions_rollup_evaluates() { .resolve_qualified("Tally::audit::total") .expect("total resolves"); // c1 + c2 are performed (4 + 9); c3 exists but is not performed. - assert_eq!(r.evaluate(e), Ok(Value::Rational(13.0))); + assert_eq!(r.evaluate(e), Ok(int(13))); } /// A bare unbound feature is a placeholder for an *unknown* sequence: @@ -1390,3 +1611,277 @@ fn verdict_helpers_evaluate_to_enum_members() { "VerificationCases::VerdictKind::fail" ); } + +/// Numbers are exact: decimal literals are rationals, arithmetic over +/// them never rounds, integers outgrow the machine range without +/// wrapping, and only transcendental results are approximate doubles. +#[test] +fn exact_rational_arithmetic() { + assert_eq!(eval("0.1 + 0.2"), Ok(rat(3, 10))); + assert_eq!(eval("0.1 + 0.2 == 0.3"), Ok(Value::Boolean(true))); + assert_eq!(eval("0.1 * 3"), Ok(rat(3, 10))); + assert_eq!(eval("100 * 1.1"), Ok(int(110))); + assert_eq!(eval("1.1 * 1.1"), Ok(rat(121, 100))); + assert_eq!(eval("0.1 + 0.7"), Ok(rat(4, 5))); + assert_eq!(eval("1 / 3"), Ok(rat(1, 3))); + assert_eq!(eval("1 / 3 * 3"), Ok(int(1))); + assert_eq!(eval("7 / 2 * 2"), Ok(int(7))); + assert_eq!(eval("2.0"), Ok(int(2))); + assert_eq!(eval("2 ** -2"), Ok(rat(1, 4))); + let text = |e: &str| eval(e).map(|v| v.to_string()); + assert_eq!(text("2.957353E-05"), Ok("0.00002957353".into())); + assert_eq!(text("1 / 3"), Ok("1/3".into())); + assert_eq!(text("0.1 + 0.2"), Ok("0.3".into())); + assert_eq!(text("-0.5 * 3"), Ok("-1.5".into())); + // Integer results beyond `i128` stay exact instead of wrapping. + assert_eq!( + text("2 ** 200"), + Ok("1606938044258990275541962092341162602522202993782792835301376".into()) + ); + assert_eq!(eval("2 ** 200 / 2 ** 199"), Ok(int(2))); + assert_eq!( + text("170141183460469231731687303715884105727 + 1"), + Ok("170141183460469231731687303715884105728".into()) + ); + assert_eq!( + eval("170141183460469231731687303715884105727 + 1 - 1"), + Ok(int(170141183460469231731687303715884105727)) + ); + // Exact roots and powers; inexact ones are doubles. + assert_eq!(eval("sqrt(0.25)"), Ok(rat(1, 2))); + assert_eq!(eval("8 ** (2/3)"), Ok(int(4))); + assert_eq!(eval("sqrt(2)"), Ok(Value::Real(std::f64::consts::SQRT_2))); + assert!(matches!(eval("sqrt(-1)"), Err(EvalError::Type(_)))); + // Comparison across exact and approximate numbers is exact. + assert_eq!(eval("3 == 3.0"), Ok(Value::Boolean(true))); + assert_eq!(eval("sqrt(0.25) == 0.5"), Ok(Value::Boolean(true))); + assert_eq!(eval("0.1 < 1/3"), Ok(Value::Boolean(true))); + assert_eq!(eval("sqrt(2) * sqrt(2) == 2"), Ok(Value::Boolean(false))); + assert_eq!(eval("max((0.3, 0.1 + 0.2))"), Ok(rat(3, 10))); + // Rational parts, rounding, and string conversion stay exact. + assert_eq!(eval("numer(0.75)"), Ok(int(3))); + assert_eq!(eval("denom(0.75)"), Ok(int(4))); + assert_eq!(eval("rat(1, 3) + rat(2, 3)"), Ok(int(1))); + assert_eq!(eval("floor(-0.5)"), Ok(int(-1))); + assert_eq!(eval("round(2.5)"), Ok(int(3))); + assert_eq!(eval("floor(sqrt(2))"), Ok(int(1))); + assert_eq!(eval("7.5 % 2"), Ok(rat(3, 2))); + assert_eq!(eval("ToReal(\"0.1\") + ToReal(\"0.2\")"), Ok(rat(3, 10))); + assert_eq!(eval("ToString(0.1 + 0.2)"), Ok(Value::String("0.3".into()))); + assert_eq!(eval("ToString(1 / 3)"), Ok(Value::String("1/3".into()))); + // `ToString` output reads back exactly, in either spelling. + assert_eq!(eval("ToReal(ToString(1 / 3))"), Ok(rat(1, 3))); + assert_eq!(eval("ToReal(\"-500000/3183\")"), Ok(rat(-500000, 3183))); + assert_eq!(eval("ToReal(\"2.5\") * 2"), Ok(int(5))); + assert!(matches!(eval("ToReal(\"1/0\")"), Err(EvalError::Type(_)))); + // Rounding an infinite value is an error, not a saturated integer. + assert!(matches!( + eval("floor(1 / 0.0)"), + Err(EvalError::DivisionByZero) + )); + assert!(matches!(eval("round(*)"), Err(EvalError::Type(_)))); +} + +/// A computed double exponent still names a root when it is the +/// nearest double of a small fraction, as a literal exponent does. +#[test] +fn approximate_unit_exponents_snap_to_small_fractions() { + let units = "attribute m;"; + assert_eq!( + eval_with(units, "(9 [m**2]) ** (sqrt(0.25))"), + Ok(Value::Quantity( + Box::new(int(3)), + unit_probe_with(units, "m") + )) + ); + // The unit exponent snaps; the magnitude stays approximate because an + // approximate operand took part. + assert_eq!( + eval_with(units, "(9 [m**2]) ** (cos(0) / 2)"), + Ok(Value::Quantity( + Box::new(Value::Real(3.0)), + unit_probe_with(units, "m") + )) + ); + assert!(matches!( + eval_with(units, "(9 [m**2]) ** (sqrt(2))"), + Err(EvalError::Unsupported(_)) + )); +} + +/// Unit scales are exact, so conversions never round: a millimetre +/// factor of `0.001` is one thousandth, not its nearest double. +#[test] +fn exact_unit_conversion() { + let units = "attribute m; + attribute mm { + attribute unitConversion { + attribute referenceUnit = m; + attribute conversionFactor = 0.001; + } + } + attribute inch { + attribute unitConversion { + attribute referenceUnit = m; + attribute conversionFactor = 2.54E-02; + } + }"; + assert_eq!( + eval_with(units, "1 [mm] + 1 [m]"), + Ok(Value::Quantity( + Box::new(int(1001)), + unit_probe_with(units, "mm") + )) + ); + assert_eq!( + eval_with(units, "(3 [mm]) [m]"), + Ok(Value::Quantity( + Box::new(rat(3, 1000)), + unit_probe_with(units, "m") + )) + ); + assert_eq!( + eval_with(units, "(0.3 [m]) [mm]"), + Ok(Value::Quantity( + Box::new(int(300)), + unit_probe_with(units, "mm") + )) + ); + assert_eq!( + eval_with(units, "0.1 [m] + 0.2 [m] == 0.3 [m]"), + Ok(Value::Boolean(true)) + ); + assert_eq!( + eval_with(units, "300 [mm] == 0.3 [m]"), + Ok(Value::Boolean(true)) + ); + assert_eq!( + eval_with(units, "(1 [inch]) [mm]"), + Ok(Value::Quantity( + Box::new(rat(127, 5)), + unit_probe_with(units, "mm") + )) + ); + assert_eq!( + eval_with(units, "(1 [m]) / (3 [mm])").map(|v| v.to_string()), + Ok("1000/3".into()) + ); + assert_eq!( + eval_with(units, "((1 [mm]) * (1 [mm])) [m ** 2]"), + Ok(Value::Quantity( + Box::new(rat(1, 1_000_000)), + unit_probe_with(units, "m ** 2") + )) + ); +} + +/// The evaluation budget: a range, a string or a step count that would +/// run or allocate without bound fails cleanly instead of hanging the +/// evaluator or exhausting memory. +#[test] +fn evaluation_budget_bounds_ranges_strings_and_steps() { + let range = eval("1..1000000000"); + assert!( + matches!(&range, Err(EvalError::Budget(m)) if m.contains("range")), + "{range:?}" + ); + let wide = eval("-500000000..500000000"); + assert!(matches!(&wide, Err(EvalError::Budget(_))), "{wide:?}"); + assert_eq!( + eval("(1..3)->collect { in x; x * 2 }"), + Ok(Value::Sequence(vec![int(2), int(4), int(6)])) + ); + let doubling = eval_with( + "calc def dbl { in s; in n; if n <= 0 ? s else dbl(s + s, n - 1) }", + "dbl(\"x\", 40)", + ); + assert!( + matches!(&doubling, Err(EvalError::Budget(m)) if m.contains("string")), + "{doubling:?}" + ); + // Step-heavy without allocating: every range an inner lambda built + // would count against the allocation budget first. + let steps = eval("(1..1000000)->collect { in x; x + x + x + x + x + x + x + x + x + x + x }"); + assert!( + matches!(&steps, Err(EvalError::Budget(m)) if m.contains("steps")), + "{steps:?}" + ); +} + +/// Budgets that the step count alone cannot enforce: sequences and +/// strings that are each admissible but add up, range bounds spanning the +/// machine range, and exact integers that grow one multiplication at a time. +#[test] +fn evaluation_budget_bounds_cumulative_allocation_and_number_size() { + use sysmlv2_parser::eval::MAX_ALLOCATION; + // One full-size range is admissible; a collect that materializes one + // per element is not, although it needs only a few million steps. + assert!(1_000_000 * std::mem::size_of::() <= MAX_ALLOCATION); + assert_eq!(eval("size(1..1000000)"), Ok(int(1_000_000))); + let nested = eval("(1..1000000)->collect { in x; 1..1000000 }"); + assert!( + matches!(&nested, Err(EvalError::Budget(m)) if m.contains("bytes")), + "{nested:?}" + ); + // Strings below the per-operation limit still add up. + let strings = eval_with( + "calc def dbl { in s; in n; if n <= 0 ? s else dbl(s + s, n - 1) }", + "(1..40)->collect { in i; dbl(\"x\", 23) }", + ); + assert!( + matches!(&strings, Err(EvalError::Budget(m)) if m.contains("bytes")), + "{strings:?}" + ); + // Bounds spanning the machine range are refused, not overflowed. + let extreme = + eval("-170141183460469231731687303715884105727..170141183460469231731687303715884105727"); + assert!( + matches!(&extreme, Err(EvalError::Budget(m)) if m.contains("range")), + "{extreme:?}" + ); + assert_eq!(eval("size(5..3)"), Ok(int(0))); + // Exact integers stop growing at the bit limit: a fold such as + // `product(1..1000000)` fails the same way, one multiplication past + // the limit, but takes tens of thousands of large multiplications to + // get there, so the check is exercised here through powers instead. + assert_eq!(eval("product(1..20)"), Ok(int(2_432_902_008_176_640_000))); + assert_eq!(eval("Length(ToString(2 ** 500000))"), Ok(int(150_515))); + let product = eval("(2 ** 500000) * (2 ** 500000) * (2 ** 100000)"); + assert!( + matches!(&product, Err(EvalError::Budget(m)) if m.contains("bits")), + "{product:?}" + ); + // A power past the limit degrades to an approximate infinity instead; + // exact operands just under it still add past it. + assert_eq!(eval("2 ** 1000000"), Ok(Value::Real(f64::INFINITY))); + let sum = eval("(2 ** 524288) * (2 ** 524287) + (2 ** 524288) * (2 ** 524287)"); + assert!( + matches!(&sum, Err(EvalError::Budget(m)) if m.contains("bits")), + "{sum:?}" + ); +} + +/// The allocation budget covers every operator that materializes a value, +/// not only arithmetic: an intrinsic that copies a sequence and a fold +/// that grows a string one item at a time each stay under the per-value +/// limits while adding up far past the cumulative one. +#[test] +fn evaluation_budget_covers_intrinsics_and_per_item_results() { + // Each copy of a full-size range is admissible on its own. + assert_eq!(eval("size(reverse(1..1000000))"), Ok(int(1_000_000))); + let copies = eval("size(reverse(reverse(reverse(reverse(reverse(1..1000000))))))"); + assert!( + matches!(&copies, Err(EvalError::Budget(m)) if m.contains("bytes")), + "{copies:?}" + ); + // A fold whose accumulator grows by a kilobyte per item: every + // intermediate string is small, their total is not. + let folded = eval_with( + "calc def dbl { in s; in n; if n <= 0 ? s else dbl(s + s, n - 1) }", + "(1..1000)->collect { in i; dbl(\"x\", 10) }->reduce '+'", + ); + assert!( + matches!(&folded, Err(EvalError::Budget(m)) if m.contains("bytes")), + "{folded:?}" + ); +} diff --git a/crates/sysmlv2-parser/tests/eval_unit_spelling_off.rs b/crates/sysmlv2-parser/tests/eval_unit_spelling_off.rs index cc5c0ff..7ea567f 100644 --- a/crates/sysmlv2-parser/tests/eval_unit_spelling_off.rs +++ b/crates/sysmlv2-parser/tests/eval_unit_spelling_off.rs @@ -45,4 +45,22 @@ fn spelling_expansion_disabled_keeps_spellings_opaque() { )) ); set_unit_spelling_expansion(true); + let mut library = Model::new(); + library.add_library_source("units.sysml", "package Quantities { attribute def MeasurementUnit; } package T { attribute m : Quantities::MeasurementUnit; attribute s : Quantities::MeasurementUnit; attribute <'m/s'> speed : Quantities::MeasurementUnit; }"); + let prepared = library.prepare_library().unwrap(); + let mut model = Model::new(); + prepared.install(&mut model).unwrap(); + model.add_source( + "u.sysml", + "package U { private import T::*; attribute result = 1 ['m/s'] + 1 [m/s]; }", + ); + let mut r = ResolvedModel::build(&model); + assert!(r.evaluate_qualified("U::result").is_ok()); + set_unit_spelling_expansion(false); + assert!(matches!( + r.evaluate_qualified("U::result"), + Err(EvalError::Type(_)) + )); + set_unit_spelling_expansion(true); + assert!(r.evaluate_qualified("U::result").is_ok()); } diff --git a/crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv b/crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv new file mode 100644 index 0000000..5990bc0 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv @@ -0,0 +1,10707 @@ +# metaclass property digest elements nonempty +AcceptActionUsage actionDefinition f754965b3c37d264 103 0 +AcceptActionUsage aliasIds f754965b3c37d264 103 0 +AcceptActionUsage behavior f754965b3c37d264 103 0 +AcceptActionUsage chainingFeature f754965b3c37d264 103 0 +AcceptActionUsage crossFeature 3bf7b4f43a417d07 103 0 +AcceptActionUsage declaredName bf38b21b55da6684 103 16 +AcceptActionUsage declaredShortName 3bf7b4f43a417d07 103 0 +AcceptActionUsage definition f754965b3c37d264 103 0 +AcceptActionUsage differencingType f754965b3c37d264 103 0 +AcceptActionUsage directedFeature 7eb87ade6e9a9f45 103 103 +AcceptActionUsage directedUsage 7eb87ade6e9a9f45 103 103 +AcceptActionUsage direction 3bf7b4f43a417d07 103 0 +AcceptActionUsage documentation f754965b3c37d264 103 0 +AcceptActionUsage elementId 4aee7b1ade05014c 103 103 +AcceptActionUsage endFeature f754965b3c37d264 103 0 +AcceptActionUsage endOwningType 3bf7b4f43a417d07 103 0 +AcceptActionUsage feature 365776f886c8f508 103 103 +AcceptActionUsage featureMembership 88a23bc2c68b7111 103 103 +AcceptActionUsage featureTarget a46efa6fbea098eb 103 0 +AcceptActionUsage featuringType f754965b3c37d264 103 0 +AcceptActionUsage importedMembership f754965b3c37d264 103 0 +AcceptActionUsage individualDefinition 3bf7b4f43a417d07 103 0 +AcceptActionUsage inheritedFeature f754965b3c37d264 103 0 +AcceptActionUsage inheritedMembership f754965b3c37d264 103 0 +AcceptActionUsage input 7eb87ade6e9a9f45 103 103 +AcceptActionUsage intersectingType f754965b3c37d264 103 0 +AcceptActionUsage isAbstract c8d27cdba36882f9 103 0 +AcceptActionUsage isComposite 2110b307b7176b78 103 103 +AcceptActionUsage isConjugated d1b0bbcdf1e10a4d 103 0 +AcceptActionUsage isConstant c8d27cdba36882f9 103 0 +AcceptActionUsage isDerived c8d27cdba36882f9 103 0 +AcceptActionUsage isEnd c8d27cdba36882f9 103 0 +AcceptActionUsage isImpliedIncluded 2110b307b7176b78 103 103 +AcceptActionUsage isIndividual 3bf7b4f43a417d07 103 0 +AcceptActionUsage isLibraryElement d1b0bbcdf1e10a4d 103 0 +AcceptActionUsage isOrdered c8d27cdba36882f9 103 0 +AcceptActionUsage isPortion 3bf7b4f43a417d07 103 0 +AcceptActionUsage isReference d1b0bbcdf1e10a4d 103 0 +AcceptActionUsage isSufficient 3bf7b4f43a417d07 103 0 +AcceptActionUsage isUnique e1a918c8192f14fc 103 23 +AcceptActionUsage isVariable 3bf7b4f43a417d07 103 0 +AcceptActionUsage isVariation d1b0bbcdf1e10a4d 103 0 +AcceptActionUsage mayTimeVary 3bf7b4f43a417d07 103 0 +AcceptActionUsage member 083fdc9a0099cee9 103 103 +AcceptActionUsage membership 9ccbb7ea8ee04620 103 103 +AcceptActionUsage multiplicity 3bf7b4f43a417d07 103 0 +AcceptActionUsage name ac08b992a3ce05d4 103 96 +AcceptActionUsage nestedAction f754965b3c37d264 103 0 +AcceptActionUsage nestedAllocation f754965b3c37d264 103 0 +AcceptActionUsage nestedAnalysisCase f754965b3c37d264 103 0 +AcceptActionUsage nestedAttribute f754965b3c37d264 103 0 +AcceptActionUsage nestedCalculation f754965b3c37d264 103 0 +AcceptActionUsage nestedCase f754965b3c37d264 103 0 +AcceptActionUsage nestedConcern f754965b3c37d264 103 0 +AcceptActionUsage nestedConnection f754965b3c37d264 103 0 +AcceptActionUsage nestedConstraint f754965b3c37d264 103 0 +AcceptActionUsage nestedEnumeration f754965b3c37d264 103 0 +AcceptActionUsage nestedFlow f754965b3c37d264 103 0 +AcceptActionUsage nestedInterface 7eb87ade6e9a9f45 103 103 +AcceptActionUsage nestedItem f754965b3c37d264 103 0 +AcceptActionUsage nestedMetadata f754965b3c37d264 103 0 +AcceptActionUsage nestedOccurrence f754965b3c37d264 103 0 +AcceptActionUsage nestedPart f754965b3c37d264 103 0 +AcceptActionUsage nestedPort f754965b3c37d264 103 0 +AcceptActionUsage nestedReference 7eb87ade6e9a9f45 103 103 +AcceptActionUsage nestedRendering f754965b3c37d264 103 0 +AcceptActionUsage nestedRequirement f754965b3c37d264 103 0 +AcceptActionUsage nestedState f754965b3c37d264 103 0 +AcceptActionUsage nestedTransition f754965b3c37d264 103 0 +AcceptActionUsage nestedUsage 7eb87ade6e9a9f45 103 103 +AcceptActionUsage nestedUseCase f754965b3c37d264 103 0 +AcceptActionUsage nestedVerificationCase f754965b3c37d264 103 0 +AcceptActionUsage nestedView f754965b3c37d264 103 0 +AcceptActionUsage nestedViewpoint f754965b3c37d264 103 0 +AcceptActionUsage occurrenceDefinition f754965b3c37d264 103 0 +AcceptActionUsage output f64efe5b5615c13e 103 103 +AcceptActionUsage ownedAnnotation f754965b3c37d264 103 0 +AcceptActionUsage ownedConjugator 3bf7b4f43a417d07 103 0 +AcceptActionUsage ownedCrossSubsetting 3bf7b4f43a417d07 103 0 +AcceptActionUsage ownedDifferencing f754965b3c37d264 103 0 +AcceptActionUsage ownedDisjoining f754965b3c37d264 103 0 +AcceptActionUsage ownedElement 083fdc9a0099cee9 103 103 +AcceptActionUsage ownedEndFeature f754965b3c37d264 103 0 +AcceptActionUsage ownedFeature 365776f886c8f508 103 103 +AcceptActionUsage ownedFeatureChaining f754965b3c37d264 103 0 +AcceptActionUsage ownedFeatureInverting f754965b3c37d264 103 0 +AcceptActionUsage ownedFeatureMembership 88a23bc2c68b7111 103 103 +AcceptActionUsage ownedImport f754965b3c37d264 103 0 +AcceptActionUsage ownedIntersecting f754965b3c37d264 103 0 +AcceptActionUsage ownedMember 083fdc9a0099cee9 103 103 +AcceptActionUsage ownedMembership 9ccbb7ea8ee04620 103 103 +AcceptActionUsage ownedRedefinition f754965b3c37d264 103 0 +AcceptActionUsage ownedReferenceSubsetting 3bf7b4f43a417d07 103 0 +AcceptActionUsage ownedRelationship aceba516cb212b79 103 103 +AcceptActionUsage ownedSpecialization 7d9fac6fbc52e8bf 103 103 +AcceptActionUsage ownedSubsetting 7d9fac6fbc52e8bf 103 103 +AcceptActionUsage ownedTypeFeaturing f754965b3c37d264 103 0 +AcceptActionUsage ownedTyping f754965b3c37d264 103 0 +AcceptActionUsage ownedUnioning f754965b3c37d264 103 0 +AcceptActionUsage owner babd825811b5d2d6 103 103 +AcceptActionUsage owningDefinition 3bf7b4f43a417d07 103 0 +AcceptActionUsage owningFeatureMembership be24b30acc35d024 103 103 +AcceptActionUsage owningMembership be24b30acc35d024 103 103 +AcceptActionUsage owningNamespace babd825811b5d2d6 103 103 +AcceptActionUsage owningRelationship be24b30acc35d024 103 103 +AcceptActionUsage owningType babd825811b5d2d6 103 103 +AcceptActionUsage owningUsage babd825811b5d2d6 103 103 +AcceptActionUsage parameter 7eb87ade6e9a9f45 103 103 +AcceptActionUsage payloadArgument b421a3281be89bc8 103 18 +AcceptActionUsage payloadParameter f7a200b3fad6f20a 103 103 +AcceptActionUsage portionKind 3bf7b4f43a417d07 103 0 +AcceptActionUsage qualifiedName 3f84796fc69a701b 103 51 +AcceptActionUsage receiverArgument caa336fb3d8bf30e 103 22 +AcceptActionUsage shortName 3bf7b4f43a417d07 103 0 +AcceptActionUsage textualRepresentation f754965b3c37d264 103 0 +AcceptActionUsage type f754965b3c37d264 103 0 +AcceptActionUsage unioningType f754965b3c37d264 103 0 +AcceptActionUsage usage 7eb87ade6e9a9f45 103 103 +AcceptActionUsage variant f754965b3c37d264 103 0 +AcceptActionUsage variantMembership f754965b3c37d264 103 0 +ActionDefinition action 4672b5af238d430d 113 16 +ActionDefinition aliasIds f91e4d450b44243e 113 0 +ActionDefinition declaredName de3a097cd6ec96ae 113 113 +ActionDefinition declaredShortName ba991553c6bd9f9f 113 0 +ActionDefinition differencingType f91e4d450b44243e 113 0 +ActionDefinition directedFeature d93fb682aeefb019 113 74 +ActionDefinition directedUsage d93fb682aeefb019 113 74 +ActionDefinition documentation f91e4d450b44243e 113 0 +ActionDefinition elementId 29e1fb87a1594d84 113 113 +ActionDefinition endFeature f91e4d450b44243e 113 0 +ActionDefinition feature 96192dfc9055e223 113 85 +ActionDefinition featureMembership 1c52452c81301b43 113 85 +ActionDefinition importedMembership f91e4d450b44243e 113 0 +ActionDefinition inheritedFeature f91e4d450b44243e 113 0 +ActionDefinition inheritedMembership f91e4d450b44243e 113 0 +ActionDefinition input 1de34a2f3444b385 113 64 +ActionDefinition intersectingType f91e4d450b44243e 113 0 +ActionDefinition isAbstract e7bedd97fe920a22 113 1 +ActionDefinition isConjugated db5948bc0fb78dad 113 0 +ActionDefinition isImpliedIncluded 0c4378ee77dafc8a 113 113 +ActionDefinition isIndividual 7fcc089af57b2988 113 3 +ActionDefinition isLibraryElement db5948bc0fb78dad 113 0 +ActionDefinition isSufficient db5948bc0fb78dad 113 0 +ActionDefinition isVariation e7bedd97fe920a22 113 1 +ActionDefinition member 1de3ce87fae09ba6 113 86 +ActionDefinition membership e6476ae959187097 113 86 +ActionDefinition multiplicity ba991553c6bd9f9f 113 0 +ActionDefinition name de3a097cd6ec96ae 113 113 +ActionDefinition output e3a57fad36e0ebae 113 66 +ActionDefinition ownedAction 4672b5af238d430d 113 16 +ActionDefinition ownedAllocation f91e4d450b44243e 113 0 +ActionDefinition ownedAnalysisCase f91e4d450b44243e 113 0 +ActionDefinition ownedAnnotation f91e4d450b44243e 113 0 +ActionDefinition ownedAttribute 5741f87a6989e09e 113 3 +ActionDefinition ownedCalculation f91e4d450b44243e 113 0 +ActionDefinition ownedCase f91e4d450b44243e 113 0 +ActionDefinition ownedConcern f91e4d450b44243e 113 0 +ActionDefinition ownedConjugator ba991553c6bd9f9f 113 0 +ActionDefinition ownedConnection 8c4850940562683e 113 11 +ActionDefinition ownedConstraint 2ee5ea93800fa966 113 3 +ActionDefinition ownedDifferencing f91e4d450b44243e 113 0 +ActionDefinition ownedDisjoining f91e4d450b44243e 113 0 +ActionDefinition ownedElement 4d2ee41ac99bd9fb 113 86 +ActionDefinition ownedEndFeature f91e4d450b44243e 113 0 +ActionDefinition ownedEnumeration f91e4d450b44243e 113 0 +ActionDefinition ownedFeature 96192dfc9055e223 113 85 +ActionDefinition ownedFeatureMembership 1c52452c81301b43 113 85 +ActionDefinition ownedFlow f91e4d450b44243e 113 0 +ActionDefinition ownedImport f91e4d450b44243e 113 0 +ActionDefinition ownedInterface 77b7d5c5069995a3 113 62 +ActionDefinition ownedIntersecting f91e4d450b44243e 113 0 +ActionDefinition ownedItem d59a676bfdd1e803 113 12 +ActionDefinition ownedMember 4d2ee41ac99bd9fb 113 86 +ActionDefinition ownedMembership e6476ae959187097 113 86 +ActionDefinition ownedMetadata f91e4d450b44243e 113 0 +ActionDefinition ownedOccurrence ec830130f61a9d56 113 28 +ActionDefinition ownedPart f91e4d450b44243e 113 0 +ActionDefinition ownedPort f91e4d450b44243e 113 0 +ActionDefinition ownedReference 77b7d5c5069995a3 113 62 +ActionDefinition ownedRelationship ceb9f1322df885d3 113 113 +ActionDefinition ownedRendering f91e4d450b44243e 113 0 +ActionDefinition ownedRequirement f91e4d450b44243e 113 0 +ActionDefinition ownedSpecialization 4777674341fb00a4 113 113 +ActionDefinition ownedState f91e4d450b44243e 113 0 +ActionDefinition ownedSubclassification 4777674341fb00a4 113 113 +ActionDefinition ownedTransition 6e28cf0f774a0d05 113 2 +ActionDefinition ownedUnioning f91e4d450b44243e 113 0 +ActionDefinition ownedUsage 96192dfc9055e223 113 85 +ActionDefinition ownedUseCase f91e4d450b44243e 113 0 +ActionDefinition ownedVerificationCase f91e4d450b44243e 113 0 +ActionDefinition ownedView f91e4d450b44243e 113 0 +ActionDefinition ownedViewpoint f91e4d450b44243e 113 0 +ActionDefinition owner 4e515dd02577cd74 113 113 +ActionDefinition owningMembership 38bc91578eb9585c 113 113 +ActionDefinition owningNamespace 4e515dd02577cd74 113 113 +ActionDefinition owningRelationship 38bc91578eb9585c 113 113 +ActionDefinition parameter d93fb682aeefb019 113 74 +ActionDefinition qualifiedName 235818d9a153b356 113 113 +ActionDefinition shortName ba991553c6bd9f9f 113 0 +ActionDefinition step 7c3a52fd9858c835 113 19 +ActionDefinition textualRepresentation f6396aaddf8f0a8d 113 2 +ActionDefinition unioningType f91e4d450b44243e 113 0 +ActionDefinition usage 96192dfc9055e223 113 85 +ActionDefinition variant 5d2aae8f595276d6 113 1 +ActionDefinition variantMembership 197e9c9236c1a76e 113 1 +ActionUsage actionDefinition d1dcbfc123d6af73 252 114 +ActionUsage aliasIds 83160429bf7fbfbb 252 0 +ActionUsage behavior d1dcbfc123d6af73 252 114 +ActionUsage chainingFeature 83160429bf7fbfbb 252 0 +ActionUsage crossFeature f51afd36e7d18cd1 252 0 +ActionUsage declaredName fc6fab781bb12cb8 252 222 +ActionUsage declaredShortName f51afd36e7d18cd1 252 0 +ActionUsage definition 16b4c0f788ec246f 252 114 +ActionUsage differencingType 83160429bf7fbfbb 252 0 +ActionUsage directedFeature 984070b5590800b5 252 95 +ActionUsage directedUsage 984070b5590800b5 252 95 +ActionUsage direction f51afd36e7d18cd1 252 0 +ActionUsage documentation 83160429bf7fbfbb 252 0 +ActionUsage elementId 9009790e3e773480 252 252 +ActionUsage endFeature 83160429bf7fbfbb 252 0 +ActionUsage endOwningType f51afd36e7d18cd1 252 0 +ActionUsage feature eb289383916ec498 252 144 +ActionUsage featureMembership 020fd8f84187bb66 252 144 +ActionUsage featureTarget 82e303efc407c18e 252 0 +ActionUsage featuringType 83160429bf7fbfbb 252 0 +ActionUsage importedMembership 83160429bf7fbfbb 252 0 +ActionUsage individualDefinition 35d04ecbd9eb010d 252 3 +ActionUsage inheritedFeature 83160429bf7fbfbb 252 0 +ActionUsage inheritedMembership 83160429bf7fbfbb 252 0 +ActionUsage input a13ec9c222a737c7 252 80 +ActionUsage intersectingType 83160429bf7fbfbb 252 0 +ActionUsage isAbstract 083b7be0c93623d5 252 2 +ActionUsage isComposite 54d9e3220d27623e 252 191 +ActionUsage isConjugated 200b57d76fa28783 252 0 +ActionUsage isConstant 146cf7b59cebe583 252 0 +ActionUsage isDerived 146cf7b59cebe583 252 0 +ActionUsage isEnd 146cf7b59cebe583 252 0 +ActionUsage isImpliedIncluded 86cdb2c993d1cabf 252 252 +ActionUsage isIndividual 24278700b413069c 252 3 +ActionUsage isLibraryElement 563a73522982ad0d 252 2 +ActionUsage isOrdered 146cf7b59cebe583 252 0 +ActionUsage isPortion f51afd36e7d18cd1 252 0 +ActionUsage isReference 4660c75d23964e04 252 61 +ActionUsage isSufficient f51afd36e7d18cd1 252 0 +ActionUsage isUnique da6dd5bddb3d9215 252 242 +ActionUsage isVariable f51afd36e7d18cd1 252 0 +ActionUsage isVariation 13d9dc029becc5d5 252 2 +ActionUsage mayTimeVary f51afd36e7d18cd1 252 0 +ActionUsage member 112c198fdecbe254 252 165 +ActionUsage membership bb37e91b3efc40ab 252 165 +ActionUsage multiplicity 7f95178979e66231 252 12 +ActionUsage name 943d7f61fc861a67 252 226 +ActionUsage nestedAction 7da38668454a6bb6 252 59 +ActionUsage nestedAllocation 83160429bf7fbfbb 252 0 +ActionUsage nestedAnalysisCase 83160429bf7fbfbb 252 0 +ActionUsage nestedAttribute a4149e61796f7174 252 7 +ActionUsage nestedCalculation dad4b2ee7d7a6557 252 4 +ActionUsage nestedCase 83160429bf7fbfbb 252 0 +ActionUsage nestedConcern 83160429bf7fbfbb 252 0 +ActionUsage nestedConnection 818dd9fde7053e3e 252 26 +ActionUsage nestedConstraint f298e8c3b6def7ad 252 3 +ActionUsage nestedEnumeration 83160429bf7fbfbb 252 0 +ActionUsage nestedFlow 83160429bf7fbfbb 252 0 +ActionUsage nestedInterface a4520ff83a825556 252 72 +ActionUsage nestedItem 13b0511bcd6ed6af 252 27 +ActionUsage nestedMetadata 83160429bf7fbfbb 252 0 +ActionUsage nestedOccurrence fa2f7954e6291e9b 252 85 +ActionUsage nestedPart 20062b2493446c6c 252 3 +ActionUsage nestedPort 83160429bf7fbfbb 252 0 +ActionUsage nestedReference a4520ff83a825556 252 72 +ActionUsage nestedRendering 83160429bf7fbfbb 252 0 +ActionUsage nestedRequirement 83160429bf7fbfbb 252 0 +ActionUsage nestedState 0dfd08cd13850cb3 252 1 +ActionUsage nestedTransition 55acdd15a8e5a33c 252 3 +ActionUsage nestedUsage eb289383916ec498 252 144 +ActionUsage nestedUseCase 83160429bf7fbfbb 252 0 +ActionUsage nestedVerificationCase 83160429bf7fbfbb 252 0 +ActionUsage nestedView 83160429bf7fbfbb 252 0 +ActionUsage nestedViewpoint 83160429bf7fbfbb 252 0 +ActionUsage occurrenceDefinition 37be466277a0118d 252 114 +ActionUsage output e70d85be853a9fa9 252 79 +ActionUsage ownedAnnotation 83160429bf7fbfbb 252 0 +ActionUsage ownedConjugator f51afd36e7d18cd1 252 0 +ActionUsage ownedCrossSubsetting f51afd36e7d18cd1 252 0 +ActionUsage ownedDifferencing 83160429bf7fbfbb 252 0 +ActionUsage ownedDisjoining 83160429bf7fbfbb 252 0 +ActionUsage ownedElement 2a79ad2ae05caaf1 252 165 +ActionUsage ownedEndFeature 83160429bf7fbfbb 252 0 +ActionUsage ownedFeature eb289383916ec498 252 144 +ActionUsage ownedFeatureChaining 83160429bf7fbfbb 252 0 +ActionUsage ownedFeatureInverting 83160429bf7fbfbb 252 0 +ActionUsage ownedFeatureMembership 020fd8f84187bb66 252 144 +ActionUsage ownedImport bdf9a5be70fd2068 252 1 +ActionUsage ownedIntersecting 83160429bf7fbfbb 252 0 +ActionUsage ownedMember 2a79ad2ae05caaf1 252 165 +ActionUsage ownedMembership bb37e91b3efc40ab 252 165 +ActionUsage ownedRedefinition 57df046aa74e6632 252 6 +ActionUsage ownedReferenceSubsetting f51afd36e7d18cd1 252 0 +ActionUsage ownedRelationship 49546c9107034a44 252 252 +ActionUsage ownedSpecialization 912d1948edc6bd4b 252 252 +ActionUsage ownedSubsetting 746c4c01d514c12b 252 252 +ActionUsage ownedTypeFeaturing 83160429bf7fbfbb 252 0 +ActionUsage ownedTyping 17f41eb886cb956f 252 102 +ActionUsage ownedUnioning 83160429bf7fbfbb 252 0 +ActionUsage owner d9dae7f2d944c25a 252 252 +ActionUsage owningDefinition eb1d0cf37a948b84 252 53 +ActionUsage owningFeatureMembership 906c33cad89fe38b 252 193 +ActionUsage owningMembership 71483fbb7a168145 252 252 +ActionUsage owningNamespace d9dae7f2d944c25a 252 252 +ActionUsage owningRelationship 71483fbb7a168145 252 252 +ActionUsage owningType 48bf75611c553958 252 193 +ActionUsage owningUsage 52bd65a489923aa5 252 140 +ActionUsage parameter 984070b5590800b5 252 95 +ActionUsage portionKind f51afd36e7d18cd1 252 0 +ActionUsage qualifiedName 97080c90afcef6cd 252 215 +ActionUsage shortName f51afd36e7d18cd1 252 0 +ActionUsage textualRepresentation 83160429bf7fbfbb 252 0 +ActionUsage type 16b4c0f788ec246f 252 114 +ActionUsage unioningType 83160429bf7fbfbb 252 0 +ActionUsage usage eb289383916ec498 252 144 +ActionUsage variant 3e70d0a79ab9ee65 252 2 +ActionUsage variantMembership d1444c88d7910dc6 252 2 +ActorMembership aliasIds 2015dc31df5c1a63 42 0 +ActorMembership declaredName a8e073a6e5714a5f 42 0 +ActorMembership declaredShortName a8e073a6e5714a5f 42 0 +ActorMembership documentation 2015dc31df5c1a63 42 0 +ActorMembership elementId 3731236159592990 42 42 +ActorMembership isImplied 2d96ccf25a18a4d5 42 0 +ActorMembership isImpliedIncluded daf9c52a8199ddaf 42 42 +ActorMembership isLibraryElement 2d96ccf25a18a4d5 42 0 +ActorMembership memberElement ab958c50f5cc62dd 42 42 +ActorMembership memberElementId cfca08d825eb09a9 42 42 +ActorMembership memberName f9c9725f4fd405c2 42 42 +ActorMembership memberShortName a8e073a6e5714a5f 42 0 +ActorMembership membershipOwningNamespace a510c1749affc4e8 42 42 +ActorMembership name a8e073a6e5714a5f 42 0 +ActorMembership ownedActorParameter ab958c50f5cc62dd 42 42 +ActorMembership ownedAnnotation 2015dc31df5c1a63 42 0 +ActorMembership ownedElement 2015dc31df5c1a63 42 0 +ActorMembership ownedMemberElement ab958c50f5cc62dd 42 42 +ActorMembership ownedMemberElementId cfca08d825eb09a9 42 42 +ActorMembership ownedMemberFeature ab958c50f5cc62dd 42 42 +ActorMembership ownedMemberName f9c9725f4fd405c2 42 42 +ActorMembership ownedMemberParameter ab958c50f5cc62dd 42 42 +ActorMembership ownedMemberShortName a8e073a6e5714a5f 42 0 +ActorMembership ownedRelatedElement 46b4336f64fc1e79 42 42 +ActorMembership ownedRelationship 2015dc31df5c1a63 42 0 +ActorMembership owner a8e073a6e5714a5f 42 0 +ActorMembership owningMembership a8e073a6e5714a5f 42 0 +ActorMembership owningNamespace a8e073a6e5714a5f 42 0 +ActorMembership owningRelatedElement a510c1749affc4e8 42 42 +ActorMembership owningRelationship a8e073a6e5714a5f 42 0 +ActorMembership owningType a510c1749affc4e8 42 42 +ActorMembership qualifiedName a8e073a6e5714a5f 42 0 +ActorMembership relatedElement a6ecffd232ba4e40 42 42 +ActorMembership shortName a8e073a6e5714a5f 42 0 +ActorMembership source 1b950a74b5fdd8d2 42 42 +ActorMembership target 46b4336f64fc1e79 42 42 +ActorMembership textualRepresentation 2015dc31df5c1a63 42 0 +ActorMembership visibility ba76e69ea5607f2b 42 42 +AllocationDefinition aliasIds 5e87d47a36afcc57 5 0 +AllocationDefinition allocation 5e87d47a36afcc57 5 0 +AllocationDefinition associationEnd 072eaf52bb8a9218 5 4 +AllocationDefinition connectionEnd 072eaf52bb8a9218 5 4 +AllocationDefinition declaredName 675df19e933af0d8 5 5 +AllocationDefinition declaredShortName 838b8d5bc57d4c8a 5 0 +AllocationDefinition differencingType 5e87d47a36afcc57 5 0 +AllocationDefinition directedFeature 5e87d47a36afcc57 5 0 +AllocationDefinition directedUsage 5e87d47a36afcc57 5 0 +AllocationDefinition documentation 5e87d47a36afcc57 5 0 +AllocationDefinition elementId 1bd531f28a1ba314 5 5 +AllocationDefinition endFeature 072eaf52bb8a9218 5 4 +AllocationDefinition feature 072eaf52bb8a9218 5 4 +AllocationDefinition featureMembership e78dae633ba12e98 5 4 +AllocationDefinition importedMembership 5e87d47a36afcc57 5 0 +AllocationDefinition inheritedFeature 5e87d47a36afcc57 5 0 +AllocationDefinition inheritedMembership 5e87d47a36afcc57 5 0 +AllocationDefinition input 5e87d47a36afcc57 5 0 +AllocationDefinition intersectingType 5e87d47a36afcc57 5 0 +AllocationDefinition isAbstract 6f10b7f29ce940b6 5 0 +AllocationDefinition isConjugated 6f10b7f29ce940b6 5 0 +AllocationDefinition isImplied 838b8d5bc57d4c8a 5 0 +AllocationDefinition isImpliedIncluded 249c0b5e785db74f 5 5 +AllocationDefinition isIndividual 838b8d5bc57d4c8a 5 0 +AllocationDefinition isLibraryElement 6f10b7f29ce940b6 5 0 +AllocationDefinition isSufficient 249c0b5e785db74f 5 5 +AllocationDefinition isVariation 6f10b7f29ce940b6 5 0 +AllocationDefinition member 072eaf52bb8a9218 5 4 +AllocationDefinition membership e78dae633ba12e98 5 4 +AllocationDefinition multiplicity 838b8d5bc57d4c8a 5 0 +AllocationDefinition name 675df19e933af0d8 5 5 +AllocationDefinition output 5e87d47a36afcc57 5 0 +AllocationDefinition ownedAction 5e87d47a36afcc57 5 0 +AllocationDefinition ownedAllocation 5e87d47a36afcc57 5 0 +AllocationDefinition ownedAnalysisCase 5e87d47a36afcc57 5 0 +AllocationDefinition ownedAnnotation 5e87d47a36afcc57 5 0 +AllocationDefinition ownedAttribute 5e87d47a36afcc57 5 0 +AllocationDefinition ownedCalculation 5e87d47a36afcc57 5 0 +AllocationDefinition ownedCase 5e87d47a36afcc57 5 0 +AllocationDefinition ownedConcern 5e87d47a36afcc57 5 0 +AllocationDefinition ownedConjugator 838b8d5bc57d4c8a 5 0 +AllocationDefinition ownedConnection 5e87d47a36afcc57 5 0 +AllocationDefinition ownedConstraint 5e87d47a36afcc57 5 0 +AllocationDefinition ownedDifferencing 5e87d47a36afcc57 5 0 +AllocationDefinition ownedDisjoining 5e87d47a36afcc57 5 0 +AllocationDefinition ownedElement 072eaf52bb8a9218 5 4 +AllocationDefinition ownedEndFeature 072eaf52bb8a9218 5 4 +AllocationDefinition ownedEnumeration 5e87d47a36afcc57 5 0 +AllocationDefinition ownedFeature 072eaf52bb8a9218 5 4 +AllocationDefinition ownedFeatureMembership e78dae633ba12e98 5 4 +AllocationDefinition ownedFlow 5e87d47a36afcc57 5 0 +AllocationDefinition ownedImport 5e87d47a36afcc57 5 0 +AllocationDefinition ownedInterface c2cc5397928e82ed 5 3 +AllocationDefinition ownedIntersecting 5e87d47a36afcc57 5 0 +AllocationDefinition ownedItem 5e87d47a36afcc57 5 0 +AllocationDefinition ownedMember 072eaf52bb8a9218 5 4 +AllocationDefinition ownedMembership e78dae633ba12e98 5 4 +AllocationDefinition ownedMetadata 5e87d47a36afcc57 5 0 +AllocationDefinition ownedOccurrence 5e87d47a36afcc57 5 0 +AllocationDefinition ownedPart 5e87d47a36afcc57 5 0 +AllocationDefinition ownedPort 5e87d47a36afcc57 5 0 +AllocationDefinition ownedReference c2cc5397928e82ed 5 3 +AllocationDefinition ownedRelatedElement 5e87d47a36afcc57 5 0 +AllocationDefinition ownedRelationship cd54d85964c25db5 5 5 +AllocationDefinition ownedRendering 5e87d47a36afcc57 5 0 +AllocationDefinition ownedRequirement 5e87d47a36afcc57 5 0 +AllocationDefinition ownedSpecialization 5bbfae42f427911e 5 5 +AllocationDefinition ownedState 5e87d47a36afcc57 5 0 +AllocationDefinition ownedSubclassification 5bbfae42f427911e 5 5 +AllocationDefinition ownedTransition 5e87d47a36afcc57 5 0 +AllocationDefinition ownedUnioning 5e87d47a36afcc57 5 0 +AllocationDefinition ownedUsage 072eaf52bb8a9218 5 4 +AllocationDefinition ownedUseCase 5e87d47a36afcc57 5 0 +AllocationDefinition ownedVerificationCase 5e87d47a36afcc57 5 0 +AllocationDefinition ownedView 5e87d47a36afcc57 5 0 +AllocationDefinition ownedViewpoint 5e87d47a36afcc57 5 0 +AllocationDefinition owner f018298f3fb0b9e6 5 5 +AllocationDefinition owningMembership 9cf74b205b75c867 5 5 +AllocationDefinition owningNamespace f018298f3fb0b9e6 5 5 +AllocationDefinition owningRelatedElement 838b8d5bc57d4c8a 5 0 +AllocationDefinition owningRelationship 9cf74b205b75c867 5 5 +AllocationDefinition qualifiedName 184ed1d81bd1f440 5 5 +AllocationDefinition relatedElement 5e87d47a36afcc57 5 0 +AllocationDefinition relatedType 3182a210a3c21131 5 3 +AllocationDefinition shortName 838b8d5bc57d4c8a 5 0 +AllocationDefinition source 5e87d47a36afcc57 5 0 +AllocationDefinition sourceType 21444ccd9d49994f 5 3 +AllocationDefinition target 5e87d47a36afcc57 5 0 +AllocationDefinition targetType d71f9421cc75be63 5 3 +AllocationDefinition textualRepresentation 5e87d47a36afcc57 5 0 +AllocationDefinition unioningType 5e87d47a36afcc57 5 0 +AllocationDefinition usage 072eaf52bb8a9218 5 4 +AllocationDefinition variant 5e87d47a36afcc57 5 0 +AllocationDefinition variantMembership 5e87d47a36afcc57 5 0 +AllocationUsage aliasIds 1a80ec4915f6f24a 18 0 +AllocationUsage allocationDefinition 5057165c7ff00c75 18 5 +AllocationUsage association 5057165c7ff00c75 18 5 +AllocationUsage chainingFeature 1a80ec4915f6f24a 18 0 +AllocationUsage connectionDefinition 5057165c7ff00c75 18 5 +AllocationUsage connectorEnd b898d5564b66d43a 18 18 +AllocationUsage crossFeature dfdbdb5537dcef4c 18 0 +AllocationUsage declaredName f3c0f19c38974a19 18 5 +AllocationUsage declaredShortName dfdbdb5537dcef4c 18 0 +AllocationUsage defaultFeaturingType 440c1a657c99f565 18 3 +AllocationUsage definition 5057165c7ff00c75 18 5 +AllocationUsage differencingType 1a80ec4915f6f24a 18 0 +AllocationUsage directedFeature 1a80ec4915f6f24a 18 0 +AllocationUsage directedUsage 1a80ec4915f6f24a 18 0 +AllocationUsage direction dfdbdb5537dcef4c 18 0 +AllocationUsage documentation 1a80ec4915f6f24a 18 0 +AllocationUsage elementId ea4c268efd7ec8a0 18 18 +AllocationUsage endFeature b898d5564b66d43a 18 18 +AllocationUsage endOwningType dfdbdb5537dcef4c 18 0 +AllocationUsage feature d00f95cdf22e673e 18 18 +AllocationUsage featureMembership 7bdaeb122c7e8a2d 18 18 +AllocationUsage featureTarget 4f2223ee8661c4ea 18 0 +AllocationUsage featuringType 1a80ec4915f6f24a 18 0 +AllocationUsage importedMembership 1a80ec4915f6f24a 18 0 +AllocationUsage individualDefinition dfdbdb5537dcef4c 18 0 +AllocationUsage inheritedFeature 1a80ec4915f6f24a 18 0 +AllocationUsage inheritedMembership 1a80ec4915f6f24a 18 0 +AllocationUsage input 1a80ec4915f6f24a 18 0 +AllocationUsage intersectingType 1a80ec4915f6f24a 18 0 +AllocationUsage isAbstract 69a8546c36895908 18 0 +AllocationUsage isComposite b5a81140110b039a 18 10 +AllocationUsage isConjugated 69a8546c36895908 18 0 +AllocationUsage isConstant 69a8546c36895908 18 0 +AllocationUsage isDerived 69a8546c36895908 18 0 +AllocationUsage isEnd 69a8546c36895908 18 0 +AllocationUsage isImplied dfdbdb5537dcef4c 18 0 +AllocationUsage isImpliedIncluded 7b67c269ff221dea 18 18 +AllocationUsage isIndividual dfdbdb5537dcef4c 18 0 +AllocationUsage isLibraryElement 69a8546c36895908 18 0 +AllocationUsage isOrdered 69a8546c36895908 18 0 +AllocationUsage isPortion dfdbdb5537dcef4c 18 0 +AllocationUsage isReference 2f68059624a07358 18 8 +AllocationUsage isSufficient dfdbdb5537dcef4c 18 0 +AllocationUsage isUnique 7b67c269ff221dea 18 18 +AllocationUsage isVariable dfdbdb5537dcef4c 18 0 +AllocationUsage isVariation 69a8546c36895908 18 0 +AllocationUsage itemDefinition 5057165c7ff00c75 18 5 +AllocationUsage mayTimeVary dfdbdb5537dcef4c 18 0 +AllocationUsage member d00f95cdf22e673e 18 18 +AllocationUsage membership 7bdaeb122c7e8a2d 18 18 +AllocationUsage multiplicity dfdbdb5537dcef4c 18 0 +AllocationUsage name f3c0f19c38974a19 18 5 +AllocationUsage nestedAction 1a80ec4915f6f24a 18 0 +AllocationUsage nestedAllocation 4ccc42c59a284210 18 6 +AllocationUsage nestedAnalysisCase 1a80ec4915f6f24a 18 0 +AllocationUsage nestedAttribute 1a80ec4915f6f24a 18 0 +AllocationUsage nestedCalculation 1a80ec4915f6f24a 18 0 +AllocationUsage nestedCase 1a80ec4915f6f24a 18 0 +AllocationUsage nestedConcern 1a80ec4915f6f24a 18 0 +AllocationUsage nestedConnection 4ccc42c59a284210 18 6 +AllocationUsage nestedConstraint 1a80ec4915f6f24a 18 0 +AllocationUsage nestedEnumeration 1a80ec4915f6f24a 18 0 +AllocationUsage nestedFlow 1a80ec4915f6f24a 18 0 +AllocationUsage nestedInterface b898d5564b66d43a 18 18 +AllocationUsage nestedItem 4ccc42c59a284210 18 6 +AllocationUsage nestedMetadata 1a80ec4915f6f24a 18 0 +AllocationUsage nestedOccurrence 4ccc42c59a284210 18 6 +AllocationUsage nestedPart 4ccc42c59a284210 18 6 +AllocationUsage nestedPort 1a80ec4915f6f24a 18 0 +AllocationUsage nestedReference b898d5564b66d43a 18 18 +AllocationUsage nestedRendering 1a80ec4915f6f24a 18 0 +AllocationUsage nestedRequirement 1a80ec4915f6f24a 18 0 +AllocationUsage nestedState 1a80ec4915f6f24a 18 0 +AllocationUsage nestedTransition 1a80ec4915f6f24a 18 0 +AllocationUsage nestedUsage d00f95cdf22e673e 18 18 +AllocationUsage nestedUseCase 1a80ec4915f6f24a 18 0 +AllocationUsage nestedVerificationCase 1a80ec4915f6f24a 18 0 +AllocationUsage nestedView 1a80ec4915f6f24a 18 0 +AllocationUsage nestedViewpoint 1a80ec4915f6f24a 18 0 +AllocationUsage occurrenceDefinition 5057165c7ff00c75 18 5 +AllocationUsage output 1a80ec4915f6f24a 18 0 +AllocationUsage ownedAnnotation 1a80ec4915f6f24a 18 0 +AllocationUsage ownedConjugator dfdbdb5537dcef4c 18 0 +AllocationUsage ownedCrossSubsetting dfdbdb5537dcef4c 18 0 +AllocationUsage ownedDifferencing 1a80ec4915f6f24a 18 0 +AllocationUsage ownedDisjoining 1a80ec4915f6f24a 18 0 +AllocationUsage ownedElement d00f95cdf22e673e 18 18 +AllocationUsage ownedEndFeature b898d5564b66d43a 18 18 +AllocationUsage ownedFeature d00f95cdf22e673e 18 18 +AllocationUsage ownedFeatureChaining 1a80ec4915f6f24a 18 0 +AllocationUsage ownedFeatureInverting 1a80ec4915f6f24a 18 0 +AllocationUsage ownedFeatureMembership 7bdaeb122c7e8a2d 18 18 +AllocationUsage ownedImport 1a80ec4915f6f24a 18 0 +AllocationUsage ownedIntersecting 1a80ec4915f6f24a 18 0 +AllocationUsage ownedMember d00f95cdf22e673e 18 18 +AllocationUsage ownedMembership 7bdaeb122c7e8a2d 18 18 +AllocationUsage ownedRedefinition 1a80ec4915f6f24a 18 0 +AllocationUsage ownedReferenceSubsetting dfdbdb5537dcef4c 18 0 +AllocationUsage ownedRelatedElement 1a80ec4915f6f24a 18 0 +AllocationUsage ownedRelationship 6889275c01b54e17 18 18 +AllocationUsage ownedSpecialization d75161ad409504cc 18 18 +AllocationUsage ownedSubsetting d465f9956ecf8c3d 18 18 +AllocationUsage ownedTypeFeaturing 1a80ec4915f6f24a 18 0 +AllocationUsage ownedTyping ea6b646fa719a329 18 5 +AllocationUsage ownedUnioning 1a80ec4915f6f24a 18 0 +AllocationUsage owner d664f9e9aaee4f1a 18 18 +AllocationUsage owningDefinition dfdbdb5537dcef4c 18 0 +AllocationUsage owningFeatureMembership 06631bb0e58335aa 18 10 +AllocationUsage owningMembership 3ead58887a29dc8e 18 18 +AllocationUsage owningNamespace d664f9e9aaee4f1a 18 18 +AllocationUsage owningRelatedElement dfdbdb5537dcef4c 18 0 +AllocationUsage owningRelationship 3ead58887a29dc8e 18 18 +AllocationUsage owningType 297987131265b56e 18 10 +AllocationUsage owningUsage 297987131265b56e 18 10 +AllocationUsage partDefinition 5057165c7ff00c75 18 5 +AllocationUsage portionKind dfdbdb5537dcef4c 18 0 +AllocationUsage qualifiedName 012f0278028099f2 18 5 +AllocationUsage relatedElement 1a80ec4915f6f24a 18 0 +AllocationUsage relatedFeature 7d853908124f8b08 18 18 +AllocationUsage shortName dfdbdb5537dcef4c 18 0 +AllocationUsage source 1a80ec4915f6f24a 18 0 +AllocationUsage sourceFeature 31e15f6cb0019203 18 18 +AllocationUsage target 1a80ec4915f6f24a 18 0 +AllocationUsage targetFeature 7fa5b23c42cdace3 18 18 +AllocationUsage textualRepresentation 1a80ec4915f6f24a 18 0 +AllocationUsage type 5057165c7ff00c75 18 5 +AllocationUsage unioningType 1a80ec4915f6f24a 18 0 +AllocationUsage usage d00f95cdf22e673e 18 18 +AllocationUsage variant 1a80ec4915f6f24a 18 0 +AllocationUsage variantMembership 1a80ec4915f6f24a 18 0 +AnalysisCaseDefinition action 63b88e288e63d28e 14 7 +AnalysisCaseDefinition actorParameter 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition aliasIds 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition calculation 1289481c8c0e170f 14 3 +AnalysisCaseDefinition declaredName 2b31c4650503be14 14 14 +AnalysisCaseDefinition declaredShortName 29f97aaefd0c0bb5 14 0 +AnalysisCaseDefinition differencingType 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition directedFeature 508490d58145ba8b 14 13 +AnalysisCaseDefinition directedUsage 508490d58145ba8b 14 13 +AnalysisCaseDefinition documentation 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition elementId 12c532322ea06f1c 14 14 +AnalysisCaseDefinition endFeature 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition expression b15122d4b179218b 14 11 +AnalysisCaseDefinition feature d21781cffa7fbdb1 14 13 +AnalysisCaseDefinition featureMembership c24a7eb347b66d28 14 13 +AnalysisCaseDefinition importedMembership 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition inheritedFeature 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition inheritedMembership 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition input a4a20aa4a4ccd4c6 14 10 +AnalysisCaseDefinition intersectingType 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition isAbstract 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition isConjugated 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition isImpliedIncluded dd78bbdb5d96cd39 14 14 +AnalysisCaseDefinition isIndividual 6168d302567fb9e6 14 1 +AnalysisCaseDefinition isLibraryElement 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition isModelLevelEvaluable 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition isSufficient 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition isVariation 92f0038f2d414a2b 14 0 +AnalysisCaseDefinition member d21781cffa7fbdb1 14 13 +AnalysisCaseDefinition membership c24a7eb347b66d28 14 13 +AnalysisCaseDefinition multiplicity 29f97aaefd0c0bb5 14 0 +AnalysisCaseDefinition name 2b31c4650503be14 14 14 +AnalysisCaseDefinition objectiveRequirement d97c994f54df1c71 14 10 +AnalysisCaseDefinition output 66261373750f540c 14 8 +AnalysisCaseDefinition ownedAction 63b88e288e63d28e 14 7 +AnalysisCaseDefinition ownedAllocation 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedAnalysisCase 7c15abfc4877205d 14 2 +AnalysisCaseDefinition ownedAnnotation 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedAttribute 35f2bbd58d87089b 14 3 +AnalysisCaseDefinition ownedCalculation 1289481c8c0e170f 14 3 +AnalysisCaseDefinition ownedCase 7c15abfc4877205d 14 2 +AnalysisCaseDefinition ownedConcern 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedConjugator 29f97aaefd0c0bb5 14 0 +AnalysisCaseDefinition ownedConnection 3cd94c914efcaa1f 14 1 +AnalysisCaseDefinition ownedConstraint a0a3aa89714e0255 14 11 +AnalysisCaseDefinition ownedDifferencing 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedDisjoining 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedElement d21781cffa7fbdb1 14 13 +AnalysisCaseDefinition ownedEndFeature 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedEnumeration 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedFeature d21781cffa7fbdb1 14 13 +AnalysisCaseDefinition ownedFeatureMembership c24a7eb347b66d28 14 13 +AnalysisCaseDefinition ownedFlow 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedImport 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedInterface c421afc4d457236e 14 13 +AnalysisCaseDefinition ownedIntersecting 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedItem 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedMember d21781cffa7fbdb1 14 13 +AnalysisCaseDefinition ownedMembership c24a7eb347b66d28 14 13 +AnalysisCaseDefinition ownedMetadata 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedOccurrence 5505aea049c6cd46 14 13 +AnalysisCaseDefinition ownedPart 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedPort 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedReference c421afc4d457236e 14 13 +AnalysisCaseDefinition ownedRelationship 251695a1a6e1375b 14 14 +AnalysisCaseDefinition ownedRendering 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedRequirement a0a3aa89714e0255 14 11 +AnalysisCaseDefinition ownedSpecialization 0ad4d14723310b7e 14 14 +AnalysisCaseDefinition ownedState 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedSubclassification 0ad4d14723310b7e 14 14 +AnalysisCaseDefinition ownedTransition 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedUnioning 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedUsage be73bc25995ec501 14 13 +AnalysisCaseDefinition ownedUseCase 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedVerificationCase 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedView 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition ownedViewpoint 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition owner 22082c281a2ef893 14 14 +AnalysisCaseDefinition owningMembership 08b790bc5bc70d4d 14 14 +AnalysisCaseDefinition owningNamespace 22082c281a2ef893 14 14 +AnalysisCaseDefinition owningRelationship 08b790bc5bc70d4d 14 14 +AnalysisCaseDefinition parameter 508490d58145ba8b 14 13 +AnalysisCaseDefinition qualifiedName 5f339036c9e35d17 14 14 +AnalysisCaseDefinition result 2fc0bb459a16b08b 14 8 +AnalysisCaseDefinition resultExpression 057f02aefe645e57 14 2 +AnalysisCaseDefinition shortName 29f97aaefd0c0bb5 14 0 +AnalysisCaseDefinition step 45c40391347a7f3a 14 13 +AnalysisCaseDefinition subjectParameter 05318e84159b8b4b 14 10 +AnalysisCaseDefinition textualRepresentation 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition unioningType 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition usage be73bc25995ec501 14 13 +AnalysisCaseDefinition variant 0e00f5209eb454f5 14 0 +AnalysisCaseDefinition variantMembership 0e00f5209eb454f5 14 0 +AnalysisCaseUsage actionDefinition b67087b47202d93c 26 24 +AnalysisCaseUsage actorParameter 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage aliasIds 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage analysisCaseDefinition 3058aaf7957ede3e 26 24 +AnalysisCaseUsage behavior b67087b47202d93c 26 24 +AnalysisCaseUsage calculationDefinition 3058aaf7957ede3e 26 24 +AnalysisCaseUsage caseDefinition 3058aaf7957ede3e 26 24 +AnalysisCaseUsage chainingFeature 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage crossFeature ad0012fb355bd2a8 26 0 +AnalysisCaseUsage declaredName e7cf3a5b4a4498ef 26 26 +AnalysisCaseUsage declaredShortName ad0012fb355bd2a8 26 0 +AnalysisCaseUsage definition b67087b47202d93c 26 24 +AnalysisCaseUsage differencingType 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage directedFeature c7b59f856bb9db27 26 25 +AnalysisCaseUsage directedUsage c7b59f856bb9db27 26 25 +AnalysisCaseUsage direction ad0012fb355bd2a8 26 0 +AnalysisCaseUsage documentation 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage elementId 201e7020e88259d4 26 26 +AnalysisCaseUsage endFeature 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage endOwningType ad0012fb355bd2a8 26 0 +AnalysisCaseUsage feature f7a49361925a8873 26 25 +AnalysisCaseUsage featureMembership 26e51d91465f7a29 26 25 +AnalysisCaseUsage featureTarget d2a7708b13e01efa 26 0 +AnalysisCaseUsage featuringType 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage function 3058aaf7957ede3e 26 24 +AnalysisCaseUsage importedMembership 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage individualDefinition 0fe16eae67414faf 26 1 +AnalysisCaseUsage inheritedFeature 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage inheritedMembership 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage input 47f2326b2d07129d 26 19 +AnalysisCaseUsage intersectingType 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage isAbstract b3509bc87b23b3a9 26 1 +AnalysisCaseUsage isComposite 304781a1847388ee 26 18 +AnalysisCaseUsage isConjugated 1b834b0924e74284 26 0 +AnalysisCaseUsage isConstant 1b834b0924e74284 26 0 +AnalysisCaseUsage isDerived 1b834b0924e74284 26 0 +AnalysisCaseUsage isEnd 1b834b0924e74284 26 0 +AnalysisCaseUsage isImpliedIncluded 454cd1c4865fec66 26 26 +AnalysisCaseUsage isIndividual 5a626ac698992e3b 26 1 +AnalysisCaseUsage isLibraryElement 1b834b0924e74284 26 0 +AnalysisCaseUsage isModelLevelEvaluable 1b834b0924e74284 26 0 +AnalysisCaseUsage isOrdered 1b834b0924e74284 26 0 +AnalysisCaseUsage isPortion ad0012fb355bd2a8 26 0 +AnalysisCaseUsage isReference 30889b2c26d3a5fc 26 8 +AnalysisCaseUsage isSufficient ad0012fb355bd2a8 26 0 +AnalysisCaseUsage isUnique 454cd1c4865fec66 26 26 +AnalysisCaseUsage isVariable ad0012fb355bd2a8 26 0 +AnalysisCaseUsage isVariation b3509bc87b23b3a9 26 1 +AnalysisCaseUsage mayTimeVary ad0012fb355bd2a8 26 0 +AnalysisCaseUsage member 7703fad0d54eaf01 26 25 +AnalysisCaseUsage membership 183f53ee90644c7b 26 25 +AnalysisCaseUsage multiplicity ad0012fb355bd2a8 26 0 +AnalysisCaseUsage name e7cf3a5b4a4498ef 26 26 +AnalysisCaseUsage nestedAction 384737c0cb13c451 26 7 +AnalysisCaseUsage nestedAllocation 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedAnalysisCase 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedAttribute ee9fa62760d2d824 26 3 +AnalysisCaseUsage nestedCalculation 6079b02a37b7a8f3 26 6 +AnalysisCaseUsage nestedCase 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedConcern 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedConnection 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedConstraint dbd47bb6c59cf66a 26 17 +AnalysisCaseUsage nestedEnumeration 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedFlow 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedInterface ee7f788f3fd049c1 26 25 +AnalysisCaseUsage nestedItem a8526d997688c315 26 4 +AnalysisCaseUsage nestedMetadata 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedOccurrence 7c5ae4341443ffb2 26 18 +AnalysisCaseUsage nestedPart a8526d997688c315 26 4 +AnalysisCaseUsage nestedPort 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedReference ee7f788f3fd049c1 26 25 +AnalysisCaseUsage nestedRendering 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedRequirement dbd47bb6c59cf66a 26 17 +AnalysisCaseUsage nestedState 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedTransition 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedUsage f7a49361925a8873 26 25 +AnalysisCaseUsage nestedUseCase 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedVerificationCase 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedView 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage nestedViewpoint 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage objectiveRequirement 89bec3d1bcd9e478 26 5 +AnalysisCaseUsage occurrenceDefinition b67087b47202d93c 26 24 +AnalysisCaseUsage output 66d5c0171d867182 26 14 +AnalysisCaseUsage ownedAnnotation 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedConjugator ad0012fb355bd2a8 26 0 +AnalysisCaseUsage ownedCrossSubsetting ad0012fb355bd2a8 26 0 +AnalysisCaseUsage ownedDifferencing 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedDisjoining 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedElement 7703fad0d54eaf01 26 25 +AnalysisCaseUsage ownedEndFeature 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedFeature f7a49361925a8873 26 25 +AnalysisCaseUsage ownedFeatureChaining 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedFeatureInverting 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedFeatureMembership 26e51d91465f7a29 26 25 +AnalysisCaseUsage ownedImport 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedIntersecting 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedMember 7703fad0d54eaf01 26 25 +AnalysisCaseUsage ownedMembership 183f53ee90644c7b 26 25 +AnalysisCaseUsage ownedRedefinition 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedReferenceSubsetting ad0012fb355bd2a8 26 0 +AnalysisCaseUsage ownedRelationship 5bc5acd50277f3e9 26 26 +AnalysisCaseUsage ownedSpecialization 11d956a4963ee80a 26 26 +AnalysisCaseUsage ownedSubsetting c0a52fe59b74cfd1 26 26 +AnalysisCaseUsage ownedTypeFeaturing 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage ownedTyping 4c60745f1b13e821 26 24 +AnalysisCaseUsage ownedUnioning 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage owner 6607b553c3934fb7 26 26 +AnalysisCaseUsage owningDefinition 58f71b144f38636f 26 2 +AnalysisCaseUsage owningFeatureMembership 99c2cc510a16dc4b 26 18 +AnalysisCaseUsage owningMembership b2385ac0a94ce934 26 26 +AnalysisCaseUsage owningNamespace 6607b553c3934fb7 26 26 +AnalysisCaseUsage owningRelationship b2385ac0a94ce934 26 26 +AnalysisCaseUsage owningType 263b253e9e5ade3c 26 18 +AnalysisCaseUsage owningUsage 7a441d25847e4d75 26 16 +AnalysisCaseUsage parameter c7b59f856bb9db27 26 25 +AnalysisCaseUsage portionKind ad0012fb355bd2a8 26 0 +AnalysisCaseUsage qualifiedName 3f1a19e25c60d89e 26 26 +AnalysisCaseUsage result 8d00f17f535afb2e 26 14 +AnalysisCaseUsage resultExpression ad0012fb355bd2a8 26 0 +AnalysisCaseUsage shortName ad0012fb355bd2a8 26 0 +AnalysisCaseUsage subjectParameter 9c5c232b7f57e6a3 26 19 +AnalysisCaseUsage textualRepresentation 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage type b67087b47202d93c 26 24 +AnalysisCaseUsage unioningType 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage usage f7a49361925a8873 26 25 +AnalysisCaseUsage variant 1102a4ab4ce3148e 26 0 +AnalysisCaseUsage variantMembership 1102a4ab4ce3148e 26 0 +Annotation aliasIds 5eeb7be6af9374f9 19 0 +Annotation annotatedElement 5ab977e657c2476f 19 19 +Annotation annotatingElement cd4307191d57aef8 19 19 +Annotation declaredName 50b8f2594b65ddf6 19 0 +Annotation declaredShortName 50b8f2594b65ddf6 19 0 +Annotation documentation 5eeb7be6af9374f9 19 0 +Annotation elementId eb62319fbf475b28 19 19 +Annotation isImplied a6630bce304e215a 19 0 +Annotation isImpliedIncluded 25ff8b5889e8d759 19 19 +Annotation isLibraryElement a6630bce304e215a 19 0 +Annotation name 50b8f2594b65ddf6 19 0 +Annotation ownedAnnotatingElement 50b8f2594b65ddf6 19 0 +Annotation ownedAnnotation 5eeb7be6af9374f9 19 0 +Annotation ownedElement 5eeb7be6af9374f9 19 0 +Annotation ownedRelatedElement 5eeb7be6af9374f9 19 0 +Annotation ownedRelationship 5eeb7be6af9374f9 19 0 +Annotation owner 50b8f2594b65ddf6 19 0 +Annotation owningAnnotatedElement 50b8f2594b65ddf6 19 0 +Annotation owningAnnotatingElement cd4307191d57aef8 19 19 +Annotation owningMembership 50b8f2594b65ddf6 19 0 +Annotation owningNamespace 50b8f2594b65ddf6 19 0 +Annotation owningRelatedElement cd4307191d57aef8 19 19 +Annotation owningRelationship 50b8f2594b65ddf6 19 0 +Annotation qualifiedName 50b8f2594b65ddf6 19 0 +Annotation relatedElement 723768554b16a056 19 19 +Annotation shortName 50b8f2594b65ddf6 19 0 +Annotation source 80aeeb693772f282 19 19 +Annotation target e2e8a46305442e3b 19 19 +Annotation textualRepresentation 5eeb7be6af9374f9 19 0 +AssertConstraintUsage aliasIds d5f0937b06325883 47 0 +AssertConstraintUsage assertedConstraint c7ebb531933a0f1f 47 4 +AssertConstraintUsage behavior 30ae6ce86f264287 47 13 +AssertConstraintUsage chainingFeature d5f0937b06325883 47 0 +AssertConstraintUsage constraintDefinition 1a6684e260c178f5 47 13 +AssertConstraintUsage crossFeature 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage declaredName 3933e561f7283dbd 47 18 +AssertConstraintUsage declaredShortName 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage definition 30ae6ce86f264287 47 13 +AssertConstraintUsage differencingType d5f0937b06325883 47 0 +AssertConstraintUsage directedFeature e3363dd79db64143 47 10 +AssertConstraintUsage directedUsage e3363dd79db64143 47 10 +AssertConstraintUsage direction 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage documentation 8f9dcf783d8f437b 47 4 +AssertConstraintUsage elementId 445f723a00316c9c 47 47 +AssertConstraintUsage endFeature d5f0937b06325883 47 0 +AssertConstraintUsage endOwningType 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage feature 73c07988908ae6aa 47 43 +AssertConstraintUsage featureMembership 49faabdfa8b8d906 47 43 +AssertConstraintUsage featureTarget 223b71405bcf3fc9 47 0 +AssertConstraintUsage featuringType d5f0937b06325883 47 0 +AssertConstraintUsage function 1a6684e260c178f5 47 13 +AssertConstraintUsage importedMembership d5f0937b06325883 47 0 +AssertConstraintUsage individualDefinition 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage inheritedFeature d5f0937b06325883 47 0 +AssertConstraintUsage inheritedMembership d5f0937b06325883 47 0 +AssertConstraintUsage input e3363dd79db64143 47 10 +AssertConstraintUsage intersectingType d5f0937b06325883 47 0 +AssertConstraintUsage isAbstract 0bf7902ed2437918 47 0 +AssertConstraintUsage isComposite bfec713989d5b186 47 46 +AssertConstraintUsage isConjugated 0bf7902ed2437918 47 0 +AssertConstraintUsage isConstant 0bf7902ed2437918 47 0 +AssertConstraintUsage isDerived 0bf7902ed2437918 47 0 +AssertConstraintUsage isEnd 0bf7902ed2437918 47 0 +AssertConstraintUsage isImpliedIncluded 8a26f22463eec8f3 47 47 +AssertConstraintUsage isIndividual 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage isLibraryElement 0bf7902ed2437918 47 0 +AssertConstraintUsage isModelLevelEvaluable 0bf7902ed2437918 47 0 +AssertConstraintUsage isNegated d6321119ac5c9085 47 1 +AssertConstraintUsage isOrdered 0bf7902ed2437918 47 0 +AssertConstraintUsage isPortion 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage isReference d6321119ac5c9085 47 1 +AssertConstraintUsage isSufficient 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage isUnique 8a26f22463eec8f3 47 47 +AssertConstraintUsage isVariable 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage isVariation 0bf7902ed2437918 47 0 +AssertConstraintUsage mayTimeVary 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage member d35557909a8d9ef6 47 46 +AssertConstraintUsage membership 0b1f140fe4fab2fc 47 46 +AssertConstraintUsage multiplicity 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage name 065fa588d8339169 47 22 +AssertConstraintUsage nestedAction d5f0937b06325883 47 0 +AssertConstraintUsage nestedAllocation d5f0937b06325883 47 0 +AssertConstraintUsage nestedAnalysisCase d5f0937b06325883 47 0 +AssertConstraintUsage nestedAttribute 20092cc3748b8bce 47 3 +AssertConstraintUsage nestedCalculation d5f0937b06325883 47 0 +AssertConstraintUsage nestedCase d5f0937b06325883 47 0 +AssertConstraintUsage nestedConcern d5f0937b06325883 47 0 +AssertConstraintUsage nestedConnection d5f0937b06325883 47 0 +AssertConstraintUsage nestedConstraint d5f0937b06325883 47 0 +AssertConstraintUsage nestedEnumeration d5f0937b06325883 47 0 +AssertConstraintUsage nestedFlow d5f0937b06325883 47 0 +AssertConstraintUsage nestedInterface a26623f81ef57b9e 47 11 +AssertConstraintUsage nestedItem d5f0937b06325883 47 0 +AssertConstraintUsage nestedMetadata d5f0937b06325883 47 0 +AssertConstraintUsage nestedOccurrence d5f0937b06325883 47 0 +AssertConstraintUsage nestedPart d5f0937b06325883 47 0 +AssertConstraintUsage nestedPort d5f0937b06325883 47 0 +AssertConstraintUsage nestedReference a26623f81ef57b9e 47 11 +AssertConstraintUsage nestedRendering d5f0937b06325883 47 0 +AssertConstraintUsage nestedRequirement d5f0937b06325883 47 0 +AssertConstraintUsage nestedState d5f0937b06325883 47 0 +AssertConstraintUsage nestedTransition d5f0937b06325883 47 0 +AssertConstraintUsage nestedUsage ec7ebd408d4eaee9 47 14 +AssertConstraintUsage nestedUseCase d5f0937b06325883 47 0 +AssertConstraintUsage nestedVerificationCase d5f0937b06325883 47 0 +AssertConstraintUsage nestedView d5f0937b06325883 47 0 +AssertConstraintUsage nestedViewpoint d5f0937b06325883 47 0 +AssertConstraintUsage occurrenceDefinition 30ae6ce86f264287 47 13 +AssertConstraintUsage output d5f0937b06325883 47 0 +AssertConstraintUsage ownedAnnotation d5f0937b06325883 47 0 +AssertConstraintUsage ownedConjugator 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage ownedCrossSubsetting 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage ownedDifferencing d5f0937b06325883 47 0 +AssertConstraintUsage ownedDisjoining d5f0937b06325883 47 0 +AssertConstraintUsage ownedElement d35557909a8d9ef6 47 46 +AssertConstraintUsage ownedEndFeature d5f0937b06325883 47 0 +AssertConstraintUsage ownedFeature 73c07988908ae6aa 47 43 +AssertConstraintUsage ownedFeatureChaining d5f0937b06325883 47 0 +AssertConstraintUsage ownedFeatureInverting d5f0937b06325883 47 0 +AssertConstraintUsage ownedFeatureMembership 49faabdfa8b8d906 47 43 +AssertConstraintUsage ownedImport d5f0937b06325883 47 0 +AssertConstraintUsage ownedIntersecting d5f0937b06325883 47 0 +AssertConstraintUsage ownedMember d35557909a8d9ef6 47 46 +AssertConstraintUsage ownedMembership 0b1f140fe4fab2fc 47 46 +AssertConstraintUsage ownedRedefinition d5f0937b06325883 47 0 +AssertConstraintUsage ownedReferenceSubsetting c54049138148793a 47 4 +AssertConstraintUsage ownedRelationship 0b792394529fad37 47 47 +AssertConstraintUsage ownedSpecialization 7e25f9c560cffce0 47 47 +AssertConstraintUsage ownedSubsetting 5df30f234034b6e8 47 47 +AssertConstraintUsage ownedTypeFeaturing d5f0937b06325883 47 0 +AssertConstraintUsage ownedTyping b93a8ffeaa33110d 47 10 +AssertConstraintUsage ownedUnioning d5f0937b06325883 47 0 +AssertConstraintUsage owner 03190308a2d6acee 47 47 +AssertConstraintUsage owningDefinition 910e66d804266ee7 47 19 +AssertConstraintUsage owningFeatureMembership dd03a72c1d448438 47 46 +AssertConstraintUsage owningMembership e3a1dd2a12531ac9 47 47 +AssertConstraintUsage owningNamespace 03190308a2d6acee 47 47 +AssertConstraintUsage owningRelationship e3a1dd2a12531ac9 47 47 +AssertConstraintUsage owningType b600a3af3598c83c 47 46 +AssertConstraintUsage owningUsage 82b2aaade93fcf89 47 27 +AssertConstraintUsage parameter e3363dd79db64143 47 10 +AssertConstraintUsage portionKind 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage predicate 1a6684e260c178f5 47 13 +AssertConstraintUsage qualifiedName 492d24f5a77cc852 47 22 +AssertConstraintUsage result 223b71405bcf3fc9 47 0 +AssertConstraintUsage shortName 5dc06dd6b7cd7634 47 0 +AssertConstraintUsage textualRepresentation 75ec53f86454bb13 47 1 +AssertConstraintUsage type 30ae6ce86f264287 47 13 +AssertConstraintUsage unioningType d5f0937b06325883 47 0 +AssertConstraintUsage usage ec7ebd408d4eaee9 47 14 +AssertConstraintUsage variant d5f0937b06325883 47 0 +AssertConstraintUsage variantMembership d5f0937b06325883 47 0 +AssignmentActionUsage actionDefinition 46d58560435835ff 27 0 +AssignmentActionUsage aliasIds 46d58560435835ff 27 0 +AssignmentActionUsage behavior 46d58560435835ff 27 0 +AssignmentActionUsage chainingFeature 46d58560435835ff 27 0 +AssignmentActionUsage crossFeature 9b268e46e142efe0 27 0 +AssignmentActionUsage declaredName 721e4f293dcc8de4 27 4 +AssignmentActionUsage declaredShortName 9b268e46e142efe0 27 0 +AssignmentActionUsage definition 46d58560435835ff 27 0 +AssignmentActionUsage differencingType 46d58560435835ff 27 0 +AssignmentActionUsage directedFeature d33c8ec8c06916dc 27 27 +AssignmentActionUsage directedUsage d33c8ec8c06916dc 27 27 +AssignmentActionUsage direction 9b268e46e142efe0 27 0 +AssignmentActionUsage documentation 46d58560435835ff 27 0 +AssignmentActionUsage elementId 7510436318f521c8 27 27 +AssignmentActionUsage endFeature 46d58560435835ff 27 0 +AssignmentActionUsage endOwningType 9b268e46e142efe0 27 0 +AssignmentActionUsage feature d33c8ec8c06916dc 27 27 +AssignmentActionUsage featureMembership f2c527fa068686c9 27 27 +AssignmentActionUsage featureTarget 3fb1e19259966791 27 0 +AssignmentActionUsage featuringType 46d58560435835ff 27 0 +AssignmentActionUsage importedMembership 46d58560435835ff 27 0 +AssignmentActionUsage individualDefinition 9b268e46e142efe0 27 0 +AssignmentActionUsage inheritedFeature 46d58560435835ff 27 0 +AssignmentActionUsage inheritedMembership 46d58560435835ff 27 0 +AssignmentActionUsage input d33c8ec8c06916dc 27 27 +AssignmentActionUsage intersectingType 46d58560435835ff 27 0 +AssignmentActionUsage isAbstract 322f626384f3b488 27 0 +AssignmentActionUsage isComposite 604b65ea72c551c7 27 27 +AssignmentActionUsage isConjugated 322f626384f3b488 27 0 +AssignmentActionUsage isConstant 322f626384f3b488 27 0 +AssignmentActionUsage isDerived 322f626384f3b488 27 0 +AssignmentActionUsage isEnd 322f626384f3b488 27 0 +AssignmentActionUsage isImpliedIncluded 604b65ea72c551c7 27 27 +AssignmentActionUsage isIndividual 9b268e46e142efe0 27 0 +AssignmentActionUsage isLibraryElement 322f626384f3b488 27 0 +AssignmentActionUsage isOrdered 322f626384f3b488 27 0 +AssignmentActionUsage isPortion 9b268e46e142efe0 27 0 +AssignmentActionUsage isReference 322f626384f3b488 27 0 +AssignmentActionUsage isSufficient 9b268e46e142efe0 27 0 +AssignmentActionUsage isUnique 604b65ea72c551c7 27 27 +AssignmentActionUsage isVariable 9b268e46e142efe0 27 0 +AssignmentActionUsage isVariation 322f626384f3b488 27 0 +AssignmentActionUsage mayTimeVary 9b268e46e142efe0 27 0 +AssignmentActionUsage member d33c8ec8c06916dc 27 27 +AssignmentActionUsage membership f2c527fa068686c9 27 27 +AssignmentActionUsage multiplicity 9b268e46e142efe0 27 0 +AssignmentActionUsage name 721e4f293dcc8de4 27 4 +AssignmentActionUsage nestedAction 46d58560435835ff 27 0 +AssignmentActionUsage nestedAllocation 46d58560435835ff 27 0 +AssignmentActionUsage nestedAnalysisCase 46d58560435835ff 27 0 +AssignmentActionUsage nestedAttribute 46d58560435835ff 27 0 +AssignmentActionUsage nestedCalculation 46d58560435835ff 27 0 +AssignmentActionUsage nestedCase 46d58560435835ff 27 0 +AssignmentActionUsage nestedConcern 46d58560435835ff 27 0 +AssignmentActionUsage nestedConnection 46d58560435835ff 27 0 +AssignmentActionUsage nestedConstraint 46d58560435835ff 27 0 +AssignmentActionUsage nestedEnumeration 46d58560435835ff 27 0 +AssignmentActionUsage nestedFlow 46d58560435835ff 27 0 +AssignmentActionUsage nestedInterface d33c8ec8c06916dc 27 27 +AssignmentActionUsage nestedItem 46d58560435835ff 27 0 +AssignmentActionUsage nestedMetadata 46d58560435835ff 27 0 +AssignmentActionUsage nestedOccurrence 46d58560435835ff 27 0 +AssignmentActionUsage nestedPart 46d58560435835ff 27 0 +AssignmentActionUsage nestedPort 46d58560435835ff 27 0 +AssignmentActionUsage nestedReference d33c8ec8c06916dc 27 27 +AssignmentActionUsage nestedRendering 46d58560435835ff 27 0 +AssignmentActionUsage nestedRequirement 46d58560435835ff 27 0 +AssignmentActionUsage nestedState 46d58560435835ff 27 0 +AssignmentActionUsage nestedTransition 46d58560435835ff 27 0 +AssignmentActionUsage nestedUsage d33c8ec8c06916dc 27 27 +AssignmentActionUsage nestedUseCase 46d58560435835ff 27 0 +AssignmentActionUsage nestedVerificationCase 46d58560435835ff 27 0 +AssignmentActionUsage nestedView 46d58560435835ff 27 0 +AssignmentActionUsage nestedViewpoint 46d58560435835ff 27 0 +AssignmentActionUsage occurrenceDefinition 46d58560435835ff 27 0 +AssignmentActionUsage output 46d58560435835ff 27 0 +AssignmentActionUsage ownedAnnotation 46d58560435835ff 27 0 +AssignmentActionUsage ownedConjugator 9b268e46e142efe0 27 0 +AssignmentActionUsage ownedCrossSubsetting 9b268e46e142efe0 27 0 +AssignmentActionUsage ownedDifferencing 46d58560435835ff 27 0 +AssignmentActionUsage ownedDisjoining 46d58560435835ff 27 0 +AssignmentActionUsage ownedElement d33c8ec8c06916dc 27 27 +AssignmentActionUsage ownedEndFeature 46d58560435835ff 27 0 +AssignmentActionUsage ownedFeature d33c8ec8c06916dc 27 27 +AssignmentActionUsage ownedFeatureChaining 46d58560435835ff 27 0 +AssignmentActionUsage ownedFeatureInverting 46d58560435835ff 27 0 +AssignmentActionUsage ownedFeatureMembership f2c527fa068686c9 27 27 +AssignmentActionUsage ownedImport 46d58560435835ff 27 0 +AssignmentActionUsage ownedIntersecting 46d58560435835ff 27 0 +AssignmentActionUsage ownedMember d33c8ec8c06916dc 27 27 +AssignmentActionUsage ownedMembership f2c527fa068686c9 27 27 +AssignmentActionUsage ownedRedefinition 46d58560435835ff 27 0 +AssignmentActionUsage ownedReferenceSubsetting 9b268e46e142efe0 27 0 +AssignmentActionUsage ownedRelationship 884f390374c6df38 27 27 +AssignmentActionUsage ownedSpecialization 2ed6e692599d9f14 27 27 +AssignmentActionUsage ownedSubsetting 2ed6e692599d9f14 27 27 +AssignmentActionUsage ownedTypeFeaturing 46d58560435835ff 27 0 +AssignmentActionUsage ownedTyping 46d58560435835ff 27 0 +AssignmentActionUsage ownedUnioning 46d58560435835ff 27 0 +AssignmentActionUsage owner a416251ba6a02e8f 27 27 +AssignmentActionUsage owningDefinition 5c987edf35a9a999 27 1 +AssignmentActionUsage owningFeatureMembership 4dd0e856e262b70d 27 27 +AssignmentActionUsage owningMembership 4dd0e856e262b70d 27 27 +AssignmentActionUsage owningNamespace a416251ba6a02e8f 27 27 +AssignmentActionUsage owningRelationship 4dd0e856e262b70d 27 27 +AssignmentActionUsage owningType a416251ba6a02e8f 27 27 +AssignmentActionUsage owningUsage e2a43483523974d6 27 26 +AssignmentActionUsage parameter d33c8ec8c06916dc 27 27 +AssignmentActionUsage portionKind 9b268e46e142efe0 27 0 +AssignmentActionUsage qualifiedName 9b268e46e142efe0 27 0 +AssignmentActionUsage referent 3fb1e19259966791 27 0 +AssignmentActionUsage shortName 9b268e46e142efe0 27 0 +AssignmentActionUsage targetArgument 02aecda8a65ba8c3 27 27 +AssignmentActionUsage textualRepresentation 46d58560435835ff 27 0 +AssignmentActionUsage type 46d58560435835ff 27 0 +AssignmentActionUsage unioningType 46d58560435835ff 27 0 +AssignmentActionUsage usage d33c8ec8c06916dc 27 27 +AssignmentActionUsage valueExpression 47f700b93a4bb252 27 27 +AssignmentActionUsage variant 46d58560435835ff 27 0 +AssignmentActionUsage variantMembership 46d58560435835ff 27 0 +AttributeDefinition aliasIds 72d05f9b3a646290 162 0 +AttributeDefinition declaredName 4a11b11cfacfbdb0 162 162 +AttributeDefinition declaredShortName 8a7d4d2484e38fc2 162 0 +AttributeDefinition differencingType 72d05f9b3a646290 162 0 +AttributeDefinition directedFeature 72d05f9b3a646290 162 0 +AttributeDefinition directedUsage 72d05f9b3a646290 162 0 +AttributeDefinition documentation 238fdb6bf70b64e6 162 5 +AttributeDefinition elementId 9030976e30696698 162 162 +AttributeDefinition endFeature 72d05f9b3a646290 162 0 +AttributeDefinition feature f4fe46d33207925a 162 66 +AttributeDefinition featureMembership 5daeb4b25ef5f6da 162 66 +AttributeDefinition importedMembership 72d05f9b3a646290 162 0 +AttributeDefinition inheritedFeature 72d05f9b3a646290 162 0 +AttributeDefinition inheritedMembership 72d05f9b3a646290 162 0 +AttributeDefinition input 72d05f9b3a646290 162 0 +AttributeDefinition intersectingType 72d05f9b3a646290 162 0 +AttributeDefinition isAbstract 1f5ce4327daf8fa0 162 2 +AttributeDefinition isConjugated b8f15fb06e90dad6 162 0 +AttributeDefinition isImpliedIncluded 27b6174a377a2a28 162 162 +AttributeDefinition isLibraryElement b8f15fb06e90dad6 162 0 +AttributeDefinition isSufficient b8f15fb06e90dad6 162 0 +AttributeDefinition isVariation 1f5ce4327daf8fa0 162 2 +AttributeDefinition member 852af33867ea4a14 162 71 +AttributeDefinition membership 89462b022d7e7d6c 162 71 +AttributeDefinition multiplicity 8a7d4d2484e38fc2 162 0 +AttributeDefinition name 4a11b11cfacfbdb0 162 162 +AttributeDefinition output 72d05f9b3a646290 162 0 +AttributeDefinition ownedAction 72d05f9b3a646290 162 0 +AttributeDefinition ownedAllocation 72d05f9b3a646290 162 0 +AttributeDefinition ownedAnalysisCase 72d05f9b3a646290 162 0 +AttributeDefinition ownedAnnotation 72d05f9b3a646290 162 0 +AttributeDefinition ownedAttribute 9af26c58e19beeb4 162 45 +AttributeDefinition ownedCalculation 72d05f9b3a646290 162 0 +AttributeDefinition ownedCase 72d05f9b3a646290 162 0 +AttributeDefinition ownedConcern 72d05f9b3a646290 162 0 +AttributeDefinition ownedConjugator 8a7d4d2484e38fc2 162 0 +AttributeDefinition ownedConnection 72d05f9b3a646290 162 0 +AttributeDefinition ownedConstraint 7e563770422c8560 162 2 +AttributeDefinition ownedDifferencing 72d05f9b3a646290 162 0 +AttributeDefinition ownedDisjoining 72d05f9b3a646290 162 0 +AttributeDefinition ownedElement 852af33867ea4a14 162 71 +AttributeDefinition ownedEndFeature 72d05f9b3a646290 162 0 +AttributeDefinition ownedEnumeration 72d05f9b3a646290 162 0 +AttributeDefinition ownedFeature f4fe46d33207925a 162 66 +AttributeDefinition ownedFeatureMembership 5daeb4b25ef5f6da 162 66 +AttributeDefinition ownedFlow 72d05f9b3a646290 162 0 +AttributeDefinition ownedImport 72d05f9b3a646290 162 0 +AttributeDefinition ownedInterface e2559fae1cfbe5cc 162 20 +AttributeDefinition ownedIntersecting 72d05f9b3a646290 162 0 +AttributeDefinition ownedItem 91967a15f3ff6718 162 4 +AttributeDefinition ownedMember 852af33867ea4a14 162 71 +AttributeDefinition ownedMembership 89462b022d7e7d6c 162 71 +AttributeDefinition ownedMetadata 72d05f9b3a646290 162 0 +AttributeDefinition ownedOccurrence 9d1c51eafbc789e8 162 6 +AttributeDefinition ownedPart 148b1bcc6966fa7e 162 2 +AttributeDefinition ownedPort 72d05f9b3a646290 162 0 +AttributeDefinition ownedReference e2559fae1cfbe5cc 162 20 +AttributeDefinition ownedRelationship 00a62e2765e6d48c 162 87 +AttributeDefinition ownedRendering 72d05f9b3a646290 162 0 +AttributeDefinition ownedRequirement 72d05f9b3a646290 162 0 +AttributeDefinition ownedSpecialization 86c0ba6622b56d74 162 62 +AttributeDefinition ownedState 72d05f9b3a646290 162 0 +AttributeDefinition ownedSubclassification 86c0ba6622b56d74 162 62 +AttributeDefinition ownedTransition 72d05f9b3a646290 162 0 +AttributeDefinition ownedUnioning 72d05f9b3a646290 162 0 +AttributeDefinition ownedUsage f4fe46d33207925a 162 66 +AttributeDefinition ownedUseCase 72d05f9b3a646290 162 0 +AttributeDefinition ownedVerificationCase 72d05f9b3a646290 162 0 +AttributeDefinition ownedView 72d05f9b3a646290 162 0 +AttributeDefinition ownedViewpoint 72d05f9b3a646290 162 0 +AttributeDefinition owner 057f099476b3b795 162 162 +AttributeDefinition owningMembership 0775cfafde094067 162 162 +AttributeDefinition owningNamespace 057f099476b3b795 162 162 +AttributeDefinition owningRelationship 0775cfafde094067 162 162 +AttributeDefinition qualifiedName ff66c3d3a922eea6 162 162 +AttributeDefinition shortName 8a7d4d2484e38fc2 162 0 +AttributeDefinition textualRepresentation 72d05f9b3a646290 162 0 +AttributeDefinition unioningType 72d05f9b3a646290 162 0 +AttributeDefinition usage f4fe46d33207925a 162 66 +AttributeDefinition variant dabdf7454d2db87c 162 2 +AttributeDefinition variantMembership f94041cf68917e3a 162 2 +AttributeUsage aliasIds 72adc62d2f0f8f4e 814 0 +AttributeUsage attributeDefinition 1a6a54e325ec1af6 814 724 +AttributeUsage chainingFeature 72adc62d2f0f8f4e 814 0 +AttributeUsage crossFeature 09874d6b189080e0 814 0 +AttributeUsage declaredName c1fa47ab1b08f709 814 619 +AttributeUsage declaredShortName 11e3c024c509493d 814 6 +AttributeUsage definition f9cd2887243430ce 814 724 +AttributeUsage differencingType 72adc62d2f0f8f4e 814 0 +AttributeUsage directedFeature 72adc62d2f0f8f4e 814 0 +AttributeUsage directedUsage 72adc62d2f0f8f4e 814 0 +AttributeUsage direction 2e5bae8c999df6d8 814 45 +AttributeUsage documentation 445d4a9a8f0ff981 814 8 +AttributeUsage elementId 61d154c763c75844 814 814 +AttributeUsage endFeature 72adc62d2f0f8f4e 814 0 +AttributeUsage endOwningType 09874d6b189080e0 814 0 +AttributeUsage feature 4b4e05cd33e22380 814 85 +AttributeUsage featureMembership 3f30a9c7c3a0ff8f 814 85 +AttributeUsage featureTarget 453a53895cad87da 814 0 +AttributeUsage featuringType 72adc62d2f0f8f4e 814 0 +AttributeUsage importedMembership 72adc62d2f0f8f4e 814 0 +AttributeUsage inheritedFeature 72adc62d2f0f8f4e 814 0 +AttributeUsage inheritedMembership 72adc62d2f0f8f4e 814 0 +AttributeUsage input 72adc62d2f0f8f4e 814 0 +AttributeUsage intersectingType 72adc62d2f0f8f4e 814 0 +AttributeUsage isAbstract 45d1832ae94187a2 814 2 +AttributeUsage isComposite 1c6e83d62debd810 814 0 +AttributeUsage isConjugated 1c6e83d62debd810 814 0 +AttributeUsage isConstant 7e51a8c65a94874a 814 2 +AttributeUsage isDerived 827b11f242ad6e1d 814 1 +AttributeUsage isEnd 1c6e83d62debd810 814 0 +AttributeUsage isImpliedIncluded 86830725770bfa5e 814 814 +AttributeUsage isLibraryElement 3e5c731d8a3929b0 814 16 +AttributeUsage isOrdered 597086bd364fbbb6 814 6 +AttributeUsage isPortion 09874d6b189080e0 814 0 +AttributeUsage isReference 86830725770bfa5e 814 814 +AttributeUsage isSufficient 09874d6b189080e0 814 0 +AttributeUsage isUnique d1367480eb7abf41 814 813 +AttributeUsage isVariable 09874d6b189080e0 814 0 +AttributeUsage isVariation f091fe40b5478bf5 814 1 +AttributeUsage mayTimeVary 09874d6b189080e0 814 0 +AttributeUsage member 227e0f870be1c71b 814 395 +AttributeUsage membership 500fc30b6b1f6ef7 814 395 +AttributeUsage multiplicity 7449d4f0ad3e5623 814 73 +AttributeUsage name 4ed99a300122430d 814 810 +AttributeUsage nestedAction 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedAllocation 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedAnalysisCase 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedAttribute 7316fa93c88d21a1 814 27 +AttributeUsage nestedCalculation 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedCase 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedConcern 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedConnection 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedConstraint 37663888eee9b5a8 814 2 +AttributeUsage nestedEnumeration 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedFlow 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedInterface f404bc2df5c0d833 814 58 +AttributeUsage nestedItem b48a992990776d6a 814 4 +AttributeUsage nestedMetadata 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedOccurrence 79430b85505193c4 814 6 +AttributeUsage nestedPart 856dc264689fa91a 814 1 +AttributeUsage nestedPort 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedReference f404bc2df5c0d833 814 58 +AttributeUsage nestedRendering 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedRequirement 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedState 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedTransition 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedUsage 4b4e05cd33e22380 814 85 +AttributeUsage nestedUseCase 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedVerificationCase 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedView 72adc62d2f0f8f4e 814 0 +AttributeUsage nestedViewpoint 72adc62d2f0f8f4e 814 0 +AttributeUsage output 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedAnnotation 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedConjugator 09874d6b189080e0 814 0 +AttributeUsage ownedCrossSubsetting 09874d6b189080e0 814 0 +AttributeUsage ownedDifferencing 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedDisjoining 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedElement fb1b5e45146a97b3 814 395 +AttributeUsage ownedEndFeature 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedFeature 4b4e05cd33e22380 814 85 +AttributeUsage ownedFeatureChaining 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedFeatureInverting 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedFeatureMembership 3f30a9c7c3a0ff8f 814 85 +AttributeUsage ownedImport 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedIntersecting 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedMember 227e0f870be1c71b 814 395 +AttributeUsage ownedMembership 500fc30b6b1f6ef7 814 395 +AttributeUsage ownedRedefinition 0d41cffd24441f46 814 234 +AttributeUsage ownedReferenceSubsetting a38a59dfbd1992bd 814 1 +AttributeUsage ownedRelationship c387a2d98e7428ef 814 783 +AttributeUsage ownedSpecialization 18bd0aeb6d59e03a 814 749 +AttributeUsage ownedSubsetting 81e59c06aebf8953 814 362 +AttributeUsage ownedTypeFeaturing 72adc62d2f0f8f4e 814 0 +AttributeUsage ownedTyping 3cfd70d5fbb42a23 814 423 +AttributeUsage ownedUnioning 72adc62d2f0f8f4e 814 0 +AttributeUsage owner d7cd4585788eddd3 814 814 +AttributeUsage owningDefinition fab94f6b2735810f 814 413 +AttributeUsage owningFeatureMembership 51d00d52f0afe433 814 740 +AttributeUsage owningMembership cb3da7c91d75c352 814 814 +AttributeUsage owningNamespace d7cd4585788eddd3 814 814 +AttributeUsage owningRelationship cb3da7c91d75c352 814 814 +AttributeUsage owningType 74b58833b8d2de28 814 740 +AttributeUsage owningUsage 233a73442ea74e2d 814 325 +AttributeUsage qualifiedName bf07f58c5c44f977 814 803 +AttributeUsage shortName 11e3c024c509493d 814 6 +AttributeUsage textualRepresentation 72adc62d2f0f8f4e 814 0 +AttributeUsage type f9cd2887243430ce 814 724 +AttributeUsage unioningType 72adc62d2f0f8f4e 814 0 +AttributeUsage usage 4b4e05cd33e22380 814 85 +AttributeUsage variant b7f95831dc9001b4 814 1 +AttributeUsage variantMembership d2ee77de9912926b 814 1 +BindingConnectorAsUsage aliasIds 37663c15d33938c4 64 0 +BindingConnectorAsUsage association b0e9aa5dc9a44870 64 1 +BindingConnectorAsUsage chainingFeature 37663c15d33938c4 64 0 +BindingConnectorAsUsage connectorEnd e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage crossFeature 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage declaredName 6dfb9b527e3b8185 64 2 +BindingConnectorAsUsage declaredShortName 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage defaultFeaturingType 0c414eeb59b5eeac 64 63 +BindingConnectorAsUsage definition b0e9aa5dc9a44870 64 1 +BindingConnectorAsUsage differencingType 37663c15d33938c4 64 0 +BindingConnectorAsUsage directedFeature 37663c15d33938c4 64 0 +BindingConnectorAsUsage directedUsage 37663c15d33938c4 64 0 +BindingConnectorAsUsage direction 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage documentation 37663c15d33938c4 64 0 +BindingConnectorAsUsage elementId 5b121104b174939c 64 64 +BindingConnectorAsUsage endFeature e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage endOwningType 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage feature e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage featureMembership c2c2493023abb6c5 64 64 +BindingConnectorAsUsage featureTarget 34947d2202773710 64 0 +BindingConnectorAsUsage featuringType 37663c15d33938c4 64 0 +BindingConnectorAsUsage importedMembership 37663c15d33938c4 64 0 +BindingConnectorAsUsage inheritedFeature 37663c15d33938c4 64 0 +BindingConnectorAsUsage inheritedMembership 37663c15d33938c4 64 0 +BindingConnectorAsUsage input 37663c15d33938c4 64 0 +BindingConnectorAsUsage intersectingType 37663c15d33938c4 64 0 +BindingConnectorAsUsage isAbstract e88efd51adf12c84 64 0 +BindingConnectorAsUsage isComposite e88efd51adf12c84 64 0 +BindingConnectorAsUsage isConjugated e88efd51adf12c84 64 0 +BindingConnectorAsUsage isConstant e88efd51adf12c84 64 0 +BindingConnectorAsUsage isDerived e88efd51adf12c84 64 0 +BindingConnectorAsUsage isEnd e88efd51adf12c84 64 0 +BindingConnectorAsUsage isImplied 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage isImpliedIncluded 4d99a22b5a417384 64 64 +BindingConnectorAsUsage isLibraryElement e88efd51adf12c84 64 0 +BindingConnectorAsUsage isOrdered e88efd51adf12c84 64 0 +BindingConnectorAsUsage isPortion 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage isReference 4d99a22b5a417384 64 64 +BindingConnectorAsUsage isSufficient 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage isUnique 4d99a22b5a417384 64 64 +BindingConnectorAsUsage isVariable 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage isVariation e88efd51adf12c84 64 0 +BindingConnectorAsUsage mayTimeVary 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage member 092b7ea97ff00f5a 64 64 +BindingConnectorAsUsage membership 207dc956e2de6f2c 64 64 +BindingConnectorAsUsage multiplicity 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage name 6dfb9b527e3b8185 64 2 +BindingConnectorAsUsage nestedAction 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedAllocation 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedAnalysisCase 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedAttribute 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedCalculation 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedCase 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedConcern 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedConnection 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedConstraint 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedEnumeration 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedFlow 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedInterface e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage nestedItem 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedMetadata 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedOccurrence 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedPart 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedPort 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedReference e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage nestedRendering 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedRequirement 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedState 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedTransition 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedUsage e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage nestedUseCase 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedVerificationCase 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedView 37663c15d33938c4 64 0 +BindingConnectorAsUsage nestedViewpoint 37663c15d33938c4 64 0 +BindingConnectorAsUsage output 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedAnnotation 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedConjugator 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage ownedCrossSubsetting 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage ownedDifferencing 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedDisjoining 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedElement 092b7ea97ff00f5a 64 64 +BindingConnectorAsUsage ownedEndFeature e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage ownedFeature e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage ownedFeatureChaining 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedFeatureInverting 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedFeatureMembership c2c2493023abb6c5 64 64 +BindingConnectorAsUsage ownedImport 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedIntersecting 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedMember 092b7ea97ff00f5a 64 64 +BindingConnectorAsUsage ownedMembership 207dc956e2de6f2c 64 64 +BindingConnectorAsUsage ownedRedefinition 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedReferenceSubsetting 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage ownedRelatedElement 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedRelationship 3a2cdad102b15433 64 64 +BindingConnectorAsUsage ownedSpecialization 0e3e940a68df7c05 64 1 +BindingConnectorAsUsage ownedSubsetting 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedTypeFeaturing 37663c15d33938c4 64 0 +BindingConnectorAsUsage ownedTyping 0e3e940a68df7c05 64 1 +BindingConnectorAsUsage ownedUnioning 37663c15d33938c4 64 0 +BindingConnectorAsUsage owner 482c1a09541d5248 64 64 +BindingConnectorAsUsage owningDefinition 33fe6eab15721942 64 11 +BindingConnectorAsUsage owningFeatureMembership 7eef6826a9d58741 64 64 +BindingConnectorAsUsage owningMembership 7eef6826a9d58741 64 64 +BindingConnectorAsUsage owningNamespace 482c1a09541d5248 64 64 +BindingConnectorAsUsage owningRelatedElement 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage owningRelationship 7eef6826a9d58741 64 64 +BindingConnectorAsUsage owningType 482c1a09541d5248 64 64 +BindingConnectorAsUsage owningUsage 1890a6d8ba77a886 64 53 +BindingConnectorAsUsage qualifiedName 0c088b3cac18971b 64 2 +BindingConnectorAsUsage relatedElement 37663c15d33938c4 64 0 +BindingConnectorAsUsage relatedFeature 1b4aaf6f97bf758f 64 64 +BindingConnectorAsUsage shortName 0462fb7a7bcc6f80 64 0 +BindingConnectorAsUsage source 37663c15d33938c4 64 0 +BindingConnectorAsUsage sourceFeature 4142f795c19e7be4 64 64 +BindingConnectorAsUsage target 37663c15d33938c4 64 0 +BindingConnectorAsUsage targetFeature be91df7f29f3e081 64 64 +BindingConnectorAsUsage textualRepresentation 37663c15d33938c4 64 0 +BindingConnectorAsUsage type b0e9aa5dc9a44870 64 1 +BindingConnectorAsUsage unioningType 37663c15d33938c4 64 0 +BindingConnectorAsUsage usage e9a2d503a3cc224c 64 64 +BindingConnectorAsUsage variant 37663c15d33938c4 64 0 +BindingConnectorAsUsage variantMembership 37663c15d33938c4 64 0 +CalculationDefinition action 8acacfef06f95a1e 39 1 +CalculationDefinition aliasIds 50103a747eaafebf 39 0 +CalculationDefinition calculation 50103a747eaafebf 39 0 +CalculationDefinition declaredName 2134c79c5b88562f 39 39 +CalculationDefinition declaredShortName b033cb227d802148 39 0 +CalculationDefinition differencingType 50103a747eaafebf 39 0 +CalculationDefinition directedFeature c8c2b2025bcec621 39 39 +CalculationDefinition directedUsage c8c2b2025bcec621 39 39 +CalculationDefinition documentation 38c868c80d4b5c8f 39 1 +CalculationDefinition elementId 69a83a47219f55e4 39 39 +CalculationDefinition endFeature 50103a747eaafebf 39 0 +CalculationDefinition expression c33d44dd497d32bc 39 3 +CalculationDefinition feature 7da7aaa3d7fefce6 39 39 +CalculationDefinition featureMembership eb38e08e42421b9c 39 39 +CalculationDefinition importedMembership 50103a747eaafebf 39 0 +CalculationDefinition inheritedFeature 50103a747eaafebf 39 0 +CalculationDefinition inheritedMembership 50103a747eaafebf 39 0 +CalculationDefinition input 430e742e929fc70d 39 39 +CalculationDefinition intersectingType 50103a747eaafebf 39 0 +CalculationDefinition isAbstract 360207e8700e7979 39 1 +CalculationDefinition isConjugated a7492130997751b4 39 0 +CalculationDefinition isImpliedIncluded f76667fa2341d9d7 39 39 +CalculationDefinition isIndividual b033cb227d802148 39 0 +CalculationDefinition isLibraryElement a7492130997751b4 39 0 +CalculationDefinition isModelLevelEvaluable a7492130997751b4 39 0 +CalculationDefinition isSufficient a7492130997751b4 39 0 +CalculationDefinition isVariation a7492130997751b4 39 0 +CalculationDefinition member b0824e669ac46832 39 39 +CalculationDefinition membership df6cca43cacdf472 39 39 +CalculationDefinition multiplicity b033cb227d802148 39 0 +CalculationDefinition name 2134c79c5b88562f 39 39 +CalculationDefinition output cd5490a1acb161c7 39 38 +CalculationDefinition ownedAction 8acacfef06f95a1e 39 1 +CalculationDefinition ownedAllocation 50103a747eaafebf 39 0 +CalculationDefinition ownedAnalysisCase 50103a747eaafebf 39 0 +CalculationDefinition ownedAnnotation 50103a747eaafebf 39 0 +CalculationDefinition ownedAttribute 4985bba2c3ccdf18 39 4 +CalculationDefinition ownedCalculation 50103a747eaafebf 39 0 +CalculationDefinition ownedCase 50103a747eaafebf 39 0 +CalculationDefinition ownedConcern 50103a747eaafebf 39 0 +CalculationDefinition ownedConjugator b033cb227d802148 39 0 +CalculationDefinition ownedConnection 50103a747eaafebf 39 0 +CalculationDefinition ownedConstraint 0dbf04a915732f2d 39 1 +CalculationDefinition ownedDifferencing 50103a747eaafebf 39 0 +CalculationDefinition ownedDisjoining 50103a747eaafebf 39 0 +CalculationDefinition ownedElement b0824e669ac46832 39 39 +CalculationDefinition ownedEndFeature 50103a747eaafebf 39 0 +CalculationDefinition ownedEnumeration 50103a747eaafebf 39 0 +CalculationDefinition ownedFeature 7da7aaa3d7fefce6 39 39 +CalculationDefinition ownedFeatureMembership eb38e08e42421b9c 39 39 +CalculationDefinition ownedFlow 50103a747eaafebf 39 0 +CalculationDefinition ownedImport 50103a747eaafebf 39 0 +CalculationDefinition ownedInterface c8c2b2025bcec621 39 39 +CalculationDefinition ownedIntersecting 50103a747eaafebf 39 0 +CalculationDefinition ownedItem 50103a747eaafebf 39 0 +CalculationDefinition ownedMember b0824e669ac46832 39 39 +CalculationDefinition ownedMembership df6cca43cacdf472 39 39 +CalculationDefinition ownedMetadata 50103a747eaafebf 39 0 +CalculationDefinition ownedOccurrence 48799a239dc18a8c 39 2 +CalculationDefinition ownedPart 50103a747eaafebf 39 0 +CalculationDefinition ownedPort 50103a747eaafebf 39 0 +CalculationDefinition ownedReference c8c2b2025bcec621 39 39 +CalculationDefinition ownedRelationship ea3c2c40c89368f5 39 39 +CalculationDefinition ownedRendering 50103a747eaafebf 39 0 +CalculationDefinition ownedRequirement 50103a747eaafebf 39 0 +CalculationDefinition ownedSpecialization eac5a99aa119f42a 39 39 +CalculationDefinition ownedState 50103a747eaafebf 39 0 +CalculationDefinition ownedSubclassification eac5a99aa119f42a 39 39 +CalculationDefinition ownedTransition 50103a747eaafebf 39 0 +CalculationDefinition ownedUnioning 50103a747eaafebf 39 0 +CalculationDefinition ownedUsage 01e1db165b4c669d 39 39 +CalculationDefinition ownedUseCase 50103a747eaafebf 39 0 +CalculationDefinition ownedVerificationCase 50103a747eaafebf 39 0 +CalculationDefinition ownedView 50103a747eaafebf 39 0 +CalculationDefinition ownedViewpoint 50103a747eaafebf 39 0 +CalculationDefinition owner e8717afe82ddf5c1 39 39 +CalculationDefinition owningMembership 753beb43d8768cfe 39 39 +CalculationDefinition owningNamespace e8717afe82ddf5c1 39 39 +CalculationDefinition owningRelationship 753beb43d8768cfe 39 39 +CalculationDefinition parameter c8c2b2025bcec621 39 39 +CalculationDefinition qualifiedName 646b579044f2a64c 39 39 +CalculationDefinition result 4d56237658b79573 39 38 +CalculationDefinition shortName b033cb227d802148 39 0 +CalculationDefinition step 14e555c28ca8cfbd 39 3 +CalculationDefinition textualRepresentation 50103a747eaafebf 39 0 +CalculationDefinition unioningType 50103a747eaafebf 39 0 +CalculationDefinition usage 01e1db165b4c669d 39 39 +CalculationDefinition variant 50103a747eaafebf 39 0 +CalculationDefinition variantMembership 50103a747eaafebf 39 0 +CalculationUsage actionDefinition e393c8c230c78912 31 24 +CalculationUsage aliasIds 479ee7aba08b15c9 31 0 +CalculationUsage behavior e393c8c230c78912 31 24 +CalculationUsage calculationDefinition 989c02477fa81e49 31 24 +CalculationUsage chainingFeature 479ee7aba08b15c9 31 0 +CalculationUsage crossFeature 61dccb86435e5b92 31 0 +CalculationUsage declaredName 1f5aa4f7968507aa 31 23 +CalculationUsage declaredShortName 61dccb86435e5b92 31 0 +CalculationUsage definition e393c8c230c78912 31 24 +CalculationUsage differencingType 479ee7aba08b15c9 31 0 +CalculationUsage directedFeature e67a6bcb4097a58f 31 24 +CalculationUsage directedUsage e67a6bcb4097a58f 31 24 +CalculationUsage direction dbd6c390e8c7ea0a 31 3 +CalculationUsage documentation 479ee7aba08b15c9 31 0 +CalculationUsage elementId 99209e3ab1f65de0 31 31 +CalculationUsage endFeature 479ee7aba08b15c9 31 0 +CalculationUsage endOwningType 61dccb86435e5b92 31 0 +CalculationUsage feature 7f974802bb94f0a3 31 25 +CalculationUsage featureMembership 69bb62922d274337 31 25 +CalculationUsage featureTarget c5871ab881c4f4f5 31 0 +CalculationUsage featuringType 479ee7aba08b15c9 31 0 +CalculationUsage function 989c02477fa81e49 31 24 +CalculationUsage importedMembership 479ee7aba08b15c9 31 0 +CalculationUsage individualDefinition 61dccb86435e5b92 31 0 +CalculationUsage inheritedFeature 479ee7aba08b15c9 31 0 +CalculationUsage inheritedMembership 479ee7aba08b15c9 31 0 +CalculationUsage input a6181f8173e7316e 31 24 +CalculationUsage intersectingType 479ee7aba08b15c9 31 0 +CalculationUsage isAbstract 85878ad133f424a6 31 0 +CalculationUsage isComposite 5a21bc58e183c903 31 25 +CalculationUsage isConjugated 85878ad133f424a6 31 0 +CalculationUsage isConstant 85878ad133f424a6 31 0 +CalculationUsage isDerived 85878ad133f424a6 31 0 +CalculationUsage isEnd 85878ad133f424a6 31 0 +CalculationUsage isImpliedIncluded be0e1619f6432621 31 31 +CalculationUsage isIndividual 61dccb86435e5b92 31 0 +CalculationUsage isLibraryElement 85878ad133f424a6 31 0 +CalculationUsage isModelLevelEvaluable 85878ad133f424a6 31 0 +CalculationUsage isOrdered 85878ad133f424a6 31 0 +CalculationUsage isPortion 61dccb86435e5b92 31 0 +CalculationUsage isReference e973e49248b381c4 31 6 +CalculationUsage isSufficient 61dccb86435e5b92 31 0 +CalculationUsage isUnique be0e1619f6432621 31 31 +CalculationUsage isVariable 61dccb86435e5b92 31 0 +CalculationUsage isVariation 85878ad133f424a6 31 0 +CalculationUsage mayTimeVary 61dccb86435e5b92 31 0 +CalculationUsage member 4f32468c0a56b536 31 27 +CalculationUsage membership 6d0578db81f9ba72 31 27 +CalculationUsage multiplicity 61dccb86435e5b92 31 0 +CalculationUsage name 4186cbd0912746f1 31 29 +CalculationUsage nestedAction a34fc57ce8e03821 31 2 +CalculationUsage nestedAllocation 479ee7aba08b15c9 31 0 +CalculationUsage nestedAnalysisCase 479ee7aba08b15c9 31 0 +CalculationUsage nestedAttribute 141ec0f3261b1d3a 31 3 +CalculationUsage nestedCalculation a34fc57ce8e03821 31 2 +CalculationUsage nestedCase 479ee7aba08b15c9 31 0 +CalculationUsage nestedConcern 479ee7aba08b15c9 31 0 +CalculationUsage nestedConnection 479ee7aba08b15c9 31 0 +CalculationUsage nestedConstraint 479ee7aba08b15c9 31 0 +CalculationUsage nestedEnumeration 479ee7aba08b15c9 31 0 +CalculationUsage nestedFlow 479ee7aba08b15c9 31 0 +CalculationUsage nestedInterface 994d933532b960b9 31 22 +CalculationUsage nestedItem 443c641a879b5b7a 31 5 +CalculationUsage nestedMetadata 479ee7aba08b15c9 31 0 +CalculationUsage nestedOccurrence 4f66768c6ef28588 31 5 +CalculationUsage nestedPart 443c641a879b5b7a 31 5 +CalculationUsage nestedPort 479ee7aba08b15c9 31 0 +CalculationUsage nestedReference 994d933532b960b9 31 22 +CalculationUsage nestedRendering 479ee7aba08b15c9 31 0 +CalculationUsage nestedRequirement 479ee7aba08b15c9 31 0 +CalculationUsage nestedState 479ee7aba08b15c9 31 0 +CalculationUsage nestedTransition 479ee7aba08b15c9 31 0 +CalculationUsage nestedUsage 4d7b1a8edaf9f98b 31 24 +CalculationUsage nestedUseCase 479ee7aba08b15c9 31 0 +CalculationUsage nestedVerificationCase 479ee7aba08b15c9 31 0 +CalculationUsage nestedView 479ee7aba08b15c9 31 0 +CalculationUsage nestedViewpoint 479ee7aba08b15c9 31 0 +CalculationUsage occurrenceDefinition e393c8c230c78912 31 24 +CalculationUsage output 02eecf78f0737214 31 18 +CalculationUsage ownedAnnotation 479ee7aba08b15c9 31 0 +CalculationUsage ownedConjugator 61dccb86435e5b92 31 0 +CalculationUsage ownedCrossSubsetting 61dccb86435e5b92 31 0 +CalculationUsage ownedDifferencing 479ee7aba08b15c9 31 0 +CalculationUsage ownedDisjoining 479ee7aba08b15c9 31 0 +CalculationUsage ownedElement 4f32468c0a56b536 31 27 +CalculationUsage ownedEndFeature 479ee7aba08b15c9 31 0 +CalculationUsage ownedFeature 7f974802bb94f0a3 31 25 +CalculationUsage ownedFeatureChaining 479ee7aba08b15c9 31 0 +CalculationUsage ownedFeatureInverting 479ee7aba08b15c9 31 0 +CalculationUsage ownedFeatureMembership 69bb62922d274337 31 25 +CalculationUsage ownedImport 479ee7aba08b15c9 31 0 +CalculationUsage ownedIntersecting 479ee7aba08b15c9 31 0 +CalculationUsage ownedMember 4f32468c0a56b536 31 27 +CalculationUsage ownedMembership 6d0578db81f9ba72 31 27 +CalculationUsage ownedRedefinition 3781d955c2d16ebc 31 6 +CalculationUsage ownedReferenceSubsetting 61dccb86435e5b92 31 0 +CalculationUsage ownedRelationship 8d7b71a592d44d08 31 31 +CalculationUsage ownedSpecialization 349050575b88ec6d 31 31 +CalculationUsage ownedSubsetting fe269c102a08f31f 31 31 +CalculationUsage ownedTypeFeaturing 479ee7aba08b15c9 31 0 +CalculationUsage ownedTyping c3a5fb826af6c139 31 16 +CalculationUsage ownedUnioning 479ee7aba08b15c9 31 0 +CalculationUsage owner 5179270944bddff3 31 31 +CalculationUsage owningDefinition 35e39fddfaa7b728 31 2 +CalculationUsage owningFeatureMembership 7c05bbbe40cbf34b 31 28 +CalculationUsage owningMembership c4cebe0921fbda5e 31 31 +CalculationUsage owningNamespace 5179270944bddff3 31 31 +CalculationUsage owningRelationship c4cebe0921fbda5e 31 31 +CalculationUsage owningType 716afd53a1f0a192 31 28 +CalculationUsage owningUsage 9d6428fbeaa745fc 31 26 +CalculationUsage parameter e67a6bcb4097a58f 31 24 +CalculationUsage portionKind 61dccb86435e5b92 31 0 +CalculationUsage qualifiedName 3c6a4ac06e43502c 31 29 +CalculationUsage result df328dd5acfdc99c 31 18 +CalculationUsage shortName 61dccb86435e5b92 31 0 +CalculationUsage textualRepresentation 479ee7aba08b15c9 31 0 +CalculationUsage type e393c8c230c78912 31 24 +CalculationUsage unioningType 479ee7aba08b15c9 31 0 +CalculationUsage usage 4d7b1a8edaf9f98b 31 24 +CalculationUsage variant 479ee7aba08b15c9 31 0 +CalculationUsage variantMembership 479ee7aba08b15c9 31 0 +Comment aliasIds 19e603febd5fa0ab 205 0 +Comment annotatedElement e5d220d73a68bb7d 205 205 +Comment annotation 07ca8c0fbfe39bc2 205 9 +Comment body 0a5b9c0151e7aed8 205 205 +Comment declaredName 5c58cac6dd15e53f 205 5 +Comment declaredShortName d6036d5fbee5a02e 205 0 +Comment documentation 19e603febd5fa0ab 205 0 +Comment elementId 798282a199a75c70 205 205 +Comment isImpliedIncluded eb6c482ab816c7d3 205 205 +Comment isLibraryElement 05ac9b11d2f0769a 205 0 +Comment locale 46268ddae9296944 205 2 +Comment name 5c58cac6dd15e53f 205 5 +Comment ownedAnnotatingRelationship 07ca8c0fbfe39bc2 205 9 +Comment ownedAnnotation 19e603febd5fa0ab 205 0 +Comment ownedElement 19e603febd5fa0ab 205 0 +Comment ownedRelationship 07ca8c0fbfe39bc2 205 9 +Comment owner 66ee8ca6a366a230 205 205 +Comment owningAnnotatingRelationship d6036d5fbee5a02e 205 0 +Comment owningMembership 0e4dba1bd5c07885 205 205 +Comment owningNamespace 66ee8ca6a366a230 205 205 +Comment owningRelationship 0e4dba1bd5c07885 205 205 +Comment qualifiedName af7081cce9345202 205 5 +Comment shortName d6036d5fbee5a02e 205 0 +Comment textualRepresentation 19e603febd5fa0ab 205 0 +ConcernDefinition actorParameter 4d3eb98c14151064 2 0 +ConcernDefinition aliasIds 4d3eb98c14151064 2 0 +ConcernDefinition assumedConstraint 4d3eb98c14151064 2 0 +ConcernDefinition declaredName 027356b3e52c3f27 2 2 +ConcernDefinition declaredShortName 6a62c06dffa571ea 2 0 +ConcernDefinition differencingType 4d3eb98c14151064 2 0 +ConcernDefinition directedFeature 31e1842ec1a49ed3 2 2 +ConcernDefinition directedUsage 31e1842ec1a49ed3 2 2 +ConcernDefinition documentation 3f246174f11d6d9d 2 1 +ConcernDefinition elementId 3547ebcf3e4d2c50 2 2 +ConcernDefinition endFeature 4d3eb98c14151064 2 0 +ConcernDefinition expression 4d3eb98c14151064 2 0 +ConcernDefinition feature 31e1842ec1a49ed3 2 2 +ConcernDefinition featureMembership 1e2fd7061bccd451 2 2 +ConcernDefinition framedConcern 4d3eb98c14151064 2 0 +ConcernDefinition importedMembership 4d3eb98c14151064 2 0 +ConcernDefinition inheritedFeature 4d3eb98c14151064 2 0 +ConcernDefinition inheritedMembership 4d3eb98c14151064 2 0 +ConcernDefinition input 31e1842ec1a49ed3 2 2 +ConcernDefinition intersectingType 4d3eb98c14151064 2 0 +ConcernDefinition isAbstract a59afe6c9d696efa 2 0 +ConcernDefinition isConjugated a59afe6c9d696efa 2 0 +ConcernDefinition isImpliedIncluded 645505fd95859664 2 2 +ConcernDefinition isIndividual 6a62c06dffa571ea 2 0 +ConcernDefinition isLibraryElement a59afe6c9d696efa 2 0 +ConcernDefinition isModelLevelEvaluable a59afe6c9d696efa 2 0 +ConcernDefinition isSufficient a59afe6c9d696efa 2 0 +ConcernDefinition isVariation a59afe6c9d696efa 2 0 +ConcernDefinition member 79bdb4845c8ded8c 2 2 +ConcernDefinition membership 9b58d2f8e8ac8f80 2 2 +ConcernDefinition multiplicity 6a62c06dffa571ea 2 0 +ConcernDefinition name 027356b3e52c3f27 2 2 +ConcernDefinition output 4d3eb98c14151064 2 0 +ConcernDefinition ownedAction 4d3eb98c14151064 2 0 +ConcernDefinition ownedAllocation 4d3eb98c14151064 2 0 +ConcernDefinition ownedAnalysisCase 4d3eb98c14151064 2 0 +ConcernDefinition ownedAnnotation 4d3eb98c14151064 2 0 +ConcernDefinition ownedAttribute 4d3eb98c14151064 2 0 +ConcernDefinition ownedCalculation 4d3eb98c14151064 2 0 +ConcernDefinition ownedCase 4d3eb98c14151064 2 0 +ConcernDefinition ownedConcern 4d3eb98c14151064 2 0 +ConcernDefinition ownedConjugator 6a62c06dffa571ea 2 0 +ConcernDefinition ownedConnection 4d3eb98c14151064 2 0 +ConcernDefinition ownedConstraint 4d3eb98c14151064 2 0 +ConcernDefinition ownedDifferencing 4d3eb98c14151064 2 0 +ConcernDefinition ownedDisjoining 4d3eb98c14151064 2 0 +ConcernDefinition ownedElement 79bdb4845c8ded8c 2 2 +ConcernDefinition ownedEndFeature 4d3eb98c14151064 2 0 +ConcernDefinition ownedEnumeration 4d3eb98c14151064 2 0 +ConcernDefinition ownedFeature 31e1842ec1a49ed3 2 2 +ConcernDefinition ownedFeatureMembership 1e2fd7061bccd451 2 2 +ConcernDefinition ownedFlow 4d3eb98c14151064 2 0 +ConcernDefinition ownedImport 4d3eb98c14151064 2 0 +ConcernDefinition ownedInterface 510da900e475140e 2 2 +ConcernDefinition ownedIntersecting 4d3eb98c14151064 2 0 +ConcernDefinition ownedItem 2ab6efb93f0813cd 2 2 +ConcernDefinition ownedMember 79bdb4845c8ded8c 2 2 +ConcernDefinition ownedMembership 9b58d2f8e8ac8f80 2 2 +ConcernDefinition ownedMetadata 4d3eb98c14151064 2 0 +ConcernDefinition ownedOccurrence 2ab6efb93f0813cd 2 2 +ConcernDefinition ownedPart 2ab6efb93f0813cd 2 2 +ConcernDefinition ownedPort 4d3eb98c14151064 2 0 +ConcernDefinition ownedReference 510da900e475140e 2 2 +ConcernDefinition ownedRelationship 5c5f48ca83e0bdee 2 2 +ConcernDefinition ownedRendering 4d3eb98c14151064 2 0 +ConcernDefinition ownedRequirement 4d3eb98c14151064 2 0 +ConcernDefinition ownedSpecialization d0055b8c6af69286 2 2 +ConcernDefinition ownedState 4d3eb98c14151064 2 0 +ConcernDefinition ownedSubclassification d0055b8c6af69286 2 2 +ConcernDefinition ownedTransition 4d3eb98c14151064 2 0 +ConcernDefinition ownedUnioning 4d3eb98c14151064 2 0 +ConcernDefinition ownedUsage 31e1842ec1a49ed3 2 2 +ConcernDefinition ownedUseCase 4d3eb98c14151064 2 0 +ConcernDefinition ownedVerificationCase 4d3eb98c14151064 2 0 +ConcernDefinition ownedView 4d3eb98c14151064 2 0 +ConcernDefinition ownedViewpoint 4d3eb98c14151064 2 0 +ConcernDefinition owner 5433c35698d257f9 2 2 +ConcernDefinition owningMembership 4e6942970b02064a 2 2 +ConcernDefinition owningNamespace 5433c35698d257f9 2 2 +ConcernDefinition owningRelationship 4e6942970b02064a 2 2 +ConcernDefinition parameter 31e1842ec1a49ed3 2 2 +ConcernDefinition qualifiedName 1fd6e4406ed3819d 2 2 +ConcernDefinition reqId 6a62c06dffa571ea 2 0 +ConcernDefinition requiredConstraint 4d3eb98c14151064 2 0 +ConcernDefinition result c48b3c836b72f552 2 0 +ConcernDefinition shortName 6a62c06dffa571ea 2 0 +ConcernDefinition stakeholderParameter 2ab6efb93f0813cd 2 2 +ConcernDefinition step 4d3eb98c14151064 2 0 +ConcernDefinition subjectParameter fd5b26e7ddb0f312 2 2 +ConcernDefinition text 8b52ca572eb715dc 2 1 +ConcernDefinition textualRepresentation 4d3eb98c14151064 2 0 +ConcernDefinition unioningType 4d3eb98c14151064 2 0 +ConcernDefinition usage 31e1842ec1a49ed3 2 2 +ConcernDefinition variant 4d3eb98c14151064 2 0 +ConcernDefinition variantMembership 4d3eb98c14151064 2 0 +ConcernUsage actorParameter f66764928aa76a1b 11 0 +ConcernUsage aliasIds f66764928aa76a1b 11 0 +ConcernUsage assumedConstraint f66764928aa76a1b 11 0 +ConcernUsage behavior b807c69764eb4619 11 3 +ConcernUsage chainingFeature f66764928aa76a1b 11 0 +ConcernUsage concernDefinition e420a1fbec28a445 11 3 +ConcernUsage constraintDefinition e420a1fbec28a445 11 3 +ConcernUsage crossFeature 07b0700da59410cc 11 0 +ConcernUsage declaredName 2a7a6012e9726996 11 7 +ConcernUsage declaredShortName 07b0700da59410cc 11 0 +ConcernUsage definition b807c69764eb4619 11 3 +ConcernUsage differencingType f66764928aa76a1b 11 0 +ConcernUsage directedFeature 70734bfe504c7d3f 11 4 +ConcernUsage directedUsage 70734bfe504c7d3f 11 4 +ConcernUsage direction 07b0700da59410cc 11 0 +ConcernUsage documentation cae81b1dc049ca47 11 2 +ConcernUsage elementId 64a98f377f55c13c 11 11 +ConcernUsage endFeature f66764928aa76a1b 11 0 +ConcernUsage endOwningType 07b0700da59410cc 11 0 +ConcernUsage feature 70734bfe504c7d3f 11 4 +ConcernUsage featureMembership bba08ac7c48120c9 11 4 +ConcernUsage featureTarget bec7d3ef3c7fbc95 11 0 +ConcernUsage featuringType f66764928aa76a1b 11 0 +ConcernUsage framedConcern f66764928aa76a1b 11 0 +ConcernUsage function e420a1fbec28a445 11 3 +ConcernUsage importedMembership f66764928aa76a1b 11 0 +ConcernUsage individualDefinition 07b0700da59410cc 11 0 +ConcernUsage inheritedFeature f66764928aa76a1b 11 0 +ConcernUsage inheritedMembership f66764928aa76a1b 11 0 +ConcernUsage input 70734bfe504c7d3f 11 4 +ConcernUsage intersectingType f66764928aa76a1b 11 0 +ConcernUsage isAbstract 0d04eff3180ee67c 11 0 +ConcernUsage isComposite 56e88c40219a8207 11 7 +ConcernUsage isConjugated 0d04eff3180ee67c 11 0 +ConcernUsage isConstant 0d04eff3180ee67c 11 0 +ConcernUsage isDerived 0d04eff3180ee67c 11 0 +ConcernUsage isEnd 0d04eff3180ee67c 11 0 +ConcernUsage isImpliedIncluded 8853e883ecbacad3 11 11 +ConcernUsage isIndividual 07b0700da59410cc 11 0 +ConcernUsage isLibraryElement 0d04eff3180ee67c 11 0 +ConcernUsage isModelLevelEvaluable 0d04eff3180ee67c 11 0 +ConcernUsage isOrdered 0d04eff3180ee67c 11 0 +ConcernUsage isPortion 07b0700da59410cc 11 0 +ConcernUsage isReference 3e704c36e32f2f48 11 4 +ConcernUsage isSufficient 07b0700da59410cc 11 0 +ConcernUsage isUnique 8853e883ecbacad3 11 11 +ConcernUsage isVariable 07b0700da59410cc 11 0 +ConcernUsage isVariation 0d04eff3180ee67c 11 0 +ConcernUsage mayTimeVary 07b0700da59410cc 11 0 +ConcernUsage member 812bc985132fa531 11 4 +ConcernUsage membership e425902157fdb702 11 4 +ConcernUsage multiplicity 07b0700da59410cc 11 0 +ConcernUsage name edfd4298f26792e9 11 11 +ConcernUsage nestedAction f66764928aa76a1b 11 0 +ConcernUsage nestedAllocation f66764928aa76a1b 11 0 +ConcernUsage nestedAnalysisCase f66764928aa76a1b 11 0 +ConcernUsage nestedAttribute f66764928aa76a1b 11 0 +ConcernUsage nestedCalculation f66764928aa76a1b 11 0 +ConcernUsage nestedCase f66764928aa76a1b 11 0 +ConcernUsage nestedConcern f66764928aa76a1b 11 0 +ConcernUsage nestedConnection f66764928aa76a1b 11 0 +ConcernUsage nestedConstraint f66764928aa76a1b 11 0 +ConcernUsage nestedEnumeration f66764928aa76a1b 11 0 +ConcernUsage nestedFlow f66764928aa76a1b 11 0 +ConcernUsage nestedInterface 5ed0f764cf144766 11 4 +ConcernUsage nestedItem e2cb5b0777dc6a62 11 4 +ConcernUsage nestedMetadata f66764928aa76a1b 11 0 +ConcernUsage nestedOccurrence e2cb5b0777dc6a62 11 4 +ConcernUsage nestedPart e2cb5b0777dc6a62 11 4 +ConcernUsage nestedPort f66764928aa76a1b 11 0 +ConcernUsage nestedReference 5ed0f764cf144766 11 4 +ConcernUsage nestedRendering f66764928aa76a1b 11 0 +ConcernUsage nestedRequirement f66764928aa76a1b 11 0 +ConcernUsage nestedState f66764928aa76a1b 11 0 +ConcernUsage nestedTransition f66764928aa76a1b 11 0 +ConcernUsage nestedUsage 70734bfe504c7d3f 11 4 +ConcernUsage nestedUseCase f66764928aa76a1b 11 0 +ConcernUsage nestedVerificationCase f66764928aa76a1b 11 0 +ConcernUsage nestedView f66764928aa76a1b 11 0 +ConcernUsage nestedViewpoint f66764928aa76a1b 11 0 +ConcernUsage occurrenceDefinition b807c69764eb4619 11 3 +ConcernUsage output f66764928aa76a1b 11 0 +ConcernUsage ownedAnnotation f66764928aa76a1b 11 0 +ConcernUsage ownedConjugator 07b0700da59410cc 11 0 +ConcernUsage ownedCrossSubsetting 07b0700da59410cc 11 0 +ConcernUsage ownedDifferencing f66764928aa76a1b 11 0 +ConcernUsage ownedDisjoining f66764928aa76a1b 11 0 +ConcernUsage ownedElement 812bc985132fa531 11 4 +ConcernUsage ownedEndFeature f66764928aa76a1b 11 0 +ConcernUsage ownedFeature 70734bfe504c7d3f 11 4 +ConcernUsage ownedFeatureChaining f66764928aa76a1b 11 0 +ConcernUsage ownedFeatureInverting f66764928aa76a1b 11 0 +ConcernUsage ownedFeatureMembership bba08ac7c48120c9 11 4 +ConcernUsage ownedImport f66764928aa76a1b 11 0 +ConcernUsage ownedIntersecting f66764928aa76a1b 11 0 +ConcernUsage ownedMember 812bc985132fa531 11 4 +ConcernUsage ownedMembership e425902157fdb702 11 4 +ConcernUsage ownedRedefinition f66764928aa76a1b 11 0 +ConcernUsage ownedReferenceSubsetting 1dbc0818a9722891 11 4 +ConcernUsage ownedRelationship 239574aaa08e3660 11 11 +ConcernUsage ownedSpecialization 957e6c719654ff7f 11 11 +ConcernUsage ownedSubsetting b4c6af4d12e6417c 11 11 +ConcernUsage ownedTypeFeaturing f66764928aa76a1b 11 0 +ConcernUsage ownedTyping c786fabfddf3d3c4 11 2 +ConcernUsage ownedUnioning f66764928aa76a1b 11 0 +ConcernUsage owner 0901ef20574bf8f5 11 11 +ConcernUsage owningDefinition 36522e4f8c31cf82 11 2 +ConcernUsage owningFeatureMembership ffab2319185aa3e8 11 7 +ConcernUsage owningMembership 73b01ee6059f7f31 11 11 +ConcernUsage owningNamespace 0901ef20574bf8f5 11 11 +ConcernUsage owningRelationship 73b01ee6059f7f31 11 11 +ConcernUsage owningType 73c6ad8ed5803779 11 7 +ConcernUsage owningUsage 4524ef4ceee278c3 11 5 +ConcernUsage parameter 70734bfe504c7d3f 11 4 +ConcernUsage portionKind 07b0700da59410cc 11 0 +ConcernUsage predicate e420a1fbec28a445 11 3 +ConcernUsage qualifiedName 3f4b71759b8d79bb 11 11 +ConcernUsage reqId 07b0700da59410cc 11 0 +ConcernUsage requiredConstraint f66764928aa76a1b 11 0 +ConcernUsage requirementDefinition e420a1fbec28a445 11 3 +ConcernUsage result bec7d3ef3c7fbc95 11 0 +ConcernUsage shortName 07b0700da59410cc 11 0 +ConcernUsage stakeholderParameter e2cb5b0777dc6a62 11 4 +ConcernUsage subjectParameter 472f774bb5b4b34c 11 4 +ConcernUsage text 70b5348ae3fae736 11 2 +ConcernUsage textualRepresentation f66764928aa76a1b 11 0 +ConcernUsage type b807c69764eb4619 11 3 +ConcernUsage unioningType f66764928aa76a1b 11 0 +ConcernUsage usage 70734bfe504c7d3f 11 4 +ConcernUsage variant f66764928aa76a1b 11 0 +ConcernUsage variantMembership f66764928aa76a1b 11 0 +ConjugatedPortDefinition aliasIds 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition conjugatedPortDefinition 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition declaredName 50c767565f3a341f 91 91 +ConjugatedPortDefinition declaredShortName 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition differencingType 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition directedFeature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition directedUsage 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition documentation 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition elementId eca90df0b7586ff8 91 91 +ConjugatedPortDefinition endFeature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition feature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition featureMembership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition importedMembership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition inheritedFeature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition inheritedMembership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition input 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition intersectingType 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition isAbstract 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition isConjugated 118e8eb459b4e651 91 91 +ConjugatedPortDefinition isImpliedIncluded 118e8eb459b4e651 91 91 +ConjugatedPortDefinition isIndividual 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition isLibraryElement f5ee9883cd100e2d 91 7 +ConjugatedPortDefinition isSufficient 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition isVariation 131b6039e5ed8222 91 0 +ConjugatedPortDefinition member 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition membership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition multiplicity 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition name 50c767565f3a341f 91 91 +ConjugatedPortDefinition originalPortDefinition a9661004b9e7b7b0 91 91 +ConjugatedPortDefinition output 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedAction 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedAllocation 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedAnalysisCase 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedAnnotation 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedAttribute 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedCalculation 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedCase 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedConcern 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedConjugator f676af240690c025 91 91 +ConjugatedPortDefinition ownedConnection 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedConstraint 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedDifferencing 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedDisjoining 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedElement 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedEndFeature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedEnumeration 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedFeature 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedFeatureMembership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedFlow 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedImport 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedInterface 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedIntersecting 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedItem 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedMember 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedMembership 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedMetadata 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedOccurrence 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedPart 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedPort 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedPortConjugator f676af240690c025 91 91 +ConjugatedPortDefinition ownedReference 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedRelationship c5324f9ab50a21c9 91 91 +ConjugatedPortDefinition ownedRendering 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedRequirement 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedSpecialization 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedState 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedSubclassification 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedTransition 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedUnioning 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedUsage 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedUseCase 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedVerificationCase 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedView 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition ownedViewpoint 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition owner a9661004b9e7b7b0 91 91 +ConjugatedPortDefinition owningMembership e174e5292945be10 91 91 +ConjugatedPortDefinition owningNamespace a9661004b9e7b7b0 91 91 +ConjugatedPortDefinition owningRelationship e174e5292945be10 91 91 +ConjugatedPortDefinition qualifiedName 3a8887e455e17c82 91 91 +ConjugatedPortDefinition shortName 722ce1aaf77f3206 91 0 +ConjugatedPortDefinition textualRepresentation 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition unioningType 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition usage 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition variant 26022f3f5c5d0029 91 0 +ConjugatedPortDefinition variantMembership 26022f3f5c5d0029 91 0 +ConjugatedPortTyping aliasIds 52b5964975d5e4a8 48 0 +ConjugatedPortTyping conjugatedPortDefinition fa532269da7a76c1 48 48 +ConjugatedPortTyping declaredName 48659858cc4fc664 48 0 +ConjugatedPortTyping declaredShortName 48659858cc4fc664 48 0 +ConjugatedPortTyping documentation 52b5964975d5e4a8 48 0 +ConjugatedPortTyping elementId 6254de059f242bf0 48 48 +ConjugatedPortTyping general fa532269da7a76c1 48 48 +ConjugatedPortTyping isImplied d31bc33992376ca8 48 0 +ConjugatedPortTyping isImpliedIncluded 2b066958e5ede950 48 48 +ConjugatedPortTyping isLibraryElement d31bc33992376ca8 48 0 +ConjugatedPortTyping name 48659858cc4fc664 48 0 +ConjugatedPortTyping ownedAnnotation 52b5964975d5e4a8 48 0 +ConjugatedPortTyping ownedElement 52b5964975d5e4a8 48 0 +ConjugatedPortTyping ownedRelatedElement 52b5964975d5e4a8 48 0 +ConjugatedPortTyping ownedRelationship 52b5964975d5e4a8 48 0 +ConjugatedPortTyping owner 48659858cc4fc664 48 0 +ConjugatedPortTyping owningFeature 8ce940f2166550f6 48 48 +ConjugatedPortTyping owningMembership 48659858cc4fc664 48 0 +ConjugatedPortTyping owningNamespace 48659858cc4fc664 48 0 +ConjugatedPortTyping owningRelatedElement 8ce940f2166550f6 48 48 +ConjugatedPortTyping owningRelationship 48659858cc4fc664 48 0 +ConjugatedPortTyping owningType 8ce940f2166550f6 48 48 +ConjugatedPortTyping portDefinition 7f3db49808563738 48 0 +ConjugatedPortTyping qualifiedName 48659858cc4fc664 48 0 +ConjugatedPortTyping relatedElement 0ede60dafae7fbfd 48 48 +ConjugatedPortTyping shortName 48659858cc4fc664 48 0 +ConjugatedPortTyping source 87667e1d7df36a56 48 48 +ConjugatedPortTyping specific 8ce940f2166550f6 48 48 +ConjugatedPortTyping target 879e124b6e9d208b 48 48 +ConjugatedPortTyping textualRepresentation 52b5964975d5e4a8 48 0 +ConjugatedPortTyping type fa532269da7a76c1 48 48 +ConjugatedPortTyping typedFeature 8ce940f2166550f6 48 48 +ConnectionDefinition aliasIds 2eecee825df0708e 26 0 +ConnectionDefinition associationEnd 6b814091254f4d0c 26 24 +ConnectionDefinition connectionEnd 6b814091254f4d0c 26 24 +ConnectionDefinition declaredName d4b218ba5022e937 26 26 +ConnectionDefinition declaredShortName 1623a0f20f8361b4 26 0 +ConnectionDefinition differencingType 2eecee825df0708e 26 0 +ConnectionDefinition directedFeature 2eecee825df0708e 26 0 +ConnectionDefinition directedUsage 2eecee825df0708e 26 0 +ConnectionDefinition documentation 2eecee825df0708e 26 0 +ConnectionDefinition elementId 7d7eaae476bfbf68 26 26 +ConnectionDefinition endFeature 6b814091254f4d0c 26 24 +ConnectionDefinition feature e1c7bca6ecf99c7b 26 24 +ConnectionDefinition featureMembership 9a32159947847ffe 26 24 +ConnectionDefinition importedMembership 2eecee825df0708e 26 0 +ConnectionDefinition inheritedFeature 2eecee825df0708e 26 0 +ConnectionDefinition inheritedMembership 2eecee825df0708e 26 0 +ConnectionDefinition input 2eecee825df0708e 26 0 +ConnectionDefinition intersectingType 2eecee825df0708e 26 0 +ConnectionDefinition isAbstract 427f31df7b099f2b 26 3 +ConnectionDefinition isConjugated cdaac4ec44a5ce24 26 0 +ConnectionDefinition isImplied 1623a0f20f8361b4 26 0 +ConnectionDefinition isImpliedIncluded dc3d44f060a0b58e 26 26 +ConnectionDefinition isIndividual 1623a0f20f8361b4 26 0 +ConnectionDefinition isLibraryElement 69104f78862067c2 26 6 +ConnectionDefinition isSufficient dc3d44f060a0b58e 26 26 +ConnectionDefinition isVariation cdaac4ec44a5ce24 26 0 +ConnectionDefinition member 93656971beb36f37 26 24 +ConnectionDefinition membership 4a1c690f16ff6abf 26 24 +ConnectionDefinition multiplicity 1623a0f20f8361b4 26 0 +ConnectionDefinition name d4b218ba5022e937 26 26 +ConnectionDefinition output 2eecee825df0708e 26 0 +ConnectionDefinition ownedAction 2eecee825df0708e 26 0 +ConnectionDefinition ownedAllocation 2eecee825df0708e 26 0 +ConnectionDefinition ownedAnalysisCase 2eecee825df0708e 26 0 +ConnectionDefinition ownedAnnotation 2eecee825df0708e 26 0 +ConnectionDefinition ownedAttribute 2eecee825df0708e 26 0 +ConnectionDefinition ownedCalculation 2eecee825df0708e 26 0 +ConnectionDefinition ownedCase 2eecee825df0708e 26 0 +ConnectionDefinition ownedConcern 2eecee825df0708e 26 0 +ConnectionDefinition ownedConjugator 1623a0f20f8361b4 26 0 +ConnectionDefinition ownedConnection 2eecee825df0708e 26 0 +ConnectionDefinition ownedConstraint 2eecee825df0708e 26 0 +ConnectionDefinition ownedDifferencing 2eecee825df0708e 26 0 +ConnectionDefinition ownedDisjoining 2eecee825df0708e 26 0 +ConnectionDefinition ownedElement 93656971beb36f37 26 24 +ConnectionDefinition ownedEndFeature 6b814091254f4d0c 26 24 +ConnectionDefinition ownedEnumeration 2eecee825df0708e 26 0 +ConnectionDefinition ownedFeature e1c7bca6ecf99c7b 26 24 +ConnectionDefinition ownedFeatureMembership 9a32159947847ffe 26 24 +ConnectionDefinition ownedFlow 2eecee825df0708e 26 0 +ConnectionDefinition ownedImport 2eecee825df0708e 26 0 +ConnectionDefinition ownedInterface bb1bd616dd831db7 26 12 +ConnectionDefinition ownedIntersecting 2eecee825df0708e 26 0 +ConnectionDefinition ownedItem 91c178ff7975f91e 26 11 +ConnectionDefinition ownedMember 93656971beb36f37 26 24 +ConnectionDefinition ownedMembership 4a1c690f16ff6abf 26 24 +ConnectionDefinition ownedMetadata 2eecee825df0708e 26 0 +ConnectionDefinition ownedOccurrence db9ca0d1ccf47ba2 26 12 +ConnectionDefinition ownedPart 76f2b7a0ff0904af 26 2 +ConnectionDefinition ownedPort 78c81654b16ef312 26 1 +ConnectionDefinition ownedReference bb1bd616dd831db7 26 12 +ConnectionDefinition ownedRelatedElement 2eecee825df0708e 26 0 +ConnectionDefinition ownedRelationship 27aab388ecf69bfc 26 26 +ConnectionDefinition ownedRendering 2eecee825df0708e 26 0 +ConnectionDefinition ownedRequirement 2eecee825df0708e 26 0 +ConnectionDefinition ownedSpecialization 64a300e87d54f71b 26 26 +ConnectionDefinition ownedState 2eecee825df0708e 26 0 +ConnectionDefinition ownedSubclassification 64a300e87d54f71b 26 26 +ConnectionDefinition ownedTransition 2eecee825df0708e 26 0 +ConnectionDefinition ownedUnioning 2eecee825df0708e 26 0 +ConnectionDefinition ownedUsage e1c7bca6ecf99c7b 26 24 +ConnectionDefinition ownedUseCase 2eecee825df0708e 26 0 +ConnectionDefinition ownedVerificationCase 2eecee825df0708e 26 0 +ConnectionDefinition ownedView 2eecee825df0708e 26 0 +ConnectionDefinition ownedViewpoint 2eecee825df0708e 26 0 +ConnectionDefinition owner e1b68ce00c2f2314 26 26 +ConnectionDefinition owningMembership 7131fc8117c9f2e3 26 26 +ConnectionDefinition owningNamespace e1b68ce00c2f2314 26 26 +ConnectionDefinition owningRelatedElement 1623a0f20f8361b4 26 0 +ConnectionDefinition owningRelationship 7131fc8117c9f2e3 26 26 +ConnectionDefinition qualifiedName 322e3aa2f3493b23 26 26 +ConnectionDefinition relatedElement 2eecee825df0708e 26 0 +ConnectionDefinition relatedType c3ec0cd9fe762f26 26 23 +ConnectionDefinition shortName 1623a0f20f8361b4 26 0 +ConnectionDefinition source 2eecee825df0708e 26 0 +ConnectionDefinition sourceType 1da2d754991be660 26 23 +ConnectionDefinition target 2eecee825df0708e 26 0 +ConnectionDefinition targetType 6e5c628758bee237 26 23 +ConnectionDefinition textualRepresentation 2eecee825df0708e 26 0 +ConnectionDefinition unioningType 2eecee825df0708e 26 0 +ConnectionDefinition usage e1c7bca6ecf99c7b 26 24 +ConnectionDefinition variant 2eecee825df0708e 26 0 +ConnectionDefinition variantMembership 2eecee825df0708e 26 0 +ConnectionUsage aliasIds 76c5a4cdd85efb74 72 0 +ConnectionUsage association 80f10333497fc3bd 72 19 +ConnectionUsage chainingFeature 76c5a4cdd85efb74 72 0 +ConnectionUsage connectionDefinition 80f10333497fc3bd 72 19 +ConnectionUsage connectorEnd 784c373031d53d28 72 67 +ConnectionUsage crossFeature 6a8adab2e0cdd568 72 0 +ConnectionUsage declaredName 105b74b733110dc9 72 13 +ConnectionUsage declaredShortName 6a8adab2e0cdd568 72 0 +ConnectionUsage defaultFeaturingType 929dc8ea1660f75a 72 52 +ConnectionUsage definition 80f10333497fc3bd 72 19 +ConnectionUsage differencingType 76c5a4cdd85efb74 72 0 +ConnectionUsage directedFeature 76c5a4cdd85efb74 72 0 +ConnectionUsage directedUsage 76c5a4cdd85efb74 72 0 +ConnectionUsage direction 6a8adab2e0cdd568 72 0 +ConnectionUsage documentation 76c5a4cdd85efb74 72 0 +ConnectionUsage elementId eaa79d4ab9ae6aec 72 72 +ConnectionUsage endFeature 784c373031d53d28 72 67 +ConnectionUsage endOwningType 6a8adab2e0cdd568 72 0 +ConnectionUsage feature e7bffb195ed96d4f 72 67 +ConnectionUsage featureMembership 6695b781ac947a96 72 67 +ConnectionUsage featureTarget b65ee9c9caba3d9c 72 0 +ConnectionUsage featuringType 76c5a4cdd85efb74 72 0 +ConnectionUsage importedMembership 76c5a4cdd85efb74 72 0 +ConnectionUsage individualDefinition 6a8adab2e0cdd568 72 0 +ConnectionUsage inheritedFeature 76c5a4cdd85efb74 72 0 +ConnectionUsage inheritedMembership 76c5a4cdd85efb74 72 0 +ConnectionUsage input 76c5a4cdd85efb74 72 0 +ConnectionUsage intersectingType 76c5a4cdd85efb74 72 0 +ConnectionUsage isAbstract 6ab660996a41265d 72 5 +ConnectionUsage isComposite 15029c3ffc548700 72 52 +ConnectionUsage isConjugated 98fed713b5a2470c 72 0 +ConnectionUsage isConstant 98fed713b5a2470c 72 0 +ConnectionUsage isDerived 98fed713b5a2470c 72 0 +ConnectionUsage isEnd 98fed713b5a2470c 72 0 +ConnectionUsage isImplied 6a8adab2e0cdd568 72 0 +ConnectionUsage isImpliedIncluded 3e087e58a6866c44 72 72 +ConnectionUsage isIndividual 6a8adab2e0cdd568 72 0 +ConnectionUsage isLibraryElement 6ab660996a41265d 72 5 +ConnectionUsage isOrdered 98fed713b5a2470c 72 0 +ConnectionUsage isPortion 6a8adab2e0cdd568 72 0 +ConnectionUsage isReference c204b92c5fd42c50 72 20 +ConnectionUsage isSufficient 6a8adab2e0cdd568 72 0 +ConnectionUsage isUnique 6c50f4d2f1e78cf3 72 67 +ConnectionUsage isVariable 6a8adab2e0cdd568 72 0 +ConnectionUsage isVariation 98fed713b5a2470c 72 0 +ConnectionUsage itemDefinition 80f10333497fc3bd 72 19 +ConnectionUsage mayTimeVary 6a8adab2e0cdd568 72 0 +ConnectionUsage member 3ab7009bead38862 72 72 +ConnectionUsage membership 7f384a982b2c55c7 72 72 +ConnectionUsage multiplicity 9c2c92fc34232693 72 7 +ConnectionUsage name 105b74b733110dc9 72 13 +ConnectionUsage nestedAction 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedAllocation 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedAnalysisCase 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedAttribute 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedCalculation 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedCase 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedConcern 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedConnection 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedConstraint 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedEnumeration 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedFlow 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedInterface 5bae9b18bfe05fcc 72 62 +ConnectionUsage nestedItem 276279a7a0b59f15 72 1 +ConnectionUsage nestedMetadata 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedOccurrence 2c037d25570f3f2f 72 2 +ConnectionUsage nestedPart 276279a7a0b59f15 72 1 +ConnectionUsage nestedPort 7b66a84b8eb89b8e 72 1 +ConnectionUsage nestedReference 5bae9b18bfe05fcc 72 62 +ConnectionUsage nestedRendering 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedRequirement 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedState 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedTransition 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedUsage e7bffb195ed96d4f 72 67 +ConnectionUsage nestedUseCase 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedVerificationCase 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedView 76c5a4cdd85efb74 72 0 +ConnectionUsage nestedViewpoint 76c5a4cdd85efb74 72 0 +ConnectionUsage occurrenceDefinition 80f10333497fc3bd 72 19 +ConnectionUsage output 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedAnnotation 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedConjugator 6a8adab2e0cdd568 72 0 +ConnectionUsage ownedCrossSubsetting 6a8adab2e0cdd568 72 0 +ConnectionUsage ownedDifferencing 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedDisjoining 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedElement 3ab7009bead38862 72 72 +ConnectionUsage ownedEndFeature 784c373031d53d28 72 67 +ConnectionUsage ownedFeature e7bffb195ed96d4f 72 67 +ConnectionUsage ownedFeatureChaining 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedFeatureInverting 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedFeatureMembership 6695b781ac947a96 72 67 +ConnectionUsage ownedImport 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedIntersecting 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedMember 3ab7009bead38862 72 72 +ConnectionUsage ownedMembership 7f384a982b2c55c7 72 72 +ConnectionUsage ownedRedefinition 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedReferenceSubsetting 6a8adab2e0cdd568 72 0 +ConnectionUsage ownedRelatedElement 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedRelationship 2c1a24d5992b0222 72 72 +ConnectionUsage ownedSpecialization 6d6c697cf720c591 72 72 +ConnectionUsage ownedSubsetting c65986d1c182832d 72 72 +ConnectionUsage ownedTypeFeaturing 76c5a4cdd85efb74 72 0 +ConnectionUsage ownedTyping 0265ae75aaa81548 72 19 +ConnectionUsage ownedUnioning 76c5a4cdd85efb74 72 0 +ConnectionUsage owner fe6bb9b9cb58797e 72 72 +ConnectionUsage owningDefinition c189dd7320d4a77e 72 19 +ConnectionUsage owningFeatureMembership a50ad53b22643d5d 72 52 +ConnectionUsage owningMembership 4b50a14f6fc0c771 72 72 +ConnectionUsage owningNamespace fe6bb9b9cb58797e 72 72 +ConnectionUsage owningRelatedElement 6a8adab2e0cdd568 72 0 +ConnectionUsage owningRelationship 4b50a14f6fc0c771 72 72 +ConnectionUsage owningType f125354261a5c1a8 72 52 +ConnectionUsage owningUsage 9a263282219eef92 72 33 +ConnectionUsage partDefinition 80f10333497fc3bd 72 19 +ConnectionUsage portionKind 6a8adab2e0cdd568 72 0 +ConnectionUsage qualifiedName 47e8edaccbc82990 72 13 +ConnectionUsage relatedElement 76c5a4cdd85efb74 72 0 +ConnectionUsage relatedFeature aa43f3ff91b9989c 72 67 +ConnectionUsage shortName 6a8adab2e0cdd568 72 0 +ConnectionUsage source 76c5a4cdd85efb74 72 0 +ConnectionUsage sourceFeature 49a47fc3955e283c 72 67 +ConnectionUsage target 76c5a4cdd85efb74 72 0 +ConnectionUsage targetFeature c3557ca939223617 72 67 +ConnectionUsage textualRepresentation 76c5a4cdd85efb74 72 0 +ConnectionUsage type 80f10333497fc3bd 72 19 +ConnectionUsage unioningType 76c5a4cdd85efb74 72 0 +ConnectionUsage usage e7bffb195ed96d4f 72 67 +ConnectionUsage variant 76c5a4cdd85efb74 72 0 +ConnectionUsage variantMembership 76c5a4cdd85efb74 72 0 +ConstraintDefinition aliasIds d454915277962f88 21 0 +ConstraintDefinition declaredName 46fa63e999683722 21 21 +ConstraintDefinition declaredShortName b11350d15d380405 21 0 +ConstraintDefinition differencingType d454915277962f88 21 0 +ConstraintDefinition directedFeature 3e345ff126586ab1 21 13 +ConstraintDefinition directedUsage 3e345ff126586ab1 21 13 +ConstraintDefinition documentation d454915277962f88 21 0 +ConstraintDefinition elementId a60a76d908914f38 21 21 +ConstraintDefinition endFeature d454915277962f88 21 0 +ConstraintDefinition expression aa13cc52f0915164 21 17 +ConstraintDefinition feature 416d99ca7ac3e286 21 20 +ConstraintDefinition featureMembership d91d3603c39ff386 21 20 +ConstraintDefinition importedMembership d454915277962f88 21 0 +ConstraintDefinition inheritedFeature d454915277962f88 21 0 +ConstraintDefinition inheritedMembership d454915277962f88 21 0 +ConstraintDefinition input 3e345ff126586ab1 21 13 +ConstraintDefinition intersectingType d454915277962f88 21 0 +ConstraintDefinition isAbstract caa7e38c2b0f4f73 21 0 +ConstraintDefinition isConjugated caa7e38c2b0f4f73 21 0 +ConstraintDefinition isImpliedIncluded 09b4e47ca24a163c 21 21 +ConstraintDefinition isIndividual b11350d15d380405 21 0 +ConstraintDefinition isLibraryElement caa7e38c2b0f4f73 21 0 +ConstraintDefinition isModelLevelEvaluable caa7e38c2b0f4f73 21 0 +ConstraintDefinition isSufficient caa7e38c2b0f4f73 21 0 +ConstraintDefinition isVariation caa7e38c2b0f4f73 21 0 +ConstraintDefinition member 416d99ca7ac3e286 21 20 +ConstraintDefinition membership d91d3603c39ff386 21 20 +ConstraintDefinition multiplicity b11350d15d380405 21 0 +ConstraintDefinition name 46fa63e999683722 21 21 +ConstraintDefinition output d454915277962f88 21 0 +ConstraintDefinition ownedAction d454915277962f88 21 0 +ConstraintDefinition ownedAllocation d454915277962f88 21 0 +ConstraintDefinition ownedAnalysisCase d454915277962f88 21 0 +ConstraintDefinition ownedAnnotation d454915277962f88 21 0 +ConstraintDefinition ownedAttribute 6bf8063711ff8311 21 9 +ConstraintDefinition ownedCalculation d454915277962f88 21 0 +ConstraintDefinition ownedCase d454915277962f88 21 0 +ConstraintDefinition ownedConcern d454915277962f88 21 0 +ConstraintDefinition ownedConjugator b11350d15d380405 21 0 +ConstraintDefinition ownedConnection d454915277962f88 21 0 +ConstraintDefinition ownedConstraint ee10cdfd67473ffe 21 1 +ConstraintDefinition ownedDifferencing d454915277962f88 21 0 +ConstraintDefinition ownedDisjoining d454915277962f88 21 0 +ConstraintDefinition ownedElement 416d99ca7ac3e286 21 20 +ConstraintDefinition ownedEndFeature d454915277962f88 21 0 +ConstraintDefinition ownedEnumeration d454915277962f88 21 0 +ConstraintDefinition ownedFeature 416d99ca7ac3e286 21 20 +ConstraintDefinition ownedFeatureMembership d91d3603c39ff386 21 20 +ConstraintDefinition ownedFlow d454915277962f88 21 0 +ConstraintDefinition ownedImport d454915277962f88 21 0 +ConstraintDefinition ownedInterface 3e345ff126586ab1 21 13 +ConstraintDefinition ownedIntersecting d454915277962f88 21 0 +ConstraintDefinition ownedItem d454915277962f88 21 0 +ConstraintDefinition ownedMember 416d99ca7ac3e286 21 20 +ConstraintDefinition ownedMembership d91d3603c39ff386 21 20 +ConstraintDefinition ownedMetadata d454915277962f88 21 0 +ConstraintDefinition ownedOccurrence ee10cdfd67473ffe 21 1 +ConstraintDefinition ownedPart d454915277962f88 21 0 +ConstraintDefinition ownedPort d454915277962f88 21 0 +ConstraintDefinition ownedReference 3e345ff126586ab1 21 13 +ConstraintDefinition ownedRelationship c33cd99d134d1a5e 21 21 +ConstraintDefinition ownedRendering d454915277962f88 21 0 +ConstraintDefinition ownedRequirement d454915277962f88 21 0 +ConstraintDefinition ownedSpecialization 7271ea44e0ee012e 21 21 +ConstraintDefinition ownedState d454915277962f88 21 0 +ConstraintDefinition ownedSubclassification 7271ea44e0ee012e 21 21 +ConstraintDefinition ownedTransition d454915277962f88 21 0 +ConstraintDefinition ownedUnioning d454915277962f88 21 0 +ConstraintDefinition ownedUsage d43b6e286e45421e 21 20 +ConstraintDefinition ownedUseCase d454915277962f88 21 0 +ConstraintDefinition ownedVerificationCase d454915277962f88 21 0 +ConstraintDefinition ownedView d454915277962f88 21 0 +ConstraintDefinition ownedViewpoint d454915277962f88 21 0 +ConstraintDefinition owner fcdb5ce2cf279ae0 21 21 +ConstraintDefinition owningMembership 078f3055385a0f24 21 21 +ConstraintDefinition owningNamespace fcdb5ce2cf279ae0 21 21 +ConstraintDefinition owningRelationship 078f3055385a0f24 21 21 +ConstraintDefinition parameter 3e345ff126586ab1 21 13 +ConstraintDefinition qualifiedName 0f4828392ab211f4 21 21 +ConstraintDefinition result 779536d9f7bbb6b9 21 0 +ConstraintDefinition shortName b11350d15d380405 21 0 +ConstraintDefinition step aa13cc52f0915164 21 17 +ConstraintDefinition textualRepresentation d454915277962f88 21 0 +ConstraintDefinition unioningType d454915277962f88 21 0 +ConstraintDefinition usage d43b6e286e45421e 21 20 +ConstraintDefinition variant d454915277962f88 21 0 +ConstraintDefinition variantMembership d454915277962f88 21 0 +ConstraintUsage aliasIds 6a2b31da0f5ce50c 73 0 +ConstraintUsage behavior 0aa319825bf1482e 73 26 +ConstraintUsage chainingFeature 6a2b31da0f5ce50c 73 0 +ConstraintUsage constraintDefinition 85398529cbf53325 73 26 +ConstraintUsage crossFeature 36f7fb2a22ecfc89 73 0 +ConstraintUsage declaredName 75e6092e697966d8 73 19 +ConstraintUsage declaredShortName 36f7fb2a22ecfc89 73 0 +ConstraintUsage definition 0aa319825bf1482e 73 26 +ConstraintUsage differencingType 6a2b31da0f5ce50c 73 0 +ConstraintUsage directedFeature 2d309bfce87c5f34 73 7 +ConstraintUsage directedUsage 2d309bfce87c5f34 73 7 +ConstraintUsage direction 36f7fb2a22ecfc89 73 0 +ConstraintUsage documentation 7fc519d73fbe1674 73 7 +ConstraintUsage elementId 6b7991b4a86651cc 73 73 +ConstraintUsage endFeature 6a2b31da0f5ce50c 73 0 +ConstraintUsage endOwningType 36f7fb2a22ecfc89 73 0 +ConstraintUsage feature d1b95ed415dfd885 73 55 +ConstraintUsage featureMembership fe881b8f7ed0cc13 73 55 +ConstraintUsage featureTarget 8e54cb029de968bd 73 0 +ConstraintUsage featuringType 6a2b31da0f5ce50c 73 0 +ConstraintUsage function 85398529cbf53325 73 26 +ConstraintUsage importedMembership 6a2b31da0f5ce50c 73 0 +ConstraintUsage individualDefinition 36f7fb2a22ecfc89 73 0 +ConstraintUsage inheritedFeature 6a2b31da0f5ce50c 73 0 +ConstraintUsage inheritedMembership 6a2b31da0f5ce50c 73 0 +ConstraintUsage input 2d309bfce87c5f34 73 7 +ConstraintUsage intersectingType 6a2b31da0f5ce50c 73 0 +ConstraintUsage isAbstract ddca65612cc45883 73 0 +ConstraintUsage isComposite 47fe85adb0176f47 73 68 +ConstraintUsage isConjugated ddca65612cc45883 73 0 +ConstraintUsage isConstant ddca65612cc45883 73 0 +ConstraintUsage isDerived ddca65612cc45883 73 0 +ConstraintUsage isEnd ddca65612cc45883 73 0 +ConstraintUsage isImpliedIncluded 80f7fbf90963fd90 73 73 +ConstraintUsage isIndividual 36f7fb2a22ecfc89 73 0 +ConstraintUsage isLibraryElement ddca65612cc45883 73 0 +ConstraintUsage isModelLevelEvaluable ddca65612cc45883 73 0 +ConstraintUsage isOrdered ddca65612cc45883 73 0 +ConstraintUsage isPortion 36f7fb2a22ecfc89 73 0 +ConstraintUsage isReference 16c3dbac8610e6cc 73 5 +ConstraintUsage isSufficient 36f7fb2a22ecfc89 73 0 +ConstraintUsage isUnique 80f7fbf90963fd90 73 73 +ConstraintUsage isVariable 36f7fb2a22ecfc89 73 0 +ConstraintUsage isVariation ddca65612cc45883 73 0 +ConstraintUsage mayTimeVary 36f7fb2a22ecfc89 73 0 +ConstraintUsage member 329c2821c4bec7cd 73 59 +ConstraintUsage membership 2e565615ab0343e2 73 59 +ConstraintUsage multiplicity 36f7fb2a22ecfc89 73 0 +ConstraintUsage name 85e2d03eca0e6d18 73 36 +ConstraintUsage nestedAction 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedAllocation 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedAnalysisCase 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedAttribute 61c6cd07ce177c03 73 6 +ConstraintUsage nestedCalculation 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedCase 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedConcern 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedConnection 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedConstraint 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedEnumeration 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedFlow 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedInterface a8b960c28d38b366 73 12 +ConstraintUsage nestedItem 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedMetadata 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedOccurrence 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedPart 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedPort 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedReference a8b960c28d38b366 73 12 +ConstraintUsage nestedRendering 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedRequirement 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedState 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedTransition 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedUsage a054fbf04bf34a5d 73 18 +ConstraintUsage nestedUseCase 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedVerificationCase 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedView 6a2b31da0f5ce50c 73 0 +ConstraintUsage nestedViewpoint 6a2b31da0f5ce50c 73 0 +ConstraintUsage occurrenceDefinition 0aa319825bf1482e 73 26 +ConstraintUsage output 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedAnnotation 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedConjugator 36f7fb2a22ecfc89 73 0 +ConstraintUsage ownedCrossSubsetting 36f7fb2a22ecfc89 73 0 +ConstraintUsage ownedDifferencing 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedDisjoining 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedElement e9807409fbca29cc 73 60 +ConstraintUsage ownedEndFeature 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedFeature d1b95ed415dfd885 73 55 +ConstraintUsage ownedFeatureChaining 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedFeatureInverting 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedFeatureMembership fe881b8f7ed0cc13 73 55 +ConstraintUsage ownedImport 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedIntersecting 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedMember 329c2821c4bec7cd 73 59 +ConstraintUsage ownedMembership 2e565615ab0343e2 73 59 +ConstraintUsage ownedRedefinition 3806fe84ee6dd381 73 1 +ConstraintUsage ownedReferenceSubsetting c8eed2f8b7e77961 73 18 +ConstraintUsage ownedRelationship f559333a6bc7759e 73 73 +ConstraintUsage ownedSpecialization 0a90d0d3e8d2a442 73 73 +ConstraintUsage ownedSubsetting c79a321538caeb5f 73 73 +ConstraintUsage ownedTypeFeaturing 6a2b31da0f5ce50c 73 0 +ConstraintUsage ownedTyping 6de7442a27451473 73 12 +ConstraintUsage ownedUnioning 6a2b31da0f5ce50c 73 0 +ConstraintUsage owner 2b75e7e46428d03f 73 73 +ConstraintUsage owningDefinition d74945d39b9faa2c 73 25 +ConstraintUsage owningFeatureMembership 7bb19becc37b4654 73 68 +ConstraintUsage owningMembership 6a9a47ffe3b61c1c 73 73 +ConstraintUsage owningNamespace 2b75e7e46428d03f 73 73 +ConstraintUsage owningRelationship 6a9a47ffe3b61c1c 73 73 +ConstraintUsage owningType 3f2e85adcc63922f 73 68 +ConstraintUsage owningUsage 9edd3b0453b0e48c 73 43 +ConstraintUsage parameter 2d309bfce87c5f34 73 7 +ConstraintUsage portionKind 36f7fb2a22ecfc89 73 0 +ConstraintUsage predicate 85398529cbf53325 73 26 +ConstraintUsage qualifiedName 8e43279ca18afee4 73 36 +ConstraintUsage result 8e54cb029de968bd 73 0 +ConstraintUsage shortName fba030b523b04d82 73 10 +ConstraintUsage textualRepresentation 6a2b31da0f5ce50c 73 0 +ConstraintUsage type 0aa319825bf1482e 73 26 +ConstraintUsage unioningType 6a2b31da0f5ce50c 73 0 +ConstraintUsage usage a054fbf04bf34a5d 73 18 +ConstraintUsage variant 6a2b31da0f5ce50c 73 0 +ConstraintUsage variantMembership 6a2b31da0f5ce50c 73 0 +ConstructorExpression aliasIds f8ff85c6262ce9f1 90 0 +ConstructorExpression argument 4b17a1302eeeaa7a 90 71 +ConstructorExpression behavior f8ff85c6262ce9f1 90 0 +ConstructorExpression chainingFeature f8ff85c6262ce9f1 90 0 +ConstructorExpression crossFeature 1f0803963818dc65 90 0 +ConstructorExpression declaredName 1f0803963818dc65 90 0 +ConstructorExpression declaredShortName 1f0803963818dc65 90 0 +ConstructorExpression differencingType f8ff85c6262ce9f1 90 0 +ConstructorExpression directedFeature ee66e2732b606d84 90 71 +ConstructorExpression direction 1f0803963818dc65 90 0 +ConstructorExpression documentation f8ff85c6262ce9f1 90 0 +ConstructorExpression elementId 1625ffaab0f7e048 90 90 +ConstructorExpression endFeature f8ff85c6262ce9f1 90 0 +ConstructorExpression endOwningType 1f0803963818dc65 90 0 +ConstructorExpression feature ee66e2732b606d84 90 71 +ConstructorExpression featureMembership 239abedeeddacb5b 90 71 +ConstructorExpression featureTarget f0710cdf84584090 90 0 +ConstructorExpression featuringType f8ff85c6262ce9f1 90 0 +ConstructorExpression function 1f0803963818dc65 90 0 +ConstructorExpression importedMembership f8ff85c6262ce9f1 90 0 +ConstructorExpression inheritedFeature f8ff85c6262ce9f1 90 0 +ConstructorExpression inheritedMembership f8ff85c6262ce9f1 90 0 +ConstructorExpression input ee66e2732b606d84 90 71 +ConstructorExpression instantiatedType fb341fddbabec0b4 90 90 +ConstructorExpression intersectingType f8ff85c6262ce9f1 90 0 +ConstructorExpression isAbstract 1f0803963818dc65 90 0 +ConstructorExpression isComposite 1f0803963818dc65 90 0 +ConstructorExpression isConjugated 90352bca78f62433 90 0 +ConstructorExpression isConstant 1f0803963818dc65 90 0 +ConstructorExpression isDerived 1f0803963818dc65 90 0 +ConstructorExpression isEnd 1f0803963818dc65 90 0 +ConstructorExpression isImpliedIncluded aea40fc4ab0b5ded 90 90 +ConstructorExpression isLibraryElement 90352bca78f62433 90 0 +ConstructorExpression isModelLevelEvaluable 4e55b8b864e0e60c 90 29 +ConstructorExpression isOrdered 1f0803963818dc65 90 0 +ConstructorExpression isPortion 1f0803963818dc65 90 0 +ConstructorExpression isSufficient 1f0803963818dc65 90 0 +ConstructorExpression isUnique 1f0803963818dc65 90 0 +ConstructorExpression isVariable 1f0803963818dc65 90 0 +ConstructorExpression member afbd0ed181ae0553 90 90 +ConstructorExpression membership e7a8aac0b5437d75 90 90 +ConstructorExpression multiplicity 1f0803963818dc65 90 0 +ConstructorExpression name 1f0803963818dc65 90 0 +ConstructorExpression output f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedAnnotation f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedConjugator 1f0803963818dc65 90 0 +ConstructorExpression ownedCrossSubsetting 1f0803963818dc65 90 0 +ConstructorExpression ownedDifferencing f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedDisjoining f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedElement ee66e2732b606d84 90 71 +ConstructorExpression ownedEndFeature f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedFeature ee66e2732b606d84 90 71 +ConstructorExpression ownedFeatureChaining f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedFeatureInverting f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedFeatureMembership 239abedeeddacb5b 90 71 +ConstructorExpression ownedImport f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedIntersecting f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedMember ee66e2732b606d84 90 71 +ConstructorExpression ownedMembership e7a8aac0b5437d75 90 90 +ConstructorExpression ownedRedefinition f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedReferenceSubsetting 1f0803963818dc65 90 0 +ConstructorExpression ownedRelationship e7a8aac0b5437d75 90 90 +ConstructorExpression ownedSpecialization f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedSubsetting f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedTypeFeaturing f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedTyping f8ff85c6262ce9f1 90 0 +ConstructorExpression ownedUnioning f8ff85c6262ce9f1 90 0 +ConstructorExpression owner a4115053675e7e8b 90 90 +ConstructorExpression owningFeatureMembership b5baeda53c37594d 90 5 +ConstructorExpression owningMembership 117da9cbcca89b60 90 90 +ConstructorExpression owningNamespace a4115053675e7e8b 90 90 +ConstructorExpression owningRelationship 117da9cbcca89b60 90 90 +ConstructorExpression owningType 95731c168bd99e9e 90 5 +ConstructorExpression parameter ee66e2732b606d84 90 71 +ConstructorExpression qualifiedName 1f0803963818dc65 90 0 +ConstructorExpression result f0710cdf84584090 90 0 +ConstructorExpression shortName 1f0803963818dc65 90 0 +ConstructorExpression textualRepresentation f8ff85c6262ce9f1 90 0 +ConstructorExpression type f8ff85c6262ce9f1 90 0 +ConstructorExpression unioningType f8ff85c6262ce9f1 90 0 +CrossSubsetting aliasIds c85478d4c87a6ecf 2 0 +CrossSubsetting crossedFeature 43d631109a8f99e7 2 2 +CrossSubsetting crossingFeature 5651b2069b2c8494 2 2 +CrossSubsetting declaredName 9d8704e5b3c9e177 2 0 +CrossSubsetting declaredShortName 9d8704e5b3c9e177 2 0 +CrossSubsetting documentation c85478d4c87a6ecf 2 0 +CrossSubsetting elementId cab46b7fd9dcbbec 2 2 +CrossSubsetting general 43d631109a8f99e7 2 2 +CrossSubsetting isImplied 4f6822c12ee0db59 2 0 +CrossSubsetting isImpliedIncluded 865fc85cdd08fe03 2 2 +CrossSubsetting isLibraryElement 4f6822c12ee0db59 2 0 +CrossSubsetting name 9d8704e5b3c9e177 2 0 +CrossSubsetting ownedAnnotation c85478d4c87a6ecf 2 0 +CrossSubsetting ownedElement c85478d4c87a6ecf 2 0 +CrossSubsetting ownedRelatedElement 191e6d2af8f579cf 2 2 +CrossSubsetting ownedRelationship c85478d4c87a6ecf 2 0 +CrossSubsetting owner 9d8704e5b3c9e177 2 0 +CrossSubsetting owningFeature 5651b2069b2c8494 2 2 +CrossSubsetting owningMembership 9d8704e5b3c9e177 2 0 +CrossSubsetting owningNamespace 9d8704e5b3c9e177 2 0 +CrossSubsetting owningRelatedElement 5651b2069b2c8494 2 2 +CrossSubsetting owningRelationship 9d8704e5b3c9e177 2 0 +CrossSubsetting owningType 5651b2069b2c8494 2 2 +CrossSubsetting qualifiedName 9d8704e5b3c9e177 2 0 +CrossSubsetting relatedElement afa7b038cb3bfaf4 2 2 +CrossSubsetting shortName 9d8704e5b3c9e177 2 0 +CrossSubsetting source 506ab167e7f74962 2 2 +CrossSubsetting specific 5651b2069b2c8494 2 2 +CrossSubsetting subsettedFeature 43d631109a8f99e7 2 2 +CrossSubsetting subsettingFeature 5651b2069b2c8494 2 2 +CrossSubsetting target 191e6d2af8f579cf 2 2 +CrossSubsetting textualRepresentation c85478d4c87a6ecf 2 0 +DecisionNode actionDefinition 36431934a5be0cc3 6 0 +DecisionNode aliasIds 36431934a5be0cc3 6 0 +DecisionNode behavior 36431934a5be0cc3 6 0 +DecisionNode chainingFeature 36431934a5be0cc3 6 0 +DecisionNode crossFeature a0ff21444582518b 6 0 +DecisionNode declaredName 28cb1c95f729668b 6 2 +DecisionNode declaredShortName a0ff21444582518b 6 0 +DecisionNode definition 36431934a5be0cc3 6 0 +DecisionNode differencingType 36431934a5be0cc3 6 0 +DecisionNode directedFeature 36431934a5be0cc3 6 0 +DecisionNode directedUsage 36431934a5be0cc3 6 0 +DecisionNode direction a0ff21444582518b 6 0 +DecisionNode documentation 36431934a5be0cc3 6 0 +DecisionNode elementId 6feccff43cf552e4 6 6 +DecisionNode endFeature 36431934a5be0cc3 6 0 +DecisionNode endOwningType a0ff21444582518b 6 0 +DecisionNode feature 36431934a5be0cc3 6 0 +DecisionNode featureMembership 36431934a5be0cc3 6 0 +DecisionNode featureTarget 14d52e53ab937ae4 6 0 +DecisionNode featuringType 36431934a5be0cc3 6 0 +DecisionNode importedMembership 36431934a5be0cc3 6 0 +DecisionNode individualDefinition a0ff21444582518b 6 0 +DecisionNode inheritedFeature 36431934a5be0cc3 6 0 +DecisionNode inheritedMembership 36431934a5be0cc3 6 0 +DecisionNode input 36431934a5be0cc3 6 0 +DecisionNode intersectingType 36431934a5be0cc3 6 0 +DecisionNode isAbstract 5b34acf0878918b1 6 0 +DecisionNode isComposite 2654cf9111944b77 6 6 +DecisionNode isConjugated 5b34acf0878918b1 6 0 +DecisionNode isConstant 5b34acf0878918b1 6 0 +DecisionNode isDerived 5b34acf0878918b1 6 0 +DecisionNode isEnd 5b34acf0878918b1 6 0 +DecisionNode isImpliedIncluded 2654cf9111944b77 6 6 +DecisionNode isIndividual a0ff21444582518b 6 0 +DecisionNode isLibraryElement 5b34acf0878918b1 6 0 +DecisionNode isOrdered 5b34acf0878918b1 6 0 +DecisionNode isPortion a0ff21444582518b 6 0 +DecisionNode isReference 5b34acf0878918b1 6 0 +DecisionNode isSufficient a0ff21444582518b 6 0 +DecisionNode isUnique 2654cf9111944b77 6 6 +DecisionNode isVariable a0ff21444582518b 6 0 +DecisionNode isVariation 5b34acf0878918b1 6 0 +DecisionNode mayTimeVary a0ff21444582518b 6 0 +DecisionNode member 36431934a5be0cc3 6 0 +DecisionNode membership 36431934a5be0cc3 6 0 +DecisionNode multiplicity a0ff21444582518b 6 0 +DecisionNode name 28cb1c95f729668b 6 2 +DecisionNode nestedAction 36431934a5be0cc3 6 0 +DecisionNode nestedAllocation 36431934a5be0cc3 6 0 +DecisionNode nestedAnalysisCase 36431934a5be0cc3 6 0 +DecisionNode nestedAttribute 36431934a5be0cc3 6 0 +DecisionNode nestedCalculation 36431934a5be0cc3 6 0 +DecisionNode nestedCase 36431934a5be0cc3 6 0 +DecisionNode nestedConcern 36431934a5be0cc3 6 0 +DecisionNode nestedConnection 36431934a5be0cc3 6 0 +DecisionNode nestedConstraint 36431934a5be0cc3 6 0 +DecisionNode nestedEnumeration 36431934a5be0cc3 6 0 +DecisionNode nestedFlow 36431934a5be0cc3 6 0 +DecisionNode nestedInterface 36431934a5be0cc3 6 0 +DecisionNode nestedItem 36431934a5be0cc3 6 0 +DecisionNode nestedMetadata 36431934a5be0cc3 6 0 +DecisionNode nestedOccurrence 36431934a5be0cc3 6 0 +DecisionNode nestedPart 36431934a5be0cc3 6 0 +DecisionNode nestedPort 36431934a5be0cc3 6 0 +DecisionNode nestedReference 36431934a5be0cc3 6 0 +DecisionNode nestedRendering 36431934a5be0cc3 6 0 +DecisionNode nestedRequirement 36431934a5be0cc3 6 0 +DecisionNode nestedState 36431934a5be0cc3 6 0 +DecisionNode nestedTransition 36431934a5be0cc3 6 0 +DecisionNode nestedUsage 36431934a5be0cc3 6 0 +DecisionNode nestedUseCase 36431934a5be0cc3 6 0 +DecisionNode nestedVerificationCase 36431934a5be0cc3 6 0 +DecisionNode nestedView 36431934a5be0cc3 6 0 +DecisionNode nestedViewpoint 36431934a5be0cc3 6 0 +DecisionNode occurrenceDefinition 36431934a5be0cc3 6 0 +DecisionNode output 36431934a5be0cc3 6 0 +DecisionNode ownedAnnotation 36431934a5be0cc3 6 0 +DecisionNode ownedConjugator a0ff21444582518b 6 0 +DecisionNode ownedCrossSubsetting a0ff21444582518b 6 0 +DecisionNode ownedDifferencing 36431934a5be0cc3 6 0 +DecisionNode ownedDisjoining 36431934a5be0cc3 6 0 +DecisionNode ownedElement 36431934a5be0cc3 6 0 +DecisionNode ownedEndFeature 36431934a5be0cc3 6 0 +DecisionNode ownedFeature 36431934a5be0cc3 6 0 +DecisionNode ownedFeatureChaining 36431934a5be0cc3 6 0 +DecisionNode ownedFeatureInverting 36431934a5be0cc3 6 0 +DecisionNode ownedFeatureMembership 36431934a5be0cc3 6 0 +DecisionNode ownedImport 36431934a5be0cc3 6 0 +DecisionNode ownedIntersecting 36431934a5be0cc3 6 0 +DecisionNode ownedMember 36431934a5be0cc3 6 0 +DecisionNode ownedMembership 36431934a5be0cc3 6 0 +DecisionNode ownedRedefinition 36431934a5be0cc3 6 0 +DecisionNode ownedReferenceSubsetting a0ff21444582518b 6 0 +DecisionNode ownedRelationship 36431934a5be0cc3 6 0 +DecisionNode ownedSpecialization 36431934a5be0cc3 6 0 +DecisionNode ownedSubsetting 36431934a5be0cc3 6 0 +DecisionNode ownedTypeFeaturing 36431934a5be0cc3 6 0 +DecisionNode ownedTyping 36431934a5be0cc3 6 0 +DecisionNode ownedUnioning 36431934a5be0cc3 6 0 +DecisionNode owner 3d89591e713e01e7 6 6 +DecisionNode owningDefinition f6a31343ee45330d 6 3 +DecisionNode owningFeatureMembership f7336699e82ddc93 6 6 +DecisionNode owningMembership f7336699e82ddc93 6 6 +DecisionNode owningNamespace 3d89591e713e01e7 6 6 +DecisionNode owningRelationship f7336699e82ddc93 6 6 +DecisionNode owningType 3d89591e713e01e7 6 6 +DecisionNode owningUsage e7e5671ec87b2065 6 3 +DecisionNode parameter 36431934a5be0cc3 6 0 +DecisionNode portionKind a0ff21444582518b 6 0 +DecisionNode qualifiedName 3d547224fe21d5b9 6 2 +DecisionNode shortName a0ff21444582518b 6 0 +DecisionNode textualRepresentation 36431934a5be0cc3 6 0 +DecisionNode type 36431934a5be0cc3 6 0 +DecisionNode unioningType 36431934a5be0cc3 6 0 +DecisionNode usage 36431934a5be0cc3 6 0 +DecisionNode variant 36431934a5be0cc3 6 0 +DecisionNode variantMembership 36431934a5be0cc3 6 0 +Definition aliasIds 561b7c9e4010737f 2 0 +Definition declaredName 7a6fba57c7c378b1 2 2 +Definition declaredShortName d40b0f23e552ecc7 2 0 +Definition differencingType 561b7c9e4010737f 2 0 +Definition directedFeature 561b7c9e4010737f 2 0 +Definition directedUsage 561b7c9e4010737f 2 0 +Definition documentation 6977885590f17f2d 2 1 +Definition elementId 4a1280068f0d9fbc 2 2 +Definition endFeature 561b7c9e4010737f 2 0 +Definition feature 59d458357c1a26da 2 2 +Definition featureMembership 1ae1e1704a0265b8 2 2 +Definition importedMembership 561b7c9e4010737f 2 0 +Definition inheritedFeature 561b7c9e4010737f 2 0 +Definition inheritedMembership 561b7c9e4010737f 2 0 +Definition input 561b7c9e4010737f 2 0 +Definition intersectingType 561b7c9e4010737f 2 0 +Definition isAbstract 1f49e1b853f65749 2 0 +Definition isConjugated 1f49e1b853f65749 2 0 +Definition isImpliedIncluded 9080d3abf7a60953 2 2 +Definition isLibraryElement 1f49e1b853f65749 2 0 +Definition isSufficient 1f49e1b853f65749 2 0 +Definition isVariation 1f49e1b853f65749 2 0 +Definition member 7ae97b574a06c616 2 2 +Definition membership 4d74d0232f277853 2 2 +Definition multiplicity d40b0f23e552ecc7 2 0 +Definition name 7a6fba57c7c378b1 2 2 +Definition output 561b7c9e4010737f 2 0 +Definition ownedAction 561b7c9e4010737f 2 0 +Definition ownedAllocation 561b7c9e4010737f 2 0 +Definition ownedAnalysisCase 561b7c9e4010737f 2 0 +Definition ownedAnnotation 561b7c9e4010737f 2 0 +Definition ownedAttribute 54e7293e1418b75b 2 2 +Definition ownedCalculation 561b7c9e4010737f 2 0 +Definition ownedCase 561b7c9e4010737f 2 0 +Definition ownedConcern 561b7c9e4010737f 2 0 +Definition ownedConjugator d40b0f23e552ecc7 2 0 +Definition ownedConnection 7e1689b1892db1d1 2 1 +Definition ownedConstraint 561b7c9e4010737f 2 0 +Definition ownedDifferencing 561b7c9e4010737f 2 0 +Definition ownedDisjoining 561b7c9e4010737f 2 0 +Definition ownedElement 7ae97b574a06c616 2 2 +Definition ownedEndFeature 561b7c9e4010737f 2 0 +Definition ownedEnumeration 561b7c9e4010737f 2 0 +Definition ownedFeature 59d458357c1a26da 2 2 +Definition ownedFeatureMembership 1ae1e1704a0265b8 2 2 +Definition ownedFlow 561b7c9e4010737f 2 0 +Definition ownedImport 561b7c9e4010737f 2 0 +Definition ownedInterface 88ed93fd4a097e41 2 1 +Definition ownedIntersecting 561b7c9e4010737f 2 0 +Definition ownedItem 7e1689b1892db1d1 2 1 +Definition ownedMember 7ae97b574a06c616 2 2 +Definition ownedMembership 4d74d0232f277853 2 2 +Definition ownedMetadata 561b7c9e4010737f 2 0 +Definition ownedOccurrence 7e1689b1892db1d1 2 1 +Definition ownedPart 7e1689b1892db1d1 2 1 +Definition ownedPort 561b7c9e4010737f 2 0 +Definition ownedReference 88ed93fd4a097e41 2 1 +Definition ownedRelationship 4d74d0232f277853 2 2 +Definition ownedRendering 561b7c9e4010737f 2 0 +Definition ownedRequirement 561b7c9e4010737f 2 0 +Definition ownedSpecialization 561b7c9e4010737f 2 0 +Definition ownedState 561b7c9e4010737f 2 0 +Definition ownedSubclassification 561b7c9e4010737f 2 0 +Definition ownedTransition 561b7c9e4010737f 2 0 +Definition ownedUnioning 561b7c9e4010737f 2 0 +Definition ownedUsage 59d458357c1a26da 2 2 +Definition ownedUseCase 561b7c9e4010737f 2 0 +Definition ownedVerificationCase 561b7c9e4010737f 2 0 +Definition ownedView 561b7c9e4010737f 2 0 +Definition ownedViewpoint 561b7c9e4010737f 2 0 +Definition owner c505d7d40d03963f 2 2 +Definition owningMembership 60623e7a18977533 2 2 +Definition owningNamespace c505d7d40d03963f 2 2 +Definition owningRelationship 60623e7a18977533 2 2 +Definition qualifiedName 6a00f4e04a40a6d4 2 2 +Definition shortName d40b0f23e552ecc7 2 0 +Definition textualRepresentation 561b7c9e4010737f 2 0 +Definition unioningType 561b7c9e4010737f 2 0 +Definition usage 59d458357c1a26da 2 2 +Definition variant 561b7c9e4010737f 2 0 +Definition variantMembership 561b7c9e4010737f 2 0 +Dependency aliasIds aae3f2b22577f6c8 10 0 +Dependency client f3a00c405621ab35 10 10 +Dependency declaredName 385761b1e42a32a1 10 3 +Dependency declaredShortName 871c3fa3b34abc96 10 0 +Dependency documentation aae3f2b22577f6c8 10 0 +Dependency elementId ec9f6e361704d98c 10 10 +Dependency isImplied 3d63ca9d2eead73e 10 0 +Dependency isImpliedIncluded 70f7e46e8f480a58 10 10 +Dependency isLibraryElement 3d63ca9d2eead73e 10 0 +Dependency name 385761b1e42a32a1 10 3 +Dependency ownedAnnotation aae3f2b22577f6c8 10 0 +Dependency ownedElement e743f4d477233620 10 1 +Dependency ownedRelatedElement aae3f2b22577f6c8 10 0 +Dependency ownedRelationship a90365de9c105aa1 10 1 +Dependency owner 8ddaa5c82ddac1ac 10 10 +Dependency owningMembership 8aac98e55a66418f 10 10 +Dependency owningNamespace 8ddaa5c82ddac1ac 10 10 +Dependency owningRelatedElement 871c3fa3b34abc96 10 0 +Dependency owningRelationship 8aac98e55a66418f 10 10 +Dependency qualifiedName b7a4322b66d5b42f 10 3 +Dependency relatedElement 316af21b529efad3 10 10 +Dependency shortName 871c3fa3b34abc96 10 0 +Dependency source f3a00c405621ab35 10 10 +Dependency supplier f5f81aa467db43e8 10 10 +Dependency target f5f81aa467db43e8 10 10 +Dependency textualRepresentation aae3f2b22577f6c8 10 0 +Documentation aliasIds ba181728fd3f54d8 157 0 +Documentation annotatedElement 67910ee6be20820b 157 157 +Documentation annotation ba181728fd3f54d8 157 0 +Documentation body 3449a3ea2ac27aab 157 157 +Documentation declaredName 95e514f01e789180 157 1 +Documentation declaredShortName 4d738ff1ee9d33b1 157 0 +Documentation documentation ba181728fd3f54d8 157 0 +Documentation documentedElement 12633c5feff30df5 157 157 +Documentation elementId 9ea67ea5682d9758 157 157 +Documentation isImpliedIncluded 1b253345122ab4ec 157 157 +Documentation isLibraryElement 12876a39bebbdacb 157 8 +Documentation locale 7a690ccf6a6178d4 157 1 +Documentation name 95e514f01e789180 157 1 +Documentation ownedAnnotatingRelationship ba181728fd3f54d8 157 0 +Documentation ownedAnnotation ba181728fd3f54d8 157 0 +Documentation ownedElement ba181728fd3f54d8 157 0 +Documentation ownedRelationship ba181728fd3f54d8 157 0 +Documentation owner 12633c5feff30df5 157 157 +Documentation owningAnnotatingRelationship 4d738ff1ee9d33b1 157 0 +Documentation owningMembership 194a8a4f302e5ae6 157 157 +Documentation owningNamespace 12633c5feff30df5 157 157 +Documentation owningRelationship 194a8a4f302e5ae6 157 157 +Documentation qualifiedName 2f0a9f4be70d5f11 157 1 +Documentation shortName 4d738ff1ee9d33b1 157 0 +Documentation textualRepresentation ba181728fd3f54d8 157 0 +ElementFilterMembership aliasIds 71d6deb8ce2e2308 26 0 +ElementFilterMembership condition 523b27aac900447d 26 26 +ElementFilterMembership declaredName f93ea268211a88f6 26 0 +ElementFilterMembership declaredShortName f93ea268211a88f6 26 0 +ElementFilterMembership documentation 71d6deb8ce2e2308 26 0 +ElementFilterMembership elementId 040db6f84439f954 26 26 +ElementFilterMembership isImplied 6c1a2fbe146b1a56 26 0 +ElementFilterMembership isImpliedIncluded b62906dc5fd598f0 26 26 +ElementFilterMembership isLibraryElement 6c1a2fbe146b1a56 26 0 +ElementFilterMembership memberElement 523b27aac900447d 26 26 +ElementFilterMembership memberElementId f758969ec488cddb 26 26 +ElementFilterMembership memberName f93ea268211a88f6 26 0 +ElementFilterMembership memberShortName f93ea268211a88f6 26 0 +ElementFilterMembership membershipOwningNamespace 2d591b30afbbd68b 26 26 +ElementFilterMembership name f93ea268211a88f6 26 0 +ElementFilterMembership ownedAnnotation 71d6deb8ce2e2308 26 0 +ElementFilterMembership ownedElement 71d6deb8ce2e2308 26 0 +ElementFilterMembership ownedMemberElement 523b27aac900447d 26 26 +ElementFilterMembership ownedMemberElementId f758969ec488cddb 26 26 +ElementFilterMembership ownedMemberName f93ea268211a88f6 26 0 +ElementFilterMembership ownedMemberShortName f93ea268211a88f6 26 0 +ElementFilterMembership ownedRelatedElement 2e98b386e75a2c3f 26 26 +ElementFilterMembership ownedRelationship 71d6deb8ce2e2308 26 0 +ElementFilterMembership owner f93ea268211a88f6 26 0 +ElementFilterMembership owningMembership f93ea268211a88f6 26 0 +ElementFilterMembership owningNamespace f93ea268211a88f6 26 0 +ElementFilterMembership owningRelatedElement 2d591b30afbbd68b 26 26 +ElementFilterMembership owningRelationship f93ea268211a88f6 26 0 +ElementFilterMembership qualifiedName f93ea268211a88f6 26 0 +ElementFilterMembership relatedElement 7c7ac74e7960489a 26 26 +ElementFilterMembership shortName f93ea268211a88f6 26 0 +ElementFilterMembership source 9a844c7f9b084209 26 26 +ElementFilterMembership target 2e98b386e75a2c3f 26 26 +ElementFilterMembership textualRepresentation 71d6deb8ce2e2308 26 0 +ElementFilterMembership visibility 0d6e8b2c454edac8 26 26 +EndFeatureMembership aliasIds 2712c4685b225924 1420 0 +EndFeatureMembership declaredName 746a6baf09990a08 1420 0 +EndFeatureMembership declaredShortName 746a6baf09990a08 1420 0 +EndFeatureMembership documentation 2712c4685b225924 1420 0 +EndFeatureMembership elementId d3bd686289112b54 1420 1420 +EndFeatureMembership isImplied 4cfcea9fe5814410 1420 0 +EndFeatureMembership isImpliedIncluded e754979b99ae8164 1420 1420 +EndFeatureMembership isLibraryElement 55640232948e62a8 1420 8 +EndFeatureMembership memberElement 1080836271a61993 1420 1420 +EndFeatureMembership memberElementId 7e7932cb7ac4913b 1420 1420 +EndFeatureMembership memberName 71e4ffe51e050073 1420 1412 +EndFeatureMembership memberShortName 746a6baf09990a08 1420 0 +EndFeatureMembership membershipOwningNamespace 8950112cee466c96 1420 1420 +EndFeatureMembership name 746a6baf09990a08 1420 0 +EndFeatureMembership ownedAnnotation 2712c4685b225924 1420 0 +EndFeatureMembership ownedElement 2712c4685b225924 1420 0 +EndFeatureMembership ownedMemberElement 1080836271a61993 1420 1420 +EndFeatureMembership ownedMemberElementId 7e7932cb7ac4913b 1420 1420 +EndFeatureMembership ownedMemberFeature 1080836271a61993 1420 1420 +EndFeatureMembership ownedMemberName 71e4ffe51e050073 1420 1412 +EndFeatureMembership ownedMemberShortName 746a6baf09990a08 1420 0 +EndFeatureMembership ownedRelatedElement 4ae84f33fa399665 1420 1420 +EndFeatureMembership ownedRelationship 2712c4685b225924 1420 0 +EndFeatureMembership owner 746a6baf09990a08 1420 0 +EndFeatureMembership owningMembership 746a6baf09990a08 1420 0 +EndFeatureMembership owningNamespace 746a6baf09990a08 1420 0 +EndFeatureMembership owningRelatedElement 8950112cee466c96 1420 1420 +EndFeatureMembership owningRelationship 746a6baf09990a08 1420 0 +EndFeatureMembership owningType 8950112cee466c96 1420 1420 +EndFeatureMembership qualifiedName 746a6baf09990a08 1420 0 +EndFeatureMembership relatedElement da0d70033c49980f 1420 1420 +EndFeatureMembership shortName 746a6baf09990a08 1420 0 +EndFeatureMembership source 4246bc6b75f5f85a 1420 1420 +EndFeatureMembership target 4ae84f33fa399665 1420 1420 +EndFeatureMembership textualRepresentation 2712c4685b225924 1420 0 +EndFeatureMembership visibility b4efc8a5792c1320 1420 1176 +EnumerationDefinition aliasIds c486104c609991eb 19 0 +EnumerationDefinition declaredName 0c1eb77f1a9b9ba2 19 19 +EnumerationDefinition declaredShortName 9a82e34d3d167a0c 19 0 +EnumerationDefinition differencingType c486104c609991eb 19 0 +EnumerationDefinition directedFeature c486104c609991eb 19 0 +EnumerationDefinition directedUsage c486104c609991eb 19 0 +EnumerationDefinition documentation 3c41f7ee031256f2 19 3 +EnumerationDefinition elementId 98eeffc5dd2638d4 19 19 +EnumerationDefinition endFeature c486104c609991eb 19 0 +EnumerationDefinition enumeratedValue 6a172431028993d2 19 18 +EnumerationDefinition feature c486104c609991eb 19 0 +EnumerationDefinition featureMembership c486104c609991eb 19 0 +EnumerationDefinition importedMembership c486104c609991eb 19 0 +EnumerationDefinition inheritedFeature c486104c609991eb 19 0 +EnumerationDefinition inheritedMembership c486104c609991eb 19 0 +EnumerationDefinition input c486104c609991eb 19 0 +EnumerationDefinition intersectingType c486104c609991eb 19 0 +EnumerationDefinition isAbstract 4def4a2b88558fcb 19 19 +EnumerationDefinition isConjugated 0e736afce357d8d4 19 0 +EnumerationDefinition isImpliedIncluded 4def4a2b88558fcb 19 19 +EnumerationDefinition isLibraryElement d540726f7450b06b 19 3 +EnumerationDefinition isSufficient 0e736afce357d8d4 19 0 +EnumerationDefinition isVariation 4def4a2b88558fcb 19 19 +EnumerationDefinition member 35b1f3ce2c49b6e1 19 18 +EnumerationDefinition membership 632316ae9e6a657d 19 18 +EnumerationDefinition multiplicity 9a82e34d3d167a0c 19 0 +EnumerationDefinition name 0c1eb77f1a9b9ba2 19 19 +EnumerationDefinition output c486104c609991eb 19 0 +EnumerationDefinition ownedAction c486104c609991eb 19 0 +EnumerationDefinition ownedAllocation c486104c609991eb 19 0 +EnumerationDefinition ownedAnalysisCase c486104c609991eb 19 0 +EnumerationDefinition ownedAnnotation c486104c609991eb 19 0 +EnumerationDefinition ownedAttribute c486104c609991eb 19 0 +EnumerationDefinition ownedCalculation c486104c609991eb 19 0 +EnumerationDefinition ownedCase c486104c609991eb 19 0 +EnumerationDefinition ownedConcern c486104c609991eb 19 0 +EnumerationDefinition ownedConjugator 9a82e34d3d167a0c 19 0 +EnumerationDefinition ownedConnection c486104c609991eb 19 0 +EnumerationDefinition ownedConstraint c486104c609991eb 19 0 +EnumerationDefinition ownedDifferencing c486104c609991eb 19 0 +EnumerationDefinition ownedDisjoining c486104c609991eb 19 0 +EnumerationDefinition ownedElement 35b1f3ce2c49b6e1 19 18 +EnumerationDefinition ownedEndFeature c486104c609991eb 19 0 +EnumerationDefinition ownedEnumeration c486104c609991eb 19 0 +EnumerationDefinition ownedFeature c486104c609991eb 19 0 +EnumerationDefinition ownedFeatureMembership c486104c609991eb 19 0 +EnumerationDefinition ownedFlow c486104c609991eb 19 0 +EnumerationDefinition ownedImport c486104c609991eb 19 0 +EnumerationDefinition ownedInterface c486104c609991eb 19 0 +EnumerationDefinition ownedIntersecting c486104c609991eb 19 0 +EnumerationDefinition ownedItem c486104c609991eb 19 0 +EnumerationDefinition ownedMember 35b1f3ce2c49b6e1 19 18 +EnumerationDefinition ownedMembership 632316ae9e6a657d 19 18 +EnumerationDefinition ownedMetadata c486104c609991eb 19 0 +EnumerationDefinition ownedOccurrence c486104c609991eb 19 0 +EnumerationDefinition ownedPart c486104c609991eb 19 0 +EnumerationDefinition ownedPort c486104c609991eb 19 0 +EnumerationDefinition ownedReference c486104c609991eb 19 0 +EnumerationDefinition ownedRelationship 97fac8e7ca127564 19 18 +EnumerationDefinition ownedRendering c486104c609991eb 19 0 +EnumerationDefinition ownedRequirement c486104c609991eb 19 0 +EnumerationDefinition ownedSpecialization 8653e1906a1ef11a 19 8 +EnumerationDefinition ownedState c486104c609991eb 19 0 +EnumerationDefinition ownedSubclassification 8653e1906a1ef11a 19 8 +EnumerationDefinition ownedTransition c486104c609991eb 19 0 +EnumerationDefinition ownedUnioning c486104c609991eb 19 0 +EnumerationDefinition ownedUsage c486104c609991eb 19 0 +EnumerationDefinition ownedUseCase c486104c609991eb 19 0 +EnumerationDefinition ownedVerificationCase c486104c609991eb 19 0 +EnumerationDefinition ownedView c486104c609991eb 19 0 +EnumerationDefinition ownedViewpoint c486104c609991eb 19 0 +EnumerationDefinition owner 30031fb1721bd154 19 19 +EnumerationDefinition owningMembership fb44bd18e567e910 19 19 +EnumerationDefinition owningNamespace 30031fb1721bd154 19 19 +EnumerationDefinition owningRelationship fb44bd18e567e910 19 19 +EnumerationDefinition qualifiedName 104c0b346203ee6e 19 19 +EnumerationDefinition shortName 9a82e34d3d167a0c 19 0 +EnumerationDefinition textualRepresentation c486104c609991eb 19 0 +EnumerationDefinition unioningType c486104c609991eb 19 0 +EnumerationDefinition usage c486104c609991eb 19 0 +EnumerationDefinition variant 6a172431028993d2 19 18 +EnumerationDefinition variantMembership 7ec82b983fb1da5c 19 18 +EnumerationUsage aliasIds 387d429d75a5c0af 55 0 +EnumerationUsage attributeDefinition a7d134e0b550c348 55 54 +EnumerationUsage chainingFeature 387d429d75a5c0af 55 0 +EnumerationUsage crossFeature cc4a9248592f7ce8 55 0 +EnumerationUsage declaredName 8b46e580aa9ab28c 55 49 +EnumerationUsage declaredShortName cc4a9248592f7ce8 55 0 +EnumerationUsage definition a7d134e0b550c348 55 54 +EnumerationUsage differencingType 387d429d75a5c0af 55 0 +EnumerationUsage directedFeature 387d429d75a5c0af 55 0 +EnumerationUsage directedUsage 387d429d75a5c0af 55 0 +EnumerationUsage direction cc4a9248592f7ce8 55 0 +EnumerationUsage documentation 387d429d75a5c0af 55 0 +EnumerationUsage elementId b1047f83332db9d8 55 55 +EnumerationUsage endFeature 387d429d75a5c0af 55 0 +EnumerationUsage endOwningType cc4a9248592f7ce8 55 0 +EnumerationUsage enumerationDefinition 8f3f57964e0b3f7f 55 54 +EnumerationUsage feature 8acf6a2297cd12c4 55 9 +EnumerationUsage featureMembership ab17f6a9b03ea60d 55 9 +EnumerationUsage featureTarget 830868c565d0e989 55 0 +EnumerationUsage featuringType 387d429d75a5c0af 55 0 +EnumerationUsage importedMembership 387d429d75a5c0af 55 0 +EnumerationUsage inheritedFeature 387d429d75a5c0af 55 0 +EnumerationUsage inheritedMembership 387d429d75a5c0af 55 0 +EnumerationUsage input 387d429d75a5c0af 55 0 +EnumerationUsage intersectingType 387d429d75a5c0af 55 0 +EnumerationUsage isAbstract be8484459cd48dd4 55 0 +EnumerationUsage isComposite be8484459cd48dd4 55 0 +EnumerationUsage isConjugated be8484459cd48dd4 55 0 +EnumerationUsage isConstant be8484459cd48dd4 55 0 +EnumerationUsage isDerived be8484459cd48dd4 55 0 +EnumerationUsage isEnd be8484459cd48dd4 55 0 +EnumerationUsage isImpliedIncluded 06bc574c8d6f8c5f 55 55 +EnumerationUsage isLibraryElement 89140a86a36fad8c 55 8 +EnumerationUsage isOrdered be8484459cd48dd4 55 0 +EnumerationUsage isPortion cc4a9248592f7ce8 55 0 +EnumerationUsage isReference 06bc574c8d6f8c5f 55 55 +EnumerationUsage isSufficient cc4a9248592f7ce8 55 0 +EnumerationUsage isUnique 06bc574c8d6f8c5f 55 55 +EnumerationUsage isVariable cc4a9248592f7ce8 55 0 +EnumerationUsage isVariation be8484459cd48dd4 55 0 +EnumerationUsage mayTimeVary cc4a9248592f7ce8 55 0 +EnumerationUsage member 043fc2ad9cf41916 55 28 +EnumerationUsage membership 575fe9461b0fe8f0 55 28 +EnumerationUsage multiplicity cc4a9248592f7ce8 55 0 +EnumerationUsage name 8b46e580aa9ab28c 55 49 +EnumerationUsage nestedAction 387d429d75a5c0af 55 0 +EnumerationUsage nestedAllocation 387d429d75a5c0af 55 0 +EnumerationUsage nestedAnalysisCase 387d429d75a5c0af 55 0 +EnumerationUsage nestedAttribute 387d429d75a5c0af 55 0 +EnumerationUsage nestedCalculation 387d429d75a5c0af 55 0 +EnumerationUsage nestedCase 387d429d75a5c0af 55 0 +EnumerationUsage nestedConcern 387d429d75a5c0af 55 0 +EnumerationUsage nestedConnection 387d429d75a5c0af 55 0 +EnumerationUsage nestedConstraint 387d429d75a5c0af 55 0 +EnumerationUsage nestedEnumeration 387d429d75a5c0af 55 0 +EnumerationUsage nestedFlow 387d429d75a5c0af 55 0 +EnumerationUsage nestedInterface 8acf6a2297cd12c4 55 9 +EnumerationUsage nestedItem 387d429d75a5c0af 55 0 +EnumerationUsage nestedMetadata 387d429d75a5c0af 55 0 +EnumerationUsage nestedOccurrence 387d429d75a5c0af 55 0 +EnumerationUsage nestedPart 387d429d75a5c0af 55 0 +EnumerationUsage nestedPort 387d429d75a5c0af 55 0 +EnumerationUsage nestedReference 8acf6a2297cd12c4 55 9 +EnumerationUsage nestedRendering 387d429d75a5c0af 55 0 +EnumerationUsage nestedRequirement 387d429d75a5c0af 55 0 +EnumerationUsage nestedState 387d429d75a5c0af 55 0 +EnumerationUsage nestedTransition 387d429d75a5c0af 55 0 +EnumerationUsage nestedUsage 8acf6a2297cd12c4 55 9 +EnumerationUsage nestedUseCase 387d429d75a5c0af 55 0 +EnumerationUsage nestedVerificationCase 387d429d75a5c0af 55 0 +EnumerationUsage nestedView 387d429d75a5c0af 55 0 +EnumerationUsage nestedViewpoint 387d429d75a5c0af 55 0 +EnumerationUsage output 387d429d75a5c0af 55 0 +EnumerationUsage ownedAnnotation 387d429d75a5c0af 55 0 +EnumerationUsage ownedConjugator cc4a9248592f7ce8 55 0 +EnumerationUsage ownedCrossSubsetting cc4a9248592f7ce8 55 0 +EnumerationUsage ownedDifferencing 387d429d75a5c0af 55 0 +EnumerationUsage ownedDisjoining 387d429d75a5c0af 55 0 +EnumerationUsage ownedElement 043fc2ad9cf41916 55 28 +EnumerationUsage ownedEndFeature 387d429d75a5c0af 55 0 +EnumerationUsage ownedFeature 8acf6a2297cd12c4 55 9 +EnumerationUsage ownedFeatureChaining 387d429d75a5c0af 55 0 +EnumerationUsage ownedFeatureInverting 387d429d75a5c0af 55 0 +EnumerationUsage ownedFeatureMembership ab17f6a9b03ea60d 55 9 +EnumerationUsage ownedImport 387d429d75a5c0af 55 0 +EnumerationUsage ownedIntersecting 387d429d75a5c0af 55 0 +EnumerationUsage ownedMember 043fc2ad9cf41916 55 28 +EnumerationUsage ownedMembership 575fe9461b0fe8f0 55 28 +EnumerationUsage ownedRedefinition 387d429d75a5c0af 55 0 +EnumerationUsage ownedReferenceSubsetting cc4a9248592f7ce8 55 0 +EnumerationUsage ownedRelationship 49eb1c5b966eaec0 55 55 +EnumerationUsage ownedSpecialization b3a66747e496cd53 55 54 +EnumerationUsage ownedSubsetting 387d429d75a5c0af 55 0 +EnumerationUsage ownedTypeFeaturing 387d429d75a5c0af 55 0 +EnumerationUsage ownedTyping b3a66747e496cd53 55 54 +EnumerationUsage ownedUnioning 387d429d75a5c0af 55 0 +EnumerationUsage owner 7854116f38c85679 55 55 +EnumerationUsage owningDefinition cc4a9248592f7ce8 55 0 +EnumerationUsage owningFeatureMembership cc4a9248592f7ce8 55 0 +EnumerationUsage owningMembership 2ec337f0d464635e 55 55 +EnumerationUsage owningNamespace 7854116f38c85679 55 55 +EnumerationUsage owningRelationship 2ec337f0d464635e 55 55 +EnumerationUsage owningType cc4a9248592f7ce8 55 0 +EnumerationUsage owningUsage cc4a9248592f7ce8 55 0 +EnumerationUsage qualifiedName 55579b8c87612bca 55 49 +EnumerationUsage shortName cc4a9248592f7ce8 55 0 +EnumerationUsage textualRepresentation 387d429d75a5c0af 55 0 +EnumerationUsage type a7d134e0b550c348 55 54 +EnumerationUsage unioningType 387d429d75a5c0af 55 0 +EnumerationUsage usage 8acf6a2297cd12c4 55 9 +EnumerationUsage variant 387d429d75a5c0af 55 0 +EnumerationUsage variantMembership 387d429d75a5c0af 55 0 +EventOccurrenceUsage aliasIds 8f1a7602506fce47 129 0 +EventOccurrenceUsage chainingFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage crossFeature 421787a3009e910e 129 0 +EventOccurrenceUsage declaredName 058f483c3bb36b6c 129 53 +EventOccurrenceUsage declaredShortName 421787a3009e910e 129 0 +EventOccurrenceUsage definition f7cd9d04d826a502 129 7 +EventOccurrenceUsage differencingType 8f1a7602506fce47 129 0 +EventOccurrenceUsage directedFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage directedUsage 8f1a7602506fce47 129 0 +EventOccurrenceUsage direction a295336c082efdca 129 1 +EventOccurrenceUsage documentation 8f1a7602506fce47 129 0 +EventOccurrenceUsage elementId 6ad5f3e80b05edf0 129 129 +EventOccurrenceUsage endFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage endOwningType 421787a3009e910e 129 0 +EventOccurrenceUsage eventOccurrence 1468a0855df557fb 129 71 +EventOccurrenceUsage feature 8f1a7602506fce47 129 0 +EventOccurrenceUsage featureMembership 8f1a7602506fce47 129 0 +EventOccurrenceUsage featureTarget f88b63ba0f1946eb 129 0 +EventOccurrenceUsage featuringType 8f1a7602506fce47 129 0 +EventOccurrenceUsage importedMembership 8f1a7602506fce47 129 0 +EventOccurrenceUsage individualDefinition 421787a3009e910e 129 0 +EventOccurrenceUsage inheritedFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage inheritedMembership 8f1a7602506fce47 129 0 +EventOccurrenceUsage input 8f1a7602506fce47 129 0 +EventOccurrenceUsage intersectingType 8f1a7602506fce47 129 0 +EventOccurrenceUsage isAbstract 8c334b651b83de2a 129 0 +EventOccurrenceUsage isComposite 8c334b651b83de2a 129 0 +EventOccurrenceUsage isConjugated 8c334b651b83de2a 129 0 +EventOccurrenceUsage isConstant 8c334b651b83de2a 129 0 +EventOccurrenceUsage isDerived 8c334b651b83de2a 129 0 +EventOccurrenceUsage isEnd 8c334b651b83de2a 129 0 +EventOccurrenceUsage isImpliedIncluded 50078a776cb6358f 129 129 +EventOccurrenceUsage isIndividual 421787a3009e910e 129 0 +EventOccurrenceUsage isLibraryElement 8c334b651b83de2a 129 0 +EventOccurrenceUsage isOrdered 8c334b651b83de2a 129 0 +EventOccurrenceUsage isPortion 421787a3009e910e 129 0 +EventOccurrenceUsage isReference 50078a776cb6358f 129 129 +EventOccurrenceUsage isSufficient 421787a3009e910e 129 0 +EventOccurrenceUsage isUnique 50078a776cb6358f 129 129 +EventOccurrenceUsage isVariable 421787a3009e910e 129 0 +EventOccurrenceUsage isVariation 8c334b651b83de2a 129 0 +EventOccurrenceUsage mayTimeVary 421787a3009e910e 129 0 +EventOccurrenceUsage member fde5fffe0c399999 129 55 +EventOccurrenceUsage membership 28bc5c85d1d157b4 129 55 +EventOccurrenceUsage multiplicity 2a0370eff469fcd5 129 46 +EventOccurrenceUsage name e000be09b75251bf 129 129 +EventOccurrenceUsage nestedAction 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedAllocation 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedAnalysisCase 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedAttribute 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedCalculation 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedCase 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedConcern 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedConnection 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedConstraint 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedEnumeration 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedFlow 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedInterface 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedItem 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedMetadata 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedOccurrence 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedPart 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedPort 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedReference 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedRendering 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedRequirement 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedState 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedTransition 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedUsage 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedUseCase 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedVerificationCase 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedView 8f1a7602506fce47 129 0 +EventOccurrenceUsage nestedViewpoint 8f1a7602506fce47 129 0 +EventOccurrenceUsage occurrenceDefinition efe7b420531183c1 129 7 +EventOccurrenceUsage output 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedAnnotation 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedConjugator 421787a3009e910e 129 0 +EventOccurrenceUsage ownedCrossSubsetting 421787a3009e910e 129 0 +EventOccurrenceUsage ownedDifferencing 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedDisjoining 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedElement 1b9807cd90aed38f 129 71 +EventOccurrenceUsage ownedEndFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedFeature 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedFeatureChaining 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedFeatureInverting 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedFeatureMembership 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedImport 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedIntersecting 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedMember fde5fffe0c399999 129 55 +EventOccurrenceUsage ownedMembership 28bc5c85d1d157b4 129 55 +EventOccurrenceUsage ownedRedefinition 6604db18e36f9506 129 29 +EventOccurrenceUsage ownedReferenceSubsetting 33f09b7023d582ae 129 71 +EventOccurrenceUsage ownedRelationship ffc7c1094ce49e56 129 129 +EventOccurrenceUsage ownedSpecialization 923d18659e7be4d3 129 129 +EventOccurrenceUsage ownedSubsetting 8d53443873312a1c 129 129 +EventOccurrenceUsage ownedTypeFeaturing 8f1a7602506fce47 129 0 +EventOccurrenceUsage ownedTyping 84279c3cd78375b0 129 4 +EventOccurrenceUsage ownedUnioning 8f1a7602506fce47 129 0 +EventOccurrenceUsage owner 84bd9c1cebac1077 129 129 +EventOccurrenceUsage owningDefinition 5c3f320b49fe11cb 129 1 +EventOccurrenceUsage owningFeatureMembership e7010ddd421886c6 129 129 +EventOccurrenceUsage owningMembership e7010ddd421886c6 129 129 +EventOccurrenceUsage owningNamespace 84bd9c1cebac1077 129 129 +EventOccurrenceUsage owningRelationship e7010ddd421886c6 129 129 +EventOccurrenceUsage owningType 84bd9c1cebac1077 129 129 +EventOccurrenceUsage owningUsage 6a95f1b4a24c8fba 129 128 +EventOccurrenceUsage portionKind 421787a3009e910e 129 0 +EventOccurrenceUsage qualifiedName 9bfe588ef5246454 129 129 +EventOccurrenceUsage shortName 421787a3009e910e 129 0 +EventOccurrenceUsage textualRepresentation 8f1a7602506fce47 129 0 +EventOccurrenceUsage type f7cd9d04d826a502 129 7 +EventOccurrenceUsage unioningType 8f1a7602506fce47 129 0 +EventOccurrenceUsage usage 8f1a7602506fce47 129 0 +EventOccurrenceUsage variant 8f1a7602506fce47 129 0 +EventOccurrenceUsage variantMembership 8f1a7602506fce47 129 0 +ExhibitStateUsage actionDefinition 6eb4b68af6644771 29 13 +ExhibitStateUsage aliasIds 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage behavior 6eb4b68af6644771 29 13 +ExhibitStateUsage chainingFeature 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage crossFeature 228e8ebb38f6d6de 29 0 +ExhibitStateUsage declaredName 45d4b0ed17156d6a 29 19 +ExhibitStateUsage declaredShortName 228e8ebb38f6d6de 29 0 +ExhibitStateUsage definition 6eb4b68af6644771 29 13 +ExhibitStateUsage differencingType 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage directedFeature 6748e972130e2b69 29 1 +ExhibitStateUsage directedUsage 6748e972130e2b69 29 1 +ExhibitStateUsage direction 228e8ebb38f6d6de 29 0 +ExhibitStateUsage doAction 228e8ebb38f6d6de 29 0 +ExhibitStateUsage documentation 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage elementId 77795d014df1ed68 29 29 +ExhibitStateUsage endFeature 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage endOwningType 228e8ebb38f6d6de 29 0 +ExhibitStateUsage entryAction 2e234ecf03ac8a5d 29 4 +ExhibitStateUsage eventOccurrence 73f978b7ce9526a1 29 10 +ExhibitStateUsage exhibitedState 73f978b7ce9526a1 29 10 +ExhibitStateUsage exitAction 228e8ebb38f6d6de 29 0 +ExhibitStateUsage feature 5ef8c1e54453db84 29 9 +ExhibitStateUsage featureMembership a5bd54b451a12c67 29 9 +ExhibitStateUsage featureTarget 0116a2dfc191162b 29 0 +ExhibitStateUsage featuringType 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage importedMembership 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage individualDefinition 228e8ebb38f6d6de 29 0 +ExhibitStateUsage inheritedFeature 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage inheritedMembership 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage input 6748e972130e2b69 29 1 +ExhibitStateUsage intersectingType 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage isAbstract e3f43f31904915de 29 0 +ExhibitStateUsage isComposite e3f43f31904915de 29 0 +ExhibitStateUsage isConjugated e3f43f31904915de 29 0 +ExhibitStateUsage isConstant e3f43f31904915de 29 0 +ExhibitStateUsage isDerived e3f43f31904915de 29 0 +ExhibitStateUsage isEnd e3f43f31904915de 29 0 +ExhibitStateUsage isImpliedIncluded 65e6796eeda6a607 29 29 +ExhibitStateUsage isIndividual 228e8ebb38f6d6de 29 0 +ExhibitStateUsage isLibraryElement e3f43f31904915de 29 0 +ExhibitStateUsage isOrdered e3f43f31904915de 29 0 +ExhibitStateUsage isParallel fa06cd8f97702bd8 29 2 +ExhibitStateUsage isPortion 228e8ebb38f6d6de 29 0 +ExhibitStateUsage isReference 65e6796eeda6a607 29 29 +ExhibitStateUsage isSufficient 228e8ebb38f6d6de 29 0 +ExhibitStateUsage isUnique 65e6796eeda6a607 29 29 +ExhibitStateUsage isVariable 228e8ebb38f6d6de 29 0 +ExhibitStateUsage isVariation e3f43f31904915de 29 0 +ExhibitStateUsage mayTimeVary 228e8ebb38f6d6de 29 0 +ExhibitStateUsage member a19338ea746f4cf5 29 12 +ExhibitStateUsage membership ca865e11bfb5e0e2 29 12 +ExhibitStateUsage multiplicity 228e8ebb38f6d6de 29 0 +ExhibitStateUsage name 50985497b31a4a9f 29 29 +ExhibitStateUsage nestedAction 8c708aa889090fa4 29 8 +ExhibitStateUsage nestedAllocation 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedAnalysisCase 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedAttribute 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedCalculation 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedCase 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedConcern 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedConnection ae9869acfecaa0b9 29 4 +ExhibitStateUsage nestedConstraint 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedEnumeration 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedFlow 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedInterface a156f618058611a9 29 2 +ExhibitStateUsage nestedItem 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedMetadata 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedOccurrence 8c708aa889090fa4 29 8 +ExhibitStateUsage nestedPart 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedPort 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedReference a156f618058611a9 29 2 +ExhibitStateUsage nestedRendering 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedRequirement 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedState 2041fd3d80851b38 29 8 +ExhibitStateUsage nestedTransition 240db0978b013f16 29 3 +ExhibitStateUsage nestedUsage 5ef8c1e54453db84 29 9 +ExhibitStateUsage nestedUseCase 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedVerificationCase 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedView 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage nestedViewpoint 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage occurrenceDefinition 6eb4b68af6644771 29 13 +ExhibitStateUsage output 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedAnnotation 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedConjugator 228e8ebb38f6d6de 29 0 +ExhibitStateUsage ownedCrossSubsetting 228e8ebb38f6d6de 29 0 +ExhibitStateUsage ownedDifferencing 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedDisjoining 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedElement c4fb24dcdc81377a 29 14 +ExhibitStateUsage ownedEndFeature 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedFeature 5ef8c1e54453db84 29 9 +ExhibitStateUsage ownedFeatureChaining 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedFeatureInverting 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedFeatureMembership a5bd54b451a12c67 29 9 +ExhibitStateUsage ownedImport 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedIntersecting 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedMember a19338ea746f4cf5 29 12 +ExhibitStateUsage ownedMembership ca865e11bfb5e0e2 29 12 +ExhibitStateUsage ownedRedefinition 215e9b4459ab514f 29 8 +ExhibitStateUsage ownedReferenceSubsetting 67fbe10d6f340abe 29 10 +ExhibitStateUsage ownedRelationship 6201e5c93f0c453d 29 29 +ExhibitStateUsage ownedSpecialization a96d763a38965182 29 29 +ExhibitStateUsage ownedSubsetting 7c2e3c2f34a93e8c 29 29 +ExhibitStateUsage ownedTypeFeaturing 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage ownedTyping ef8249a173d93f8f 29 6 +ExhibitStateUsage ownedUnioning 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage owner 5a3ed4b406819608 29 29 +ExhibitStateUsage owningDefinition 3baa54dfd1fd5683 29 14 +ExhibitStateUsage owningFeatureMembership 1dd303701c36d6f7 29 29 +ExhibitStateUsage owningMembership 1dd303701c36d6f7 29 29 +ExhibitStateUsage owningNamespace 5a3ed4b406819608 29 29 +ExhibitStateUsage owningRelationship 1dd303701c36d6f7 29 29 +ExhibitStateUsage owningType 5a3ed4b406819608 29 29 +ExhibitStateUsage owningUsage 41230e8f6d7b1663 29 15 +ExhibitStateUsage parameter 6748e972130e2b69 29 1 +ExhibitStateUsage performedAction 73f978b7ce9526a1 29 10 +ExhibitStateUsage portionKind 228e8ebb38f6d6de 29 0 +ExhibitStateUsage qualifiedName 133451ec007b64b2 29 29 +ExhibitStateUsage shortName 228e8ebb38f6d6de 29 0 +ExhibitStateUsage stateDefinition 6eb4b68af6644771 29 13 +ExhibitStateUsage textualRepresentation 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage type 6eb4b68af6644771 29 13 +ExhibitStateUsage unioningType 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage usage 5ef8c1e54453db84 29 9 +ExhibitStateUsage variant 7bc33aca39cb9e6f 29 0 +ExhibitStateUsage variantMembership 7bc33aca39cb9e6f 29 0 +Expression aliasIds 6b5e99f8af607b18 10 0 +Expression behavior 6b5e99f8af607b18 10 0 +Expression chainingFeature 6b5e99f8af607b18 10 0 +Expression crossFeature 3f0b2b0aed30b606 10 0 +Expression declaredName 3f0b2b0aed30b606 10 0 +Expression declaredShortName 3f0b2b0aed30b606 10 0 +Expression differencingType 6b5e99f8af607b18 10 0 +Expression directedFeature 8df19487f90a47cb 10 10 +Expression direction 3f0b2b0aed30b606 10 0 +Expression documentation 6b5e99f8af607b18 10 0 +Expression elementId 7b9cf146407c0a58 10 10 +Expression endFeature 6b5e99f8af607b18 10 0 +Expression endOwningType 3f0b2b0aed30b606 10 0 +Expression feature 7cab4e6c71232bb4 10 10 +Expression featureMembership 832769e902390fcc 10 10 +Expression featureTarget 9a0697444598fcda 10 0 +Expression featuringType 6b5e99f8af607b18 10 0 +Expression function 3f0b2b0aed30b606 10 0 +Expression importedMembership 6b5e99f8af607b18 10 0 +Expression inheritedFeature 6b5e99f8af607b18 10 0 +Expression inheritedMembership 6b5e99f8af607b18 10 0 +Expression input 8df19487f90a47cb 10 10 +Expression intersectingType 6b5e99f8af607b18 10 0 +Expression isAbstract 3f0b2b0aed30b606 10 0 +Expression isComposite 3f0b2b0aed30b606 10 0 +Expression isConjugated 54e5a1a874a917de 10 0 +Expression isConstant 3f0b2b0aed30b606 10 0 +Expression isDerived 3f0b2b0aed30b606 10 0 +Expression isEnd 3f0b2b0aed30b606 10 0 +Expression isImpliedIncluded 7873bdc21f354b48 10 10 +Expression isLibraryElement 54e5a1a874a917de 10 0 +Expression isModelLevelEvaluable 54e5a1a874a917de 10 0 +Expression isOrdered 3f0b2b0aed30b606 10 0 +Expression isPortion 3f0b2b0aed30b606 10 0 +Expression isSufficient 3f0b2b0aed30b606 10 0 +Expression isUnique 3f0b2b0aed30b606 10 0 +Expression isVariable 3f0b2b0aed30b606 10 0 +Expression member 7cab4e6c71232bb4 10 10 +Expression membership 832769e902390fcc 10 10 +Expression multiplicity 3f0b2b0aed30b606 10 0 +Expression name 3f0b2b0aed30b606 10 0 +Expression output 6b5e99f8af607b18 10 0 +Expression ownedAnnotation 6b5e99f8af607b18 10 0 +Expression ownedConjugator 3f0b2b0aed30b606 10 0 +Expression ownedCrossSubsetting 3f0b2b0aed30b606 10 0 +Expression ownedDifferencing 6b5e99f8af607b18 10 0 +Expression ownedDisjoining 6b5e99f8af607b18 10 0 +Expression ownedElement 7cab4e6c71232bb4 10 10 +Expression ownedEndFeature 6b5e99f8af607b18 10 0 +Expression ownedFeature 7cab4e6c71232bb4 10 10 +Expression ownedFeatureChaining 6b5e99f8af607b18 10 0 +Expression ownedFeatureInverting 6b5e99f8af607b18 10 0 +Expression ownedFeatureMembership 832769e902390fcc 10 10 +Expression ownedImport 6b5e99f8af607b18 10 0 +Expression ownedIntersecting 6b5e99f8af607b18 10 0 +Expression ownedMember 7cab4e6c71232bb4 10 10 +Expression ownedMembership 832769e902390fcc 10 10 +Expression ownedRedefinition 6b5e99f8af607b18 10 0 +Expression ownedReferenceSubsetting 3f0b2b0aed30b606 10 0 +Expression ownedRelationship 832769e902390fcc 10 10 +Expression ownedSpecialization 6b5e99f8af607b18 10 0 +Expression ownedSubsetting 6b5e99f8af607b18 10 0 +Expression ownedTypeFeaturing 6b5e99f8af607b18 10 0 +Expression ownedTyping 6b5e99f8af607b18 10 0 +Expression ownedUnioning 6b5e99f8af607b18 10 0 +Expression owner 6568fa64798370ce 10 10 +Expression owningFeatureMembership 3f0b2b0aed30b606 10 0 +Expression owningMembership f8b254977a44404d 10 10 +Expression owningNamespace 6568fa64798370ce 10 10 +Expression owningRelationship f8b254977a44404d 10 10 +Expression owningType 3f0b2b0aed30b606 10 0 +Expression parameter 8df19487f90a47cb 10 10 +Expression qualifiedName 3f0b2b0aed30b606 10 0 +Expression result 9a0697444598fcda 10 0 +Expression shortName 3f0b2b0aed30b606 10 0 +Expression textualRepresentation 6b5e99f8af607b18 10 0 +Expression type 6b5e99f8af607b18 10 0 +Expression unioningType 6b5e99f8af607b18 10 0 +Feature aliasIds 2e0ba96366134a49 3333 0 +Feature chainingFeature 7e3822cf230f6214 3333 588 +Feature crossFeature 7860fdb3d3713efc 3333 0 +Feature declaredName 7860fdb3d3713efc 3333 0 +Feature declaredShortName 7860fdb3d3713efc 3333 0 +Feature differencingType 2e0ba96366134a49 3333 0 +Feature directedFeature 2e0ba96366134a49 3333 0 +Feature direction b93601c232d94f39 3333 2708 +Feature documentation 2e0ba96366134a49 3333 0 +Feature elementId 0a3aa20bb1a9e6d4 3333 3333 +Feature endFeature 2e0ba96366134a49 3333 0 +Feature endOwningType 7860fdb3d3713efc 3333 0 +Feature feature 2e0ba96366134a49 3333 0 +Feature featureMembership 2e0ba96366134a49 3333 0 +Feature featureTarget 278491fcafbf30ed 3333 588 +Feature featuringType 2e0ba96366134a49 3333 0 +Feature importedMembership 2e0ba96366134a49 3333 0 +Feature inheritedFeature 2e0ba96366134a49 3333 0 +Feature inheritedMembership 2e0ba96366134a49 3333 0 +Feature input 2e0ba96366134a49 3333 0 +Feature intersectingType 2e0ba96366134a49 3333 0 +Feature isAbstract 7860fdb3d3713efc 3333 0 +Feature isComposite 7860fdb3d3713efc 3333 0 +Feature isConjugated 9622ca34078c90b0 3333 0 +Feature isConstant 7860fdb3d3713efc 3333 0 +Feature isDerived 7860fdb3d3713efc 3333 0 +Feature isEnd 7860fdb3d3713efc 3333 0 +Feature isImpliedIncluded 76bee21979ca3ac9 3333 3333 +Feature isLibraryElement a176886648250a26 3333 46 +Feature isOrdered 7860fdb3d3713efc 3333 0 +Feature isPortion 7860fdb3d3713efc 3333 0 +Feature isSufficient 7860fdb3d3713efc 3333 0 +Feature isUnique 7860fdb3d3713efc 3333 0 +Feature isVariable 7860fdb3d3713efc 3333 0 +Feature member 3e16e99b4b2acdd3 3333 2633 +Feature membership 19a4b097362a0410 3333 2633 +Feature multiplicity 7860fdb3d3713efc 3333 0 +Feature name ae90ead7f102609a 3333 843 +Feature output 2e0ba96366134a49 3333 0 +Feature ownedAnnotation 2e0ba96366134a49 3333 0 +Feature ownedConjugator 7860fdb3d3713efc 3333 0 +Feature ownedCrossSubsetting 7860fdb3d3713efc 3333 0 +Feature ownedDifferencing 2e0ba96366134a49 3333 0 +Feature ownedDisjoining 2e0ba96366134a49 3333 0 +Feature ownedElement 3e16e99b4b2acdd3 3333 2633 +Feature ownedEndFeature 2e0ba96366134a49 3333 0 +Feature ownedFeature 2e0ba96366134a49 3333 0 +Feature ownedFeatureChaining d6a6b0046f905a48 3333 588 +Feature ownedFeatureInverting 2e0ba96366134a49 3333 0 +Feature ownedFeatureMembership 2e0ba96366134a49 3333 0 +Feature ownedImport 2e0ba96366134a49 3333 0 +Feature ownedIntersecting 2e0ba96366134a49 3333 0 +Feature ownedMember 3e16e99b4b2acdd3 3333 2633 +Feature ownedMembership 19a4b097362a0410 3333 2633 +Feature ownedRedefinition 6aeb5e929f5034d1 3333 18 +Feature ownedReferenceSubsetting 7860fdb3d3713efc 3333 0 +Feature ownedRelationship a564ad33d1f5609e 3333 3296 +Feature ownedSpecialization 7c5d83fce6472600 3333 93 +Feature ownedSubsetting 6aeb5e929f5034d1 3333 18 +Feature ownedTypeFeaturing 2e0ba96366134a49 3333 0 +Feature ownedTyping 3f7dcecdad0a3b78 3333 75 +Feature ownedUnioning 2e0ba96366134a49 3333 0 +Feature owner 80dabbaca56b761e 3333 3333 +Feature owningFeatureMembership 3728030d82a69138 3333 2745 +Feature owningMembership ebf8c27b80c40459 3333 2822 +Feature owningNamespace 5f68ecafebeeb3e4 3333 2822 +Feature owningRelationship ca14151fc631b6d5 3333 3333 +Feature owningType d6bfa895be770ff6 3333 2745 +Feature qualifiedName 613daa99e86ab95a 3333 2 +Feature shortName 61e4f32768359ab2 3333 2 +Feature textualRepresentation 2e0ba96366134a49 3333 0 +Feature type e5a66786adb39b3c 3333 468 +Feature unioningType 2e0ba96366134a49 3333 0 +FeatureChainExpression aliasIds 98cec053baff32ac 438 0 +FeatureChainExpression argument bb79f05658d4dbf9 438 438 +FeatureChainExpression behavior 98cec053baff32ac 438 0 +FeatureChainExpression chainingFeature 98cec053baff32ac 438 0 +FeatureChainExpression crossFeature 506fa127847f1052 438 0 +FeatureChainExpression declaredName 506fa127847f1052 438 0 +FeatureChainExpression declaredShortName 506fa127847f1052 438 0 +FeatureChainExpression differencingType 98cec053baff32ac 438 0 +FeatureChainExpression directedFeature 9dcce3b54350db52 438 438 +FeatureChainExpression direction 506fa127847f1052 438 0 +FeatureChainExpression documentation 98cec053baff32ac 438 0 +FeatureChainExpression elementId 3a3096d23cbad974 438 438 +FeatureChainExpression endFeature 98cec053baff32ac 438 0 +FeatureChainExpression endOwningType 506fa127847f1052 438 0 +FeatureChainExpression feature 9dcce3b54350db52 438 438 +FeatureChainExpression featureMembership ade389c4be4c7411 438 438 +FeatureChainExpression featureTarget 693fa8b853dfd56e 438 0 +FeatureChainExpression featuringType 98cec053baff32ac 438 0 +FeatureChainExpression function 506fa127847f1052 438 0 +FeatureChainExpression importedMembership 98cec053baff32ac 438 0 +FeatureChainExpression inheritedFeature 98cec053baff32ac 438 0 +FeatureChainExpression inheritedMembership 98cec053baff32ac 438 0 +FeatureChainExpression input 9dcce3b54350db52 438 438 +FeatureChainExpression instantiatedType 91845df91d964fb0 438 438 +FeatureChainExpression intersectingType 98cec053baff32ac 438 0 +FeatureChainExpression isAbstract 506fa127847f1052 438 0 +FeatureChainExpression isComposite 506fa127847f1052 438 0 +FeatureChainExpression isConjugated 40cf7e8420f74896 438 0 +FeatureChainExpression isConstant 506fa127847f1052 438 0 +FeatureChainExpression isDerived 506fa127847f1052 438 0 +FeatureChainExpression isEnd 506fa127847f1052 438 0 +FeatureChainExpression isImpliedIncluded 1d908f9623ab151c 438 438 +FeatureChainExpression isLibraryElement 40cf7e8420f74896 438 0 +FeatureChainExpression isModelLevelEvaluable 16661cbfcb31e671 438 71 +FeatureChainExpression isOrdered 506fa127847f1052 438 0 +FeatureChainExpression isPortion 506fa127847f1052 438 0 +FeatureChainExpression isSufficient 506fa127847f1052 438 0 +FeatureChainExpression isUnique 506fa127847f1052 438 0 +FeatureChainExpression isVariable 506fa127847f1052 438 0 +FeatureChainExpression member 38c2b2594d6ae0ff 438 438 +FeatureChainExpression membership a37e7d2717dfab70 438 438 +FeatureChainExpression multiplicity 506fa127847f1052 438 0 +FeatureChainExpression name 506fa127847f1052 438 0 +FeatureChainExpression operator 45e968385fe6d298 438 438 +FeatureChainExpression output 98cec053baff32ac 438 0 +FeatureChainExpression ownedAnnotation 98cec053baff32ac 438 0 +FeatureChainExpression ownedConjugator 506fa127847f1052 438 0 +FeatureChainExpression ownedCrossSubsetting 506fa127847f1052 438 0 +FeatureChainExpression ownedDifferencing 98cec053baff32ac 438 0 +FeatureChainExpression ownedDisjoining 98cec053baff32ac 438 0 +FeatureChainExpression ownedElement e318b753f6d3db5f 438 438 +FeatureChainExpression ownedEndFeature 98cec053baff32ac 438 0 +FeatureChainExpression ownedFeature 9dcce3b54350db52 438 438 +FeatureChainExpression ownedFeatureChaining 98cec053baff32ac 438 0 +FeatureChainExpression ownedFeatureInverting 98cec053baff32ac 438 0 +FeatureChainExpression ownedFeatureMembership ade389c4be4c7411 438 438 +FeatureChainExpression ownedImport 98cec053baff32ac 438 0 +FeatureChainExpression ownedIntersecting 98cec053baff32ac 438 0 +FeatureChainExpression ownedMember e318b753f6d3db5f 438 438 +FeatureChainExpression ownedMembership a37e7d2717dfab70 438 438 +FeatureChainExpression ownedRedefinition 98cec053baff32ac 438 0 +FeatureChainExpression ownedReferenceSubsetting 506fa127847f1052 438 0 +FeatureChainExpression ownedRelationship a37e7d2717dfab70 438 438 +FeatureChainExpression ownedSpecialization 98cec053baff32ac 438 0 +FeatureChainExpression ownedSubsetting 98cec053baff32ac 438 0 +FeatureChainExpression ownedTypeFeaturing 98cec053baff32ac 438 0 +FeatureChainExpression ownedTyping 98cec053baff32ac 438 0 +FeatureChainExpression ownedUnioning 98cec053baff32ac 438 0 +FeatureChainExpression owner 010516549ae55fb7 438 438 +FeatureChainExpression owningFeatureMembership ec35b0802a2dd4a7 438 14 +FeatureChainExpression owningMembership 7cab8c0e424a6684 438 438 +FeatureChainExpression owningNamespace 010516549ae55fb7 438 438 +FeatureChainExpression owningRelationship 7cab8c0e424a6684 438 438 +FeatureChainExpression owningType 0d81de1ce3ae7ae8 438 14 +FeatureChainExpression parameter 9dcce3b54350db52 438 438 +FeatureChainExpression qualifiedName 506fa127847f1052 438 0 +FeatureChainExpression result 693fa8b853dfd56e 438 0 +FeatureChainExpression shortName 506fa127847f1052 438 0 +FeatureChainExpression targetFeature aeb1a0f6cc3c0cff 438 438 +FeatureChainExpression textualRepresentation 98cec053baff32ac 438 0 +FeatureChainExpression type 98cec053baff32ac 438 0 +FeatureChainExpression unioningType 98cec053baff32ac 438 0 +FeatureChaining aliasIds 03d94b4d88a72e24 1331 0 +FeatureChaining chainingFeature 588f4d9a8997fb47 1331 1331 +FeatureChaining declaredName 6016fc3e25b13bb3 1331 0 +FeatureChaining declaredShortName 6016fc3e25b13bb3 1331 0 +FeatureChaining documentation 03d94b4d88a72e24 1331 0 +FeatureChaining elementId 8adec0159c171828 1331 1331 +FeatureChaining featureChained aace47465ea82b29 1331 1331 +FeatureChaining isImplied 6f2e1ab290fc1259 1331 0 +FeatureChaining isImpliedIncluded 7fa273852bb14a50 1331 1331 +FeatureChaining isLibraryElement 6f2e1ab290fc1259 1331 0 +FeatureChaining name 6016fc3e25b13bb3 1331 0 +FeatureChaining ownedAnnotation 03d94b4d88a72e24 1331 0 +FeatureChaining ownedElement 4646d308cfc0c362 1331 31 +FeatureChaining ownedRelatedElement 03d94b4d88a72e24 1331 0 +FeatureChaining ownedRelationship c0a6995cf45133fa 1331 31 +FeatureChaining owner 6016fc3e25b13bb3 1331 0 +FeatureChaining owningMembership 6016fc3e25b13bb3 1331 0 +FeatureChaining owningNamespace 6016fc3e25b13bb3 1331 0 +FeatureChaining owningRelatedElement aace47465ea82b29 1331 1331 +FeatureChaining owningRelationship 6016fc3e25b13bb3 1331 0 +FeatureChaining qualifiedName 6016fc3e25b13bb3 1331 0 +FeatureChaining relatedElement c4a498731d2c4a20 1331 1331 +FeatureChaining shortName 6016fc3e25b13bb3 1331 0 +FeatureChaining source 3317cceb0582437f 1331 1331 +FeatureChaining target 5e87f6a115b6278d 1331 1331 +FeatureChaining textualRepresentation 4646d308cfc0c362 1331 31 +FeatureMembership aliasIds 00360b795a3051cc 4966 0 +FeatureMembership declaredName 81c848f417c72bee 4966 0 +FeatureMembership declaredShortName 81c848f417c72bee 4966 0 +FeatureMembership documentation 00360b795a3051cc 4966 0 +FeatureMembership elementId 31797c7c205ffe1c 4966 4966 +FeatureMembership isImplied 41bff65fd52f06d6 4966 0 +FeatureMembership isImpliedIncluded 1aa8bff1b702a654 4966 4966 +FeatureMembership isLibraryElement 2000b8b038a5d1fa 4966 76 +FeatureMembership memberElement c9dda260344fcc1c 4966 4966 +FeatureMembership memberElementId 38d725a374eaba0e 4966 4966 +FeatureMembership memberName feacd1658f16e7a0 4966 4353 +FeatureMembership memberShortName 4b81c985b774e202 4966 17 +FeatureMembership membershipOwningNamespace e38ccc516b0607a9 4966 4966 +FeatureMembership name 81c848f417c72bee 4966 0 +FeatureMembership ownedAnnotation 00360b795a3051cc 4966 0 +FeatureMembership ownedElement 00360b795a3051cc 4966 0 +FeatureMembership ownedMemberElement c9dda260344fcc1c 4966 4966 +FeatureMembership ownedMemberElementId 38d725a374eaba0e 4966 4966 +FeatureMembership ownedMemberFeature c9dda260344fcc1c 4966 4966 +FeatureMembership ownedMemberName feacd1658f16e7a0 4966 4353 +FeatureMembership ownedMemberShortName 3c6ed9324144d64c 4966 19 +FeatureMembership ownedRelatedElement da70b04f0fe04230 4966 4966 +FeatureMembership ownedRelationship 00360b795a3051cc 4966 0 +FeatureMembership owner 81c848f417c72bee 4966 0 +FeatureMembership owningMembership 81c848f417c72bee 4966 0 +FeatureMembership owningNamespace 81c848f417c72bee 4966 0 +FeatureMembership owningRelatedElement e38ccc516b0607a9 4966 4966 +FeatureMembership owningRelationship 81c848f417c72bee 4966 0 +FeatureMembership owningType e38ccc516b0607a9 4966 4966 +FeatureMembership qualifiedName 81c848f417c72bee 4966 0 +FeatureMembership relatedElement 4b25bc0dd3260ff5 4966 4966 +FeatureMembership shortName 81c848f417c72bee 4966 0 +FeatureMembership source 1ed5bd519be71dbf 4966 4966 +FeatureMembership target da70b04f0fe04230 4966 4966 +FeatureMembership textualRepresentation 00360b795a3051cc 4966 0 +FeatureMembership visibility 6560e9fcf4ef119e 4966 4719 +FeatureReferenceExpression aliasIds 192b663fba555fc2 1722 0 +FeatureReferenceExpression behavior 192b663fba555fc2 1722 0 +FeatureReferenceExpression chainingFeature 192b663fba555fc2 1722 0 +FeatureReferenceExpression crossFeature ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression declaredName ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression declaredShortName ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression differencingType 192b663fba555fc2 1722 0 +FeatureReferenceExpression directedFeature 37973ce2eafc430a 1722 37 +FeatureReferenceExpression direction ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression documentation 192b663fba555fc2 1722 0 +FeatureReferenceExpression elementId 435d55d8be101d44 1722 1722 +FeatureReferenceExpression endFeature 192b663fba555fc2 1722 0 +FeatureReferenceExpression endOwningType ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression feature 37973ce2eafc430a 1722 37 +FeatureReferenceExpression featureMembership b6d59856d9d634c3 1722 37 +FeatureReferenceExpression featureTarget 42bb219e2edd6fe2 1722 0 +FeatureReferenceExpression featuringType 192b663fba555fc2 1722 0 +FeatureReferenceExpression function ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression importedMembership 192b663fba555fc2 1722 0 +FeatureReferenceExpression inheritedFeature 192b663fba555fc2 1722 0 +FeatureReferenceExpression inheritedMembership 192b663fba555fc2 1722 0 +FeatureReferenceExpression input 192b663fba555fc2 1722 0 +FeatureReferenceExpression intersectingType 192b663fba555fc2 1722 0 +FeatureReferenceExpression isAbstract ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isComposite ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isConjugated 55577cc4a95915a0 1722 0 +FeatureReferenceExpression isConstant ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isDerived ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isEnd ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isImpliedIncluded c16a64ad16821262 1722 1722 +FeatureReferenceExpression isLibraryElement 55577cc4a95915a0 1722 0 +FeatureReferenceExpression isModelLevelEvaluable e45718ef9b5f77d2 1722 570 +FeatureReferenceExpression isOrdered ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isPortion ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isSufficient ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isUnique ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression isVariable ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression member 218dd2b2674f8b42 1722 1722 +FeatureReferenceExpression membership 0abc42d4c3bdc51b 1722 1722 +FeatureReferenceExpression multiplicity ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression name ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression output 37973ce2eafc430a 1722 37 +FeatureReferenceExpression ownedAnnotation 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedConjugator ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression ownedCrossSubsetting ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression ownedDifferencing 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedDisjoining 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedElement 2e32c29b3add8dc4 1722 42 +FeatureReferenceExpression ownedEndFeature 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedFeature 37973ce2eafc430a 1722 37 +FeatureReferenceExpression ownedFeatureChaining 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedFeatureInverting 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedFeatureMembership b6d59856d9d634c3 1722 37 +FeatureReferenceExpression ownedImport 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedIntersecting 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedMember 2e32c29b3add8dc4 1722 42 +FeatureReferenceExpression ownedMembership 0abc42d4c3bdc51b 1722 1722 +FeatureReferenceExpression ownedRedefinition 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedReferenceSubsetting ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression ownedRelationship 0abc42d4c3bdc51b 1722 1722 +FeatureReferenceExpression ownedSpecialization 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedSubsetting 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedTypeFeaturing 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedTyping 192b663fba555fc2 1722 0 +FeatureReferenceExpression ownedUnioning 192b663fba555fc2 1722 0 +FeatureReferenceExpression owner e19043dfdcb5f69c 1722 1722 +FeatureReferenceExpression owningFeatureMembership 24f412663649be37 1722 2 +FeatureReferenceExpression owningMembership e5be20a5906ce5d0 1722 1722 +FeatureReferenceExpression owningNamespace e19043dfdcb5f69c 1722 1722 +FeatureReferenceExpression owningRelationship e5be20a5906ce5d0 1722 1722 +FeatureReferenceExpression owningType 1e417441717b750d 1722 2 +FeatureReferenceExpression parameter 37973ce2eafc430a 1722 37 +FeatureReferenceExpression qualifiedName ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression referent 85e7b4c00be174ba 1722 1685 +FeatureReferenceExpression result 3463dc3dd02f4542 1722 37 +FeatureReferenceExpression shortName ca4b41d63c6a6c6c 1722 0 +FeatureReferenceExpression textualRepresentation 192b663fba555fc2 1722 0 +FeatureReferenceExpression type 192b663fba555fc2 1722 0 +FeatureReferenceExpression unioningType 192b663fba555fc2 1722 0 +FeatureTyping aliasIds 76eefbeb35b84dfc 2739 0 +FeatureTyping declaredName 9c7606770f3ff527 2739 0 +FeatureTyping declaredShortName 9c7606770f3ff527 2739 0 +FeatureTyping documentation 76eefbeb35b84dfc 2739 0 +FeatureTyping elementId f6e83c2e0a7f55cc 2739 2739 +FeatureTyping general 167dd08dec56c4db 2739 2739 +FeatureTyping isImplied 19d87771ff382417 2739 62 +FeatureTyping isImpliedIncluded b4acbaa2b8c7cc18 2739 2739 +FeatureTyping isLibraryElement 5e8d088e9e0e45db 2739 114 +FeatureTyping name 9c7606770f3ff527 2739 0 +FeatureTyping ownedAnnotation 76eefbeb35b84dfc 2739 0 +FeatureTyping ownedElement 76eefbeb35b84dfc 2739 0 +FeatureTyping ownedRelatedElement 76eefbeb35b84dfc 2739 0 +FeatureTyping ownedRelationship 76eefbeb35b84dfc 2739 0 +FeatureTyping owner 9c7606770f3ff527 2739 0 +FeatureTyping owningFeature 789149465074186e 2739 2739 +FeatureTyping owningMembership 9c7606770f3ff527 2739 0 +FeatureTyping owningNamespace 9c7606770f3ff527 2739 0 +FeatureTyping owningRelatedElement 789149465074186e 2739 2739 +FeatureTyping owningRelationship 9c7606770f3ff527 2739 0 +FeatureTyping owningType 789149465074186e 2739 2739 +FeatureTyping qualifiedName 9c7606770f3ff527 2739 0 +FeatureTyping relatedElement 7d1b2ce1bee7fbb5 2739 2739 +FeatureTyping shortName 9c7606770f3ff527 2739 0 +FeatureTyping source 1aa60fac6e3edc4a 2739 2739 +FeatureTyping specific 789149465074186e 2739 2739 +FeatureTyping target 117b013c5778b059 2739 2739 +FeatureTyping textualRepresentation 76eefbeb35b84dfc 2739 0 +FeatureTyping type 167dd08dec56c4db 2739 2739 +FeatureTyping typedFeature 789149465074186e 2739 2739 +FeatureValue aliasIds 5e28329b811d25a1 3825 0 +FeatureValue declaredName 3b234e6df5c8b944 3825 0 +FeatureValue declaredShortName 3b234e6df5c8b944 3825 0 +FeatureValue documentation 5e28329b811d25a1 3825 0 +FeatureValue elementId 3fb18c686b049520 3825 3825 +FeatureValue featureWithValue 84c0df2219480413 3825 3825 +FeatureValue isDefault 413b35144ffa45f2 3825 18 +FeatureValue isImplied 7b6547276ae1cd8c 3825 0 +FeatureValue isImpliedIncluded 10739a101a5312f9 3825 3825 +FeatureValue isInitial 2742bb665c1ae290 3825 8 +FeatureValue isLibraryElement ae59f51d9f343f5e 3825 50 +FeatureValue memberElement 6af83bfd821ea8f1 3825 3825 +FeatureValue memberElementId 9cfa3b2933747ee6 3825 3825 +FeatureValue memberName 3b234e6df5c8b944 3825 0 +FeatureValue memberShortName 3b234e6df5c8b944 3825 0 +FeatureValue membershipOwningNamespace 84c0df2219480413 3825 3825 +FeatureValue name 3b234e6df5c8b944 3825 0 +FeatureValue ownedAnnotation 5e28329b811d25a1 3825 0 +FeatureValue ownedElement 5e28329b811d25a1 3825 0 +FeatureValue ownedMemberElement 6af83bfd821ea8f1 3825 3825 +FeatureValue ownedMemberElementId 9cfa3b2933747ee6 3825 3825 +FeatureValue ownedMemberName 3b234e6df5c8b944 3825 0 +FeatureValue ownedMemberShortName 3b234e6df5c8b944 3825 0 +FeatureValue ownedRelatedElement 94eb609abf456509 3825 3825 +FeatureValue ownedRelationship 5e28329b811d25a1 3825 0 +FeatureValue owner 3b234e6df5c8b944 3825 0 +FeatureValue owningMembership 3b234e6df5c8b944 3825 0 +FeatureValue owningNamespace 3b234e6df5c8b944 3825 0 +FeatureValue owningRelatedElement 84c0df2219480413 3825 3825 +FeatureValue owningRelationship 3b234e6df5c8b944 3825 0 +FeatureValue qualifiedName 3b234e6df5c8b944 3825 0 +FeatureValue relatedElement a10391775c8fb9c5 3825 3825 +FeatureValue shortName 3b234e6df5c8b944 3825 0 +FeatureValue source a9bc0bd6c8537bfb 3825 3825 +FeatureValue target 94eb609abf456509 3825 3825 +FeatureValue textualRepresentation 5e28329b811d25a1 3825 0 +FeatureValue value 6af83bfd821ea8f1 3825 3825 +FeatureValue visibility 3b234e6df5c8b944 3825 0 +FlowDefinition action 73ed7ac011b51a56 2 0 +FlowDefinition aliasIds 73ed7ac011b51a56 2 0 +FlowDefinition associationEnd e657db3a4d47d937 2 1 +FlowDefinition declaredName 2f553c3718d4bcd0 2 2 +FlowDefinition declaredShortName 5b23f978dbddce70 2 0 +FlowDefinition differencingType 73ed7ac011b51a56 2 0 +FlowDefinition directedFeature 73ed7ac011b51a56 2 0 +FlowDefinition directedUsage 73ed7ac011b51a56 2 0 +FlowDefinition documentation 73ed7ac011b51a56 2 0 +FlowDefinition elementId 38d5337c790568c0 2 2 +FlowDefinition endFeature e657db3a4d47d937 2 1 +FlowDefinition feature 0f446d3e75caf2c3 2 1 +FlowDefinition featureMembership 6271ff984992efc7 2 1 +FlowDefinition flowEnd 73ed7ac011b51a56 2 0 +FlowDefinition importedMembership 73ed7ac011b51a56 2 0 +FlowDefinition inheritedFeature 73ed7ac011b51a56 2 0 +FlowDefinition inheritedMembership 73ed7ac011b51a56 2 0 +FlowDefinition input 73ed7ac011b51a56 2 0 +FlowDefinition intersectingType 73ed7ac011b51a56 2 0 +FlowDefinition isAbstract 2236eed276b5a889 2 1 +FlowDefinition isConjugated e60a57699af4fb3c 2 0 +FlowDefinition isImplied 5b23f978dbddce70 2 0 +FlowDefinition isImpliedIncluded 49bd6578d1fdce96 2 2 +FlowDefinition isIndividual 5b23f978dbddce70 2 0 +FlowDefinition isLibraryElement e60a57699af4fb3c 2 0 +FlowDefinition isSufficient e60a57699af4fb3c 2 0 +FlowDefinition isVariation e60a57699af4fb3c 2 0 +FlowDefinition member 0f446d3e75caf2c3 2 1 +FlowDefinition membership 6271ff984992efc7 2 1 +FlowDefinition multiplicity 5b23f978dbddce70 2 0 +FlowDefinition name 2f553c3718d4bcd0 2 2 +FlowDefinition output 73ed7ac011b51a56 2 0 +FlowDefinition ownedAction 73ed7ac011b51a56 2 0 +FlowDefinition ownedAllocation 73ed7ac011b51a56 2 0 +FlowDefinition ownedAnalysisCase 73ed7ac011b51a56 2 0 +FlowDefinition ownedAnnotation 73ed7ac011b51a56 2 0 +FlowDefinition ownedAttribute 73ed7ac011b51a56 2 0 +FlowDefinition ownedCalculation 73ed7ac011b51a56 2 0 +FlowDefinition ownedCase 73ed7ac011b51a56 2 0 +FlowDefinition ownedConcern 73ed7ac011b51a56 2 0 +FlowDefinition ownedConjugator 5b23f978dbddce70 2 0 +FlowDefinition ownedConnection 73ed7ac011b51a56 2 0 +FlowDefinition ownedConstraint 73ed7ac011b51a56 2 0 +FlowDefinition ownedDifferencing 73ed7ac011b51a56 2 0 +FlowDefinition ownedDisjoining 73ed7ac011b51a56 2 0 +FlowDefinition ownedElement 0f446d3e75caf2c3 2 1 +FlowDefinition ownedEndFeature e657db3a4d47d937 2 1 +FlowDefinition ownedEnumeration 73ed7ac011b51a56 2 0 +FlowDefinition ownedFeature 0f446d3e75caf2c3 2 1 +FlowDefinition ownedFeatureMembership 6271ff984992efc7 2 1 +FlowDefinition ownedFlow 73ed7ac011b51a56 2 0 +FlowDefinition ownedImport 73ed7ac011b51a56 2 0 +FlowDefinition ownedInterface 87b1c51e2b41a670 2 1 +FlowDefinition ownedIntersecting 73ed7ac011b51a56 2 0 +FlowDefinition ownedItem 73ed7ac011b51a56 2 0 +FlowDefinition ownedMember 0f446d3e75caf2c3 2 1 +FlowDefinition ownedMembership 6271ff984992efc7 2 1 +FlowDefinition ownedMetadata 73ed7ac011b51a56 2 0 +FlowDefinition ownedOccurrence e657db3a4d47d937 2 1 +FlowDefinition ownedPart 73ed7ac011b51a56 2 0 +FlowDefinition ownedPort e657db3a4d47d937 2 1 +FlowDefinition ownedReference 87b1c51e2b41a670 2 1 +FlowDefinition ownedRelatedElement 73ed7ac011b51a56 2 0 +FlowDefinition ownedRelationship 84049c191bb02b9f 2 2 +FlowDefinition ownedRendering 73ed7ac011b51a56 2 0 +FlowDefinition ownedRequirement 73ed7ac011b51a56 2 0 +FlowDefinition ownedSpecialization 7707388e0ce4f440 2 2 +FlowDefinition ownedState 73ed7ac011b51a56 2 0 +FlowDefinition ownedSubclassification 7707388e0ce4f440 2 2 +FlowDefinition ownedTransition 73ed7ac011b51a56 2 0 +FlowDefinition ownedUnioning 73ed7ac011b51a56 2 0 +FlowDefinition ownedUsage 0f446d3e75caf2c3 2 1 +FlowDefinition ownedUseCase 73ed7ac011b51a56 2 0 +FlowDefinition ownedVerificationCase 73ed7ac011b51a56 2 0 +FlowDefinition ownedView 73ed7ac011b51a56 2 0 +FlowDefinition ownedViewpoint 73ed7ac011b51a56 2 0 +FlowDefinition owner 1bb96416d5cb0d6c 2 2 +FlowDefinition owningMembership 50bc20beb4ffc93f 2 2 +FlowDefinition owningNamespace 1bb96416d5cb0d6c 2 2 +FlowDefinition owningRelatedElement 5b23f978dbddce70 2 0 +FlowDefinition owningRelationship 50bc20beb4ffc93f 2 2 +FlowDefinition parameter 73ed7ac011b51a56 2 0 +FlowDefinition qualifiedName a10eef73a1262e3b 2 2 +FlowDefinition relatedElement 73ed7ac011b51a56 2 0 +FlowDefinition relatedType 5483180fc42b1785 2 1 +FlowDefinition shortName 5b23f978dbddce70 2 0 +FlowDefinition source 73ed7ac011b51a56 2 0 +FlowDefinition sourceType 9c266396e1f50d3f 2 1 +FlowDefinition step 73ed7ac011b51a56 2 0 +FlowDefinition target 73ed7ac011b51a56 2 0 +FlowDefinition targetType 30b3c46640acf7ff 2 1 +FlowDefinition textualRepresentation 73ed7ac011b51a56 2 0 +FlowDefinition unioningType 73ed7ac011b51a56 2 0 +FlowDefinition usage 0f446d3e75caf2c3 2 1 +FlowDefinition variant 73ed7ac011b51a56 2 0 +FlowDefinition variantMembership 73ed7ac011b51a56 2 0 +FlowEnd aliasIds d33c02dbe74d73b9 244 0 +FlowEnd chainingFeature d33c02dbe74d73b9 244 0 +FlowEnd crossFeature 25cd5efbce3d8323 244 0 +FlowEnd declaredName 25cd5efbce3d8323 244 0 +FlowEnd declaredShortName 25cd5efbce3d8323 244 0 +FlowEnd differencingType d33c02dbe74d73b9 244 0 +FlowEnd directedFeature da830443e6ef0931 244 244 +FlowEnd direction 25cd5efbce3d8323 244 0 +FlowEnd documentation d33c02dbe74d73b9 244 0 +FlowEnd elementId 82837509e5aa6f90 244 244 +FlowEnd endFeature d33c02dbe74d73b9 244 0 +FlowEnd endOwningType d196619903ea3c4d 244 244 +FlowEnd feature da830443e6ef0931 244 244 +FlowEnd featureMembership 82447bc3c6cdf1bd 244 244 +FlowEnd featureTarget 302c1692db0491ce 244 0 +FlowEnd featuringType d33c02dbe74d73b9 244 0 +FlowEnd importedMembership d33c02dbe74d73b9 244 0 +FlowEnd inheritedFeature d33c02dbe74d73b9 244 0 +FlowEnd inheritedMembership d33c02dbe74d73b9 244 0 +FlowEnd input 0b90fb40e9036ae1 244 122 +FlowEnd intersectingType d33c02dbe74d73b9 244 0 +FlowEnd isAbstract 25cd5efbce3d8323 244 0 +FlowEnd isComposite 25cd5efbce3d8323 244 0 +FlowEnd isConjugated 8fab66a7f94cbb51 244 0 +FlowEnd isConstant 25cd5efbce3d8323 244 0 +FlowEnd isDerived 25cd5efbce3d8323 244 0 +FlowEnd isEnd 042f7984909630fd 244 244 +FlowEnd isImpliedIncluded 042f7984909630fd 244 244 +FlowEnd isLibraryElement 8fab66a7f94cbb51 244 0 +FlowEnd isOrdered 25cd5efbce3d8323 244 0 +FlowEnd isPortion 25cd5efbce3d8323 244 0 +FlowEnd isSufficient 25cd5efbce3d8323 244 0 +FlowEnd isUnique 25cd5efbce3d8323 244 0 +FlowEnd isVariable 25cd5efbce3d8323 244 0 +FlowEnd member da830443e6ef0931 244 244 +FlowEnd membership 82447bc3c6cdf1bd 244 244 +FlowEnd multiplicity 25cd5efbce3d8323 244 0 +FlowEnd name 72066bb8dc8a0f47 244 244 +FlowEnd output a22e0bdee5391209 244 122 +FlowEnd ownedAnnotation d33c02dbe74d73b9 244 0 +FlowEnd ownedConjugator 25cd5efbce3d8323 244 0 +FlowEnd ownedCrossSubsetting 25cd5efbce3d8323 244 0 +FlowEnd ownedDifferencing d33c02dbe74d73b9 244 0 +FlowEnd ownedDisjoining d33c02dbe74d73b9 244 0 +FlowEnd ownedElement ec7a6284ae317529 244 244 +FlowEnd ownedEndFeature d33c02dbe74d73b9 244 0 +FlowEnd ownedFeature da830443e6ef0931 244 244 +FlowEnd ownedFeatureChaining d33c02dbe74d73b9 244 0 +FlowEnd ownedFeatureInverting d33c02dbe74d73b9 244 0 +FlowEnd ownedFeatureMembership 82447bc3c6cdf1bd 244 244 +FlowEnd ownedImport d33c02dbe74d73b9 244 0 +FlowEnd ownedIntersecting d33c02dbe74d73b9 244 0 +FlowEnd ownedMember da830443e6ef0931 244 244 +FlowEnd ownedMembership 82447bc3c6cdf1bd 244 244 +FlowEnd ownedRedefinition d33c02dbe74d73b9 244 0 +FlowEnd ownedReferenceSubsetting 3db53c7a5c0712ae 244 241 +FlowEnd ownedRelationship 54dec9590d81e07f 244 244 +FlowEnd ownedSpecialization 993151fb47a6c0a9 244 241 +FlowEnd ownedSubsetting 993151fb47a6c0a9 244 241 +FlowEnd ownedTypeFeaturing d33c02dbe74d73b9 244 0 +FlowEnd ownedTyping d33c02dbe74d73b9 244 0 +FlowEnd ownedUnioning d33c02dbe74d73b9 244 0 +FlowEnd owner d196619903ea3c4d 244 244 +FlowEnd owningFeatureMembership b3cfa1cb3e89710a 244 244 +FlowEnd owningMembership b3cfa1cb3e89710a 244 244 +FlowEnd owningNamespace d196619903ea3c4d 244 244 +FlowEnd owningRelationship b3cfa1cb3e89710a 244 244 +FlowEnd owningType d196619903ea3c4d 244 244 +FlowEnd qualifiedName 0b8ee48708915493 244 130 +FlowEnd shortName 25cd5efbce3d8323 244 0 +FlowEnd textualRepresentation d33c02dbe74d73b9 244 0 +FlowEnd type ad0aec8ad828297e 244 146 +FlowEnd unioningType d33c02dbe74d73b9 244 0 +FlowUsage actionDefinition 437960690ffe330c 138 8 +FlowUsage aliasIds 6739ccf89892f02c 138 0 +FlowUsage association 437960690ffe330c 138 8 +FlowUsage behavior 437960690ffe330c 138 8 +FlowUsage chainingFeature 6739ccf89892f02c 138 0 +FlowUsage connectorEnd 42c1571e01dacb32 138 124 +FlowUsage crossFeature 89c8c45b24c6263a 138 0 +FlowUsage declaredName da7d5235f935e5f3 138 65 +FlowUsage declaredShortName 89c8c45b24c6263a 138 0 +FlowUsage defaultFeaturingType acc6b6fcf35b1f2e 138 109 +FlowUsage definition 437960690ffe330c 138 8 +FlowUsage differencingType 6739ccf89892f02c 138 0 +FlowUsage directedFeature 6739ccf89892f02c 138 0 +FlowUsage directedUsage 6739ccf89892f02c 138 0 +FlowUsage direction 89c8c45b24c6263a 138 0 +FlowUsage documentation 6739ccf89892f02c 138 0 +FlowUsage elementId 026db2ba3fe5c814 138 138 +FlowUsage endFeature 42c1571e01dacb32 138 124 +FlowUsage endOwningType 89c8c45b24c6263a 138 0 +FlowUsage feature cfbef3abcebd69c3 138 132 +FlowUsage featureMembership 1bf89a5de3105580 138 132 +FlowUsage featureTarget 66a027bff9468392 138 0 +FlowUsage featuringType 6739ccf89892f02c 138 0 +FlowUsage flowDefinition 437960690ffe330c 138 8 +FlowUsage flowEnd 40e801fdbce039b5 138 118 +FlowUsage importedMembership 6739ccf89892f02c 138 0 +FlowUsage individualDefinition 89c8c45b24c6263a 138 0 +FlowUsage inheritedFeature 6739ccf89892f02c 138 0 +FlowUsage inheritedMembership 6739ccf89892f02c 138 0 +FlowUsage input 6739ccf89892f02c 138 0 +FlowUsage interaction 437960690ffe330c 138 8 +FlowUsage intersectingType 6739ccf89892f02c 138 0 +FlowUsage isAbstract 7a1270115d01d5aa 138 0 +FlowUsage isComposite d6f5f34e0a9981d7 138 137 +FlowUsage isConjugated 7a1270115d01d5aa 138 0 +FlowUsage isConstant 7a1270115d01d5aa 138 0 +FlowUsage isDerived 7a1270115d01d5aa 138 0 +FlowUsage isEnd 7a1270115d01d5aa 138 0 +FlowUsage isImplied 89c8c45b24c6263a 138 0 +FlowUsage isImpliedIncluded f627069ebe32b304 138 138 +FlowUsage isIndividual 89c8c45b24c6263a 138 0 +FlowUsage isLibraryElement 7a1270115d01d5aa 138 0 +FlowUsage isOrdered 7a1270115d01d5aa 138 0 +FlowUsage isPortion 89c8c45b24c6263a 138 0 +FlowUsage isReference 99438362109b06d7 138 1 +FlowUsage isSufficient 89c8c45b24c6263a 138 0 +FlowUsage isUnique f627069ebe32b304 138 138 +FlowUsage isVariable 89c8c45b24c6263a 138 0 +FlowUsage isVariation 7a1270115d01d5aa 138 0 +FlowUsage mayTimeVary 89c8c45b24c6263a 138 0 +FlowUsage member 7676eb80159ae48e 138 138 +FlowUsage membership 6bb18ba4238467fb 138 138 +FlowUsage multiplicity 89c8c45b24c6263a 138 0 +FlowUsage name 2d9bfb28140196eb 138 83 +FlowUsage nestedAction 6739ccf89892f02c 138 0 +FlowUsage nestedAllocation 6739ccf89892f02c 138 0 +FlowUsage nestedAnalysisCase 6739ccf89892f02c 138 0 +FlowUsage nestedAttribute 4d9ef8b993af65cb 138 6 +FlowUsage nestedCalculation 6739ccf89892f02c 138 0 +FlowUsage nestedCase 6739ccf89892f02c 138 0 +FlowUsage nestedConcern 6739ccf89892f02c 138 0 +FlowUsage nestedConnection a2eb4766917e87d9 138 6 +FlowUsage nestedConstraint 6739ccf89892f02c 138 0 +FlowUsage nestedEnumeration 6739ccf89892f02c 138 0 +FlowUsage nestedFlow 6739ccf89892f02c 138 0 +FlowUsage nestedInterface 69132218dd8d81a9 138 6 +FlowUsage nestedItem 6739ccf89892f02c 138 0 +FlowUsage nestedMetadata 6739ccf89892f02c 138 0 +FlowUsage nestedOccurrence b8861b160213ad64 138 6 +FlowUsage nestedPart 6739ccf89892f02c 138 0 +FlowUsage nestedPort 6739ccf89892f02c 138 0 +FlowUsage nestedReference 69132218dd8d81a9 138 6 +FlowUsage nestedRendering 6739ccf89892f02c 138 0 +FlowUsage nestedRequirement 6739ccf89892f02c 138 0 +FlowUsage nestedState 6739ccf89892f02c 138 0 +FlowUsage nestedTransition 6739ccf89892f02c 138 0 +FlowUsage nestedUsage 2980865b575660f7 138 18 +FlowUsage nestedUseCase 6739ccf89892f02c 138 0 +FlowUsage nestedVerificationCase 6739ccf89892f02c 138 0 +FlowUsage nestedView 6739ccf89892f02c 138 0 +FlowUsage nestedViewpoint 6739ccf89892f02c 138 0 +FlowUsage occurrenceDefinition 437960690ffe330c 138 8 +FlowUsage output 6739ccf89892f02c 138 0 +FlowUsage ownedAnnotation 6739ccf89892f02c 138 0 +FlowUsage ownedConjugator 89c8c45b24c6263a 138 0 +FlowUsage ownedCrossSubsetting 89c8c45b24c6263a 138 0 +FlowUsage ownedDifferencing 6739ccf89892f02c 138 0 +FlowUsage ownedDisjoining 6739ccf89892f02c 138 0 +FlowUsage ownedElement 7676eb80159ae48e 138 138 +FlowUsage ownedEndFeature 42c1571e01dacb32 138 124 +FlowUsage ownedFeature cfbef3abcebd69c3 138 132 +FlowUsage ownedFeatureChaining 6739ccf89892f02c 138 0 +FlowUsage ownedFeatureInverting 6739ccf89892f02c 138 0 +FlowUsage ownedFeatureMembership 1bf89a5de3105580 138 132 +FlowUsage ownedImport 6739ccf89892f02c 138 0 +FlowUsage ownedIntersecting 6739ccf89892f02c 138 0 +FlowUsage ownedMember 7676eb80159ae48e 138 138 +FlowUsage ownedMembership 6bb18ba4238467fb 138 138 +FlowUsage ownedRedefinition 0c87338fdbb15b85 138 18 +FlowUsage ownedReferenceSubsetting 89c8c45b24c6263a 138 0 +FlowUsage ownedRelatedElement 6739ccf89892f02c 138 0 +FlowUsage ownedRelationship e20ecd2288f07b69 138 138 +FlowUsage ownedSpecialization 4b74c9c1f1d2344c 138 138 +FlowUsage ownedSubsetting a16416c631d677da 138 138 +FlowUsage ownedTypeFeaturing 6739ccf89892f02c 138 0 +FlowUsage ownedTyping 415b512cf0e3f1a6 138 8 +FlowUsage ownedUnioning 6739ccf89892f02c 138 0 +FlowUsage owner 25ee06aa42f5db75 138 138 +FlowUsage owningDefinition b298d867d6628575 138 41 +FlowUsage owningFeatureMembership d0b8a9be0cb247d2 138 137 +FlowUsage owningMembership ae37561ddbb27f2a 138 138 +FlowUsage owningNamespace 25ee06aa42f5db75 138 138 +FlowUsage owningRelatedElement 89c8c45b24c6263a 138 0 +FlowUsage owningRelationship ae37561ddbb27f2a 138 138 +FlowUsage owningType 60f2c75c44f36d19 138 137 +FlowUsage owningUsage 3822b34f93570dde 138 96 +FlowUsage parameter 6739ccf89892f02c 138 0 +FlowUsage payloadFeature 22bb18fc9945bab5 138 48 +FlowUsage payloadType bc3a5d0dad93b44e 138 48 +FlowUsage portionKind 89c8c45b24c6263a 138 0 +FlowUsage qualifiedName 07e283f4f48a7269 138 83 +FlowUsage relatedElement 6739ccf89892f02c 138 0 +FlowUsage relatedFeature 9cad2a98bbb1865c 138 123 +FlowUsage shortName 89c8c45b24c6263a 138 0 +FlowUsage source 6739ccf89892f02c 138 0 +FlowUsage sourceFeature c33d72208adb8a13 138 123 +FlowUsage sourceOutputFeature 16e567f0bc2060de 138 118 +FlowUsage target 6739ccf89892f02c 138 0 +FlowUsage targetFeature 284b4d7ed50074f4 138 122 +FlowUsage targetInputFeature 5c62620893ff0261 138 118 +FlowUsage textualRepresentation 6739ccf89892f02c 138 0 +FlowUsage type 437960690ffe330c 138 8 +FlowUsage unioningType 6739ccf89892f02c 138 0 +FlowUsage usage 2980865b575660f7 138 18 +FlowUsage variant 6739ccf89892f02c 138 0 +FlowUsage variantMembership 6739ccf89892f02c 138 0 +ForLoopActionUsage actionDefinition 4629922cff854cc1 3 0 +ForLoopActionUsage aliasIds 4629922cff854cc1 3 0 +ForLoopActionUsage behavior 4629922cff854cc1 3 0 +ForLoopActionUsage bodyAction 1cf318c62329e4d2 3 3 +ForLoopActionUsage chainingFeature 4629922cff854cc1 3 0 +ForLoopActionUsage crossFeature 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage declaredName 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage declaredShortName 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage definition 4629922cff854cc1 3 0 +ForLoopActionUsage differencingType 4629922cff854cc1 3 0 +ForLoopActionUsage directedFeature 188e695deb9223c3 3 3 +ForLoopActionUsage directedUsage 188e695deb9223c3 3 3 +ForLoopActionUsage direction 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage documentation 4629922cff854cc1 3 0 +ForLoopActionUsage elementId 41696aaee4a847b4 3 3 +ForLoopActionUsage endFeature 4629922cff854cc1 3 0 +ForLoopActionUsage endOwningType 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage feature 7622b696d3e8c675 3 3 +ForLoopActionUsage featureMembership 64a886c7c6245f37 3 3 +ForLoopActionUsage featureTarget fdf575856e3c24ad 3 0 +ForLoopActionUsage featuringType 4629922cff854cc1 3 0 +ForLoopActionUsage importedMembership 4629922cff854cc1 3 0 +ForLoopActionUsage individualDefinition 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage inheritedFeature 4629922cff854cc1 3 0 +ForLoopActionUsage inheritedMembership 4629922cff854cc1 3 0 +ForLoopActionUsage input 188e695deb9223c3 3 3 +ForLoopActionUsage intersectingType 4629922cff854cc1 3 0 +ForLoopActionUsage isAbstract 7e3168b194ad2d22 3 0 +ForLoopActionUsage isComposite e7326f3db2eba311 3 3 +ForLoopActionUsage isConjugated 7e3168b194ad2d22 3 0 +ForLoopActionUsage isConstant 7e3168b194ad2d22 3 0 +ForLoopActionUsage isDerived 7e3168b194ad2d22 3 0 +ForLoopActionUsage isEnd 7e3168b194ad2d22 3 0 +ForLoopActionUsage isImpliedIncluded e7326f3db2eba311 3 3 +ForLoopActionUsage isIndividual 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage isLibraryElement 7e3168b194ad2d22 3 0 +ForLoopActionUsage isOrdered 7e3168b194ad2d22 3 0 +ForLoopActionUsage isPortion 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage isReference 7e3168b194ad2d22 3 0 +ForLoopActionUsage isSufficient 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage isUnique e7326f3db2eba311 3 3 +ForLoopActionUsage isVariable 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage isVariation 7e3168b194ad2d22 3 0 +ForLoopActionUsage loopVariable 1a185b361cf78d3b 3 3 +ForLoopActionUsage mayTimeVary 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage member 7622b696d3e8c675 3 3 +ForLoopActionUsage membership 64a886c7c6245f37 3 3 +ForLoopActionUsage multiplicity 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage name 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage nestedAction be4971dde3085df4 3 3 +ForLoopActionUsage nestedAllocation 4629922cff854cc1 3 0 +ForLoopActionUsage nestedAnalysisCase 4629922cff854cc1 3 0 +ForLoopActionUsage nestedAttribute 4629922cff854cc1 3 0 +ForLoopActionUsage nestedCalculation 4629922cff854cc1 3 0 +ForLoopActionUsage nestedCase 4629922cff854cc1 3 0 +ForLoopActionUsage nestedConcern 4629922cff854cc1 3 0 +ForLoopActionUsage nestedConnection 4629922cff854cc1 3 0 +ForLoopActionUsage nestedConstraint 4629922cff854cc1 3 0 +ForLoopActionUsage nestedEnumeration 4629922cff854cc1 3 0 +ForLoopActionUsage nestedFlow 4629922cff854cc1 3 0 +ForLoopActionUsage nestedInterface 7efd02c3451dc694 3 3 +ForLoopActionUsage nestedItem 4629922cff854cc1 3 0 +ForLoopActionUsage nestedMetadata 4629922cff854cc1 3 0 +ForLoopActionUsage nestedOccurrence be4971dde3085df4 3 3 +ForLoopActionUsage nestedPart 4629922cff854cc1 3 0 +ForLoopActionUsage nestedPort 4629922cff854cc1 3 0 +ForLoopActionUsage nestedReference 7efd02c3451dc694 3 3 +ForLoopActionUsage nestedRendering 4629922cff854cc1 3 0 +ForLoopActionUsage nestedRequirement 4629922cff854cc1 3 0 +ForLoopActionUsage nestedState 4629922cff854cc1 3 0 +ForLoopActionUsage nestedTransition 4629922cff854cc1 3 0 +ForLoopActionUsage nestedUsage 7622b696d3e8c675 3 3 +ForLoopActionUsage nestedUseCase 4629922cff854cc1 3 0 +ForLoopActionUsage nestedVerificationCase 4629922cff854cc1 3 0 +ForLoopActionUsage nestedView 4629922cff854cc1 3 0 +ForLoopActionUsage nestedViewpoint 4629922cff854cc1 3 0 +ForLoopActionUsage occurrenceDefinition 4629922cff854cc1 3 0 +ForLoopActionUsage output 4629922cff854cc1 3 0 +ForLoopActionUsage ownedAnnotation 4629922cff854cc1 3 0 +ForLoopActionUsage ownedConjugator 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage ownedCrossSubsetting 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage ownedDifferencing 4629922cff854cc1 3 0 +ForLoopActionUsage ownedDisjoining 4629922cff854cc1 3 0 +ForLoopActionUsage ownedElement 7622b696d3e8c675 3 3 +ForLoopActionUsage ownedEndFeature 4629922cff854cc1 3 0 +ForLoopActionUsage ownedFeature 7622b696d3e8c675 3 3 +ForLoopActionUsage ownedFeatureChaining 4629922cff854cc1 3 0 +ForLoopActionUsage ownedFeatureInverting 4629922cff854cc1 3 0 +ForLoopActionUsage ownedFeatureMembership 64a886c7c6245f37 3 3 +ForLoopActionUsage ownedImport 4629922cff854cc1 3 0 +ForLoopActionUsage ownedIntersecting 4629922cff854cc1 3 0 +ForLoopActionUsage ownedMember 7622b696d3e8c675 3 3 +ForLoopActionUsage ownedMembership 64a886c7c6245f37 3 3 +ForLoopActionUsage ownedRedefinition 4629922cff854cc1 3 0 +ForLoopActionUsage ownedReferenceSubsetting 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage ownedRelationship 437c17122beee713 3 3 +ForLoopActionUsage ownedSpecialization 3aa52bd11ff8d875 3 3 +ForLoopActionUsage ownedSubsetting 3aa52bd11ff8d875 3 3 +ForLoopActionUsage ownedTypeFeaturing 4629922cff854cc1 3 0 +ForLoopActionUsage ownedTyping 4629922cff854cc1 3 0 +ForLoopActionUsage ownedUnioning 4629922cff854cc1 3 0 +ForLoopActionUsage owner 510547ad9699a1d2 3 3 +ForLoopActionUsage owningDefinition a450e3ff77efc8cf 3 2 +ForLoopActionUsage owningFeatureMembership 348d779a3efb4d53 3 3 +ForLoopActionUsage owningMembership 348d779a3efb4d53 3 3 +ForLoopActionUsage owningNamespace 510547ad9699a1d2 3 3 +ForLoopActionUsage owningRelationship 348d779a3efb4d53 3 3 +ForLoopActionUsage owningType 510547ad9699a1d2 3 3 +ForLoopActionUsage owningUsage 17c50e9d6a5b979d 3 1 +ForLoopActionUsage parameter 188e695deb9223c3 3 3 +ForLoopActionUsage portionKind 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage qualifiedName 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage seqArgument 2969c316538b1e5a 3 3 +ForLoopActionUsage shortName 6b10aaef4bb1be9a 3 0 +ForLoopActionUsage textualRepresentation 4629922cff854cc1 3 0 +ForLoopActionUsage type 4629922cff854cc1 3 0 +ForLoopActionUsage unioningType 4629922cff854cc1 3 0 +ForLoopActionUsage usage 7622b696d3e8c675 3 3 +ForLoopActionUsage variant 4629922cff854cc1 3 0 +ForLoopActionUsage variantMembership 4629922cff854cc1 3 0 +ForkNode actionDefinition 9cf4bcb75b9f414f 6 0 +ForkNode aliasIds 9cf4bcb75b9f414f 6 0 +ForkNode behavior 9cf4bcb75b9f414f 6 0 +ForkNode chainingFeature 9cf4bcb75b9f414f 6 0 +ForkNode crossFeature aada5e3e378a1fbf 6 0 +ForkNode declaredName 970df574d1cd1947 6 4 +ForkNode declaredShortName aada5e3e378a1fbf 6 0 +ForkNode definition 9cf4bcb75b9f414f 6 0 +ForkNode differencingType 9cf4bcb75b9f414f 6 0 +ForkNode directedFeature 5ccb746fea7c29b2 6 1 +ForkNode directedUsage 5ccb746fea7c29b2 6 1 +ForkNode direction aada5e3e378a1fbf 6 0 +ForkNode documentation 9cf4bcb75b9f414f 6 0 +ForkNode elementId 9fed83cf92857d4c 6 6 +ForkNode endFeature 9cf4bcb75b9f414f 6 0 +ForkNode endOwningType aada5e3e378a1fbf 6 0 +ForkNode feature 5ccb746fea7c29b2 6 1 +ForkNode featureMembership 0c7a8e51f9c34c1d 6 1 +ForkNode featureTarget be78339f10b8eb58 6 0 +ForkNode featuringType 9cf4bcb75b9f414f 6 0 +ForkNode importedMembership 9cf4bcb75b9f414f 6 0 +ForkNode individualDefinition aada5e3e378a1fbf 6 0 +ForkNode inheritedFeature 9cf4bcb75b9f414f 6 0 +ForkNode inheritedMembership 9cf4bcb75b9f414f 6 0 +ForkNode input 351eadc65c06893a 6 1 +ForkNode intersectingType 9cf4bcb75b9f414f 6 0 +ForkNode isAbstract 2bf97b4033fd3a35 6 0 +ForkNode isComposite 631f361abb2e9b03 6 6 +ForkNode isConjugated 2bf97b4033fd3a35 6 0 +ForkNode isConstant 2bf97b4033fd3a35 6 0 +ForkNode isDerived 2bf97b4033fd3a35 6 0 +ForkNode isEnd 2bf97b4033fd3a35 6 0 +ForkNode isImpliedIncluded 631f361abb2e9b03 6 6 +ForkNode isIndividual aada5e3e378a1fbf 6 0 +ForkNode isLibraryElement 2bf97b4033fd3a35 6 0 +ForkNode isOrdered 2bf97b4033fd3a35 6 0 +ForkNode isPortion aada5e3e378a1fbf 6 0 +ForkNode isReference 2bf97b4033fd3a35 6 0 +ForkNode isSufficient aada5e3e378a1fbf 6 0 +ForkNode isUnique 631f361abb2e9b03 6 6 +ForkNode isVariable aada5e3e378a1fbf 6 0 +ForkNode isVariation 2bf97b4033fd3a35 6 0 +ForkNode mayTimeVary aada5e3e378a1fbf 6 0 +ForkNode member 5ccb746fea7c29b2 6 1 +ForkNode membership 0c7a8e51f9c34c1d 6 1 +ForkNode multiplicity aada5e3e378a1fbf 6 0 +ForkNode name 970df574d1cd1947 6 4 +ForkNode nestedAction 9cf4bcb75b9f414f 6 0 +ForkNode nestedAllocation 9cf4bcb75b9f414f 6 0 +ForkNode nestedAnalysisCase 9cf4bcb75b9f414f 6 0 +ForkNode nestedAttribute 9cf4bcb75b9f414f 6 0 +ForkNode nestedCalculation 9cf4bcb75b9f414f 6 0 +ForkNode nestedCase 9cf4bcb75b9f414f 6 0 +ForkNode nestedConcern 9cf4bcb75b9f414f 6 0 +ForkNode nestedConnection 9cf4bcb75b9f414f 6 0 +ForkNode nestedConstraint 9cf4bcb75b9f414f 6 0 +ForkNode nestedEnumeration 9cf4bcb75b9f414f 6 0 +ForkNode nestedFlow 9cf4bcb75b9f414f 6 0 +ForkNode nestedInterface 5ccb746fea7c29b2 6 1 +ForkNode nestedItem 9cf4bcb75b9f414f 6 0 +ForkNode nestedMetadata 9cf4bcb75b9f414f 6 0 +ForkNode nestedOccurrence 9cf4bcb75b9f414f 6 0 +ForkNode nestedPart 9cf4bcb75b9f414f 6 0 +ForkNode nestedPort 9cf4bcb75b9f414f 6 0 +ForkNode nestedReference 5ccb746fea7c29b2 6 1 +ForkNode nestedRendering 9cf4bcb75b9f414f 6 0 +ForkNode nestedRequirement 9cf4bcb75b9f414f 6 0 +ForkNode nestedState 9cf4bcb75b9f414f 6 0 +ForkNode nestedTransition 9cf4bcb75b9f414f 6 0 +ForkNode nestedUsage 5ccb746fea7c29b2 6 1 +ForkNode nestedUseCase 9cf4bcb75b9f414f 6 0 +ForkNode nestedVerificationCase 9cf4bcb75b9f414f 6 0 +ForkNode nestedView 9cf4bcb75b9f414f 6 0 +ForkNode nestedViewpoint 9cf4bcb75b9f414f 6 0 +ForkNode occurrenceDefinition 9cf4bcb75b9f414f 6 0 +ForkNode output a96772f53f4cfe95 6 1 +ForkNode ownedAnnotation 9cf4bcb75b9f414f 6 0 +ForkNode ownedConjugator aada5e3e378a1fbf 6 0 +ForkNode ownedCrossSubsetting aada5e3e378a1fbf 6 0 +ForkNode ownedDifferencing 9cf4bcb75b9f414f 6 0 +ForkNode ownedDisjoining 9cf4bcb75b9f414f 6 0 +ForkNode ownedElement 5ccb746fea7c29b2 6 1 +ForkNode ownedEndFeature 9cf4bcb75b9f414f 6 0 +ForkNode ownedFeature 5ccb746fea7c29b2 6 1 +ForkNode ownedFeatureChaining 9cf4bcb75b9f414f 6 0 +ForkNode ownedFeatureInverting 9cf4bcb75b9f414f 6 0 +ForkNode ownedFeatureMembership 0c7a8e51f9c34c1d 6 1 +ForkNode ownedImport 9cf4bcb75b9f414f 6 0 +ForkNode ownedIntersecting 9cf4bcb75b9f414f 6 0 +ForkNode ownedMember 5ccb746fea7c29b2 6 1 +ForkNode ownedMembership 0c7a8e51f9c34c1d 6 1 +ForkNode ownedRedefinition 9cf4bcb75b9f414f 6 0 +ForkNode ownedReferenceSubsetting aada5e3e378a1fbf 6 0 +ForkNode ownedRelationship 0c7a8e51f9c34c1d 6 1 +ForkNode ownedSpecialization 9cf4bcb75b9f414f 6 0 +ForkNode ownedSubsetting 9cf4bcb75b9f414f 6 0 +ForkNode ownedTypeFeaturing 9cf4bcb75b9f414f 6 0 +ForkNode ownedTyping 9cf4bcb75b9f414f 6 0 +ForkNode ownedUnioning 9cf4bcb75b9f414f 6 0 +ForkNode owner e6315920f4d88a2e 6 6 +ForkNode owningDefinition 5c3a466295fafedf 6 3 +ForkNode owningFeatureMembership 11487f79f646c4fa 6 6 +ForkNode owningMembership 11487f79f646c4fa 6 6 +ForkNode owningNamespace e6315920f4d88a2e 6 6 +ForkNode owningRelationship 11487f79f646c4fa 6 6 +ForkNode owningType e6315920f4d88a2e 6 6 +ForkNode owningUsage 34d170fc9667ab0e 6 3 +ForkNode parameter 5ccb746fea7c29b2 6 1 +ForkNode portionKind aada5e3e378a1fbf 6 0 +ForkNode qualifiedName dd0780b1d34a6d74 6 4 +ForkNode shortName aada5e3e378a1fbf 6 0 +ForkNode textualRepresentation 9cf4bcb75b9f414f 6 0 +ForkNode type 9cf4bcb75b9f414f 6 0 +ForkNode unioningType 9cf4bcb75b9f414f 6 0 +ForkNode usage 5ccb746fea7c29b2 6 1 +ForkNode variant 9cf4bcb75b9f414f 6 0 +ForkNode variantMembership 9cf4bcb75b9f414f 6 0 +FramedConcernMembership aliasIds d54ed67d945ec95a 6 0 +FramedConcernMembership declaredName 7f81a799e40f0b08 6 0 +FramedConcernMembership declaredShortName 7f81a799e40f0b08 6 0 +FramedConcernMembership documentation d54ed67d945ec95a 6 0 +FramedConcernMembership elementId 4d426ae9e723280c 6 6 +FramedConcernMembership isImplied ff9aadd898cafaa4 6 0 +FramedConcernMembership isImpliedIncluded 0bf6862b8450a5ca 6 6 +FramedConcernMembership isLibraryElement ff9aadd898cafaa4 6 0 +FramedConcernMembership kind 047f164288eb8814 6 6 +FramedConcernMembership memberElement d7996c61dae29b03 6 6 +FramedConcernMembership memberElementId 28bde858a00a36fd 6 6 +FramedConcernMembership memberName 2d20a1b21cce4cc6 6 6 +FramedConcernMembership memberShortName 7f81a799e40f0b08 6 0 +FramedConcernMembership membershipOwningNamespace bf2daf7bd43752f1 6 6 +FramedConcernMembership name 7f81a799e40f0b08 6 0 +FramedConcernMembership ownedAnnotation d54ed67d945ec95a 6 0 +FramedConcernMembership ownedConcern d7996c61dae29b03 6 6 +FramedConcernMembership ownedConstraint d7996c61dae29b03 6 6 +FramedConcernMembership ownedElement d54ed67d945ec95a 6 0 +FramedConcernMembership ownedMemberElement d7996c61dae29b03 6 6 +FramedConcernMembership ownedMemberElementId 28bde858a00a36fd 6 6 +FramedConcernMembership ownedMemberFeature d7996c61dae29b03 6 6 +FramedConcernMembership ownedMemberName 2d20a1b21cce4cc6 6 6 +FramedConcernMembership ownedMemberShortName 7f81a799e40f0b08 6 0 +FramedConcernMembership ownedRelatedElement ffe0171847f840e9 6 6 +FramedConcernMembership ownedRelationship d54ed67d945ec95a 6 0 +FramedConcernMembership owner 7f81a799e40f0b08 6 0 +FramedConcernMembership owningMembership 7f81a799e40f0b08 6 0 +FramedConcernMembership owningNamespace 7f81a799e40f0b08 6 0 +FramedConcernMembership owningRelatedElement bf2daf7bd43752f1 6 6 +FramedConcernMembership owningRelationship 7f81a799e40f0b08 6 0 +FramedConcernMembership owningType bf2daf7bd43752f1 6 6 +FramedConcernMembership qualifiedName 7f81a799e40f0b08 6 0 +FramedConcernMembership referencedConcern 10647f7628533fda 6 6 +FramedConcernMembership referencedConstraint 10647f7628533fda 6 6 +FramedConcernMembership relatedElement 632fa848dd8ec7ae 6 6 +FramedConcernMembership shortName 7f81a799e40f0b08 6 0 +FramedConcernMembership source be6681bac6ebb1cf 6 6 +FramedConcernMembership target ffe0171847f840e9 6 6 +FramedConcernMembership textualRepresentation d54ed67d945ec95a 6 0 +FramedConcernMembership visibility 332e66b62b778218 6 6 +IfActionUsage actionDefinition f08edf5fbb89c3af 4 0 +IfActionUsage aliasIds f08edf5fbb89c3af 4 0 +IfActionUsage behavior f08edf5fbb89c3af 4 0 +IfActionUsage chainingFeature f08edf5fbb89c3af 4 0 +IfActionUsage crossFeature 61a209a68fdfa1d5 4 0 +IfActionUsage declaredName 61a209a68fdfa1d5 4 0 +IfActionUsage declaredShortName 61a209a68fdfa1d5 4 0 +IfActionUsage definition f08edf5fbb89c3af 4 0 +IfActionUsage differencingType f08edf5fbb89c3af 4 0 +IfActionUsage directedFeature c05aa7cc835ea16f 4 4 +IfActionUsage directedUsage c05aa7cc835ea16f 4 4 +IfActionUsage direction 61a209a68fdfa1d5 4 0 +IfActionUsage documentation f08edf5fbb89c3af 4 0 +IfActionUsage elementId b0ddfb0a3cd20d78 4 4 +IfActionUsage elseAction 76b634c9eee708ac 4 2 +IfActionUsage endFeature f08edf5fbb89c3af 4 0 +IfActionUsage endOwningType 61a209a68fdfa1d5 4 0 +IfActionUsage feature c05aa7cc835ea16f 4 4 +IfActionUsage featureMembership 1521c6255be50424 4 4 +IfActionUsage featureTarget 98428a5ee98af336 4 0 +IfActionUsage featuringType f08edf5fbb89c3af 4 0 +IfActionUsage ifArgument f7bec016608d4b26 4 4 +IfActionUsage importedMembership f08edf5fbb89c3af 4 0 +IfActionUsage individualDefinition 61a209a68fdfa1d5 4 0 +IfActionUsage inheritedFeature f08edf5fbb89c3af 4 0 +IfActionUsage inheritedMembership f08edf5fbb89c3af 4 0 +IfActionUsage input c05aa7cc835ea16f 4 4 +IfActionUsage intersectingType f08edf5fbb89c3af 4 0 +IfActionUsage isAbstract 245045b624acc607 4 0 +IfActionUsage isComposite ff56baad27eba373 4 4 +IfActionUsage isConjugated 245045b624acc607 4 0 +IfActionUsage isConstant 245045b624acc607 4 0 +IfActionUsage isDerived 245045b624acc607 4 0 +IfActionUsage isEnd 245045b624acc607 4 0 +IfActionUsage isImpliedIncluded ff56baad27eba373 4 4 +IfActionUsage isIndividual 61a209a68fdfa1d5 4 0 +IfActionUsage isLibraryElement 245045b624acc607 4 0 +IfActionUsage isOrdered 245045b624acc607 4 0 +IfActionUsage isPortion 61a209a68fdfa1d5 4 0 +IfActionUsage isReference 245045b624acc607 4 0 +IfActionUsage isSufficient 61a209a68fdfa1d5 4 0 +IfActionUsage isUnique ff56baad27eba373 4 4 +IfActionUsage isVariable 61a209a68fdfa1d5 4 0 +IfActionUsage isVariation 245045b624acc607 4 0 +IfActionUsage mayTimeVary 61a209a68fdfa1d5 4 0 +IfActionUsage member c05aa7cc835ea16f 4 4 +IfActionUsage membership 1521c6255be50424 4 4 +IfActionUsage multiplicity 61a209a68fdfa1d5 4 0 +IfActionUsage name 61a209a68fdfa1d5 4 0 +IfActionUsage nestedAction 2da7b3a27cff3602 4 4 +IfActionUsage nestedAllocation f08edf5fbb89c3af 4 0 +IfActionUsage nestedAnalysisCase f08edf5fbb89c3af 4 0 +IfActionUsage nestedAttribute f08edf5fbb89c3af 4 0 +IfActionUsage nestedCalculation f08edf5fbb89c3af 4 0 +IfActionUsage nestedCase f08edf5fbb89c3af 4 0 +IfActionUsage nestedConcern f08edf5fbb89c3af 4 0 +IfActionUsage nestedConnection f08edf5fbb89c3af 4 0 +IfActionUsage nestedConstraint f08edf5fbb89c3af 4 0 +IfActionUsage nestedEnumeration f08edf5fbb89c3af 4 0 +IfActionUsage nestedFlow f08edf5fbb89c3af 4 0 +IfActionUsage nestedInterface 7255426307f0f962 4 4 +IfActionUsage nestedItem f08edf5fbb89c3af 4 0 +IfActionUsage nestedMetadata f08edf5fbb89c3af 4 0 +IfActionUsage nestedOccurrence 2da7b3a27cff3602 4 4 +IfActionUsage nestedPart f08edf5fbb89c3af 4 0 +IfActionUsage nestedPort f08edf5fbb89c3af 4 0 +IfActionUsage nestedReference 7255426307f0f962 4 4 +IfActionUsage nestedRendering f08edf5fbb89c3af 4 0 +IfActionUsage nestedRequirement f08edf5fbb89c3af 4 0 +IfActionUsage nestedState f08edf5fbb89c3af 4 0 +IfActionUsage nestedTransition f08edf5fbb89c3af 4 0 +IfActionUsage nestedUsage c05aa7cc835ea16f 4 4 +IfActionUsage nestedUseCase f08edf5fbb89c3af 4 0 +IfActionUsage nestedVerificationCase f08edf5fbb89c3af 4 0 +IfActionUsage nestedView f08edf5fbb89c3af 4 0 +IfActionUsage nestedViewpoint f08edf5fbb89c3af 4 0 +IfActionUsage occurrenceDefinition f08edf5fbb89c3af 4 0 +IfActionUsage output f08edf5fbb89c3af 4 0 +IfActionUsage ownedAnnotation f08edf5fbb89c3af 4 0 +IfActionUsage ownedConjugator 61a209a68fdfa1d5 4 0 +IfActionUsage ownedCrossSubsetting 61a209a68fdfa1d5 4 0 +IfActionUsage ownedDifferencing f08edf5fbb89c3af 4 0 +IfActionUsage ownedDisjoining f08edf5fbb89c3af 4 0 +IfActionUsage ownedElement c05aa7cc835ea16f 4 4 +IfActionUsage ownedEndFeature f08edf5fbb89c3af 4 0 +IfActionUsage ownedFeature c05aa7cc835ea16f 4 4 +IfActionUsage ownedFeatureChaining f08edf5fbb89c3af 4 0 +IfActionUsage ownedFeatureInverting f08edf5fbb89c3af 4 0 +IfActionUsage ownedFeatureMembership 1521c6255be50424 4 4 +IfActionUsage ownedImport f08edf5fbb89c3af 4 0 +IfActionUsage ownedIntersecting f08edf5fbb89c3af 4 0 +IfActionUsage ownedMember c05aa7cc835ea16f 4 4 +IfActionUsage ownedMembership 1521c6255be50424 4 4 +IfActionUsage ownedRedefinition f08edf5fbb89c3af 4 0 +IfActionUsage ownedReferenceSubsetting 61a209a68fdfa1d5 4 0 +IfActionUsage ownedRelationship 42e908ad03fea1b8 4 4 +IfActionUsage ownedSpecialization 23892c56bae6f17b 4 4 +IfActionUsage ownedSubsetting 23892c56bae6f17b 4 4 +IfActionUsage ownedTypeFeaturing f08edf5fbb89c3af 4 0 +IfActionUsage ownedTyping f08edf5fbb89c3af 4 0 +IfActionUsage ownedUnioning f08edf5fbb89c3af 4 0 +IfActionUsage owner 5e20382bc94a1c21 4 4 +IfActionUsage owningDefinition 61a209a68fdfa1d5 4 0 +IfActionUsage owningFeatureMembership 230f11c8d8c97135 4 4 +IfActionUsage owningMembership 230f11c8d8c97135 4 4 +IfActionUsage owningNamespace 5e20382bc94a1c21 4 4 +IfActionUsage owningRelationship 230f11c8d8c97135 4 4 +IfActionUsage owningType 5e20382bc94a1c21 4 4 +IfActionUsage owningUsage 5e20382bc94a1c21 4 4 +IfActionUsage parameter c05aa7cc835ea16f 4 4 +IfActionUsage portionKind 61a209a68fdfa1d5 4 0 +IfActionUsage qualifiedName 61a209a68fdfa1d5 4 0 +IfActionUsage shortName 61a209a68fdfa1d5 4 0 +IfActionUsage textualRepresentation f08edf5fbb89c3af 4 0 +IfActionUsage thenAction e3a90df29f5300cf 4 4 +IfActionUsage type f08edf5fbb89c3af 4 0 +IfActionUsage unioningType f08edf5fbb89c3af 4 0 +IfActionUsage usage c05aa7cc835ea16f 4 4 +IfActionUsage variant f08edf5fbb89c3af 4 0 +IfActionUsage variantMembership f08edf5fbb89c3af 4 0 +IncludeUseCaseUsage actionDefinition 3e758271a694f9dc 13 7 +IncludeUseCaseUsage actorParameter c82d6e266d54dcf3 13 7 +IncludeUseCaseUsage aliasIds 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage behavior 3e758271a694f9dc 13 7 +IncludeUseCaseUsage calculationDefinition 1f8e79bd9d262ece 13 7 +IncludeUseCaseUsage caseDefinition 1f8e79bd9d262ece 13 7 +IncludeUseCaseUsage chainingFeature 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage crossFeature 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage declaredName 928c369701eb33b6 13 6 +IncludeUseCaseUsage declaredShortName 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage definition 3e758271a694f9dc 13 7 +IncludeUseCaseUsage differencingType 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage directedFeature 7d2a60c7b22dcd59 13 7 +IncludeUseCaseUsage directedUsage 7d2a60c7b22dcd59 13 7 +IncludeUseCaseUsage direction 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage documentation 47de40d3f0b85781 13 1 +IncludeUseCaseUsage elementId a440721a0e019830 13 13 +IncludeUseCaseUsage endFeature 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage endOwningType 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage eventOccurrence f923e57c5eb4118d 13 7 +IncludeUseCaseUsage feature 7e10746bc13e6a9b 13 7 +IncludeUseCaseUsage featureMembership 2a43b04f29aea7cb 13 7 +IncludeUseCaseUsage featureTarget 53daf70a8f6476c9 13 0 +IncludeUseCaseUsage featuringType 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage function 1f8e79bd9d262ece 13 7 +IncludeUseCaseUsage importedMembership 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage includedUseCase 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage individualDefinition 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage inheritedFeature 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage inheritedMembership 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage input 7d2a60c7b22dcd59 13 7 +IncludeUseCaseUsage intersectingType 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage isAbstract 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isComposite 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isConjugated 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isConstant 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isDerived 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isEnd 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isImpliedIncluded 8abd2a443fde5cd8 13 13 +IncludeUseCaseUsage isIndividual 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage isLibraryElement 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isModelLevelEvaluable 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isOrdered 7fb527c91ec55027 13 0 +IncludeUseCaseUsage isPortion 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage isReference 8abd2a443fde5cd8 13 13 +IncludeUseCaseUsage isSufficient 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage isUnique 8abd2a443fde5cd8 13 13 +IncludeUseCaseUsage isVariable 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage isVariation 7fb527c91ec55027 13 0 +IncludeUseCaseUsage mayTimeVary 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage member 197e9e6b454cf2b3 13 9 +IncludeUseCaseUsage membership a7fd15aeae31f7cc 13 9 +IncludeUseCaseUsage multiplicity f581ea49959aa764 13 4 +IncludeUseCaseUsage name a7beda9558fbd3c5 13 13 +IncludeUseCaseUsage nestedAction 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedAllocation 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedAnalysisCase 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedAttribute 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedCalculation 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedCase 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedConcern 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedConnection 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedConstraint 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedEnumeration 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedFlow 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedInterface 17533a8a35ddd2f2 13 7 +IncludeUseCaseUsage nestedItem c82d6e266d54dcf3 13 7 +IncludeUseCaseUsage nestedMetadata 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedOccurrence c82d6e266d54dcf3 13 7 +IncludeUseCaseUsage nestedPart c82d6e266d54dcf3 13 7 +IncludeUseCaseUsage nestedPort 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedReference 17533a8a35ddd2f2 13 7 +IncludeUseCaseUsage nestedRendering 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedRequirement 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedState 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedTransition 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedUsage 7e10746bc13e6a9b 13 7 +IncludeUseCaseUsage nestedUseCase 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedVerificationCase 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedView 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage nestedViewpoint 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage objectiveRequirement 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage occurrenceDefinition 3e758271a694f9dc 13 7 +IncludeUseCaseUsage output 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedAnnotation 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedConjugator 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage ownedCrossSubsetting 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage ownedDifferencing 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedDisjoining 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedElement 6802b866db7ad29d 13 10 +IncludeUseCaseUsage ownedEndFeature 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedFeature 7e10746bc13e6a9b 13 7 +IncludeUseCaseUsage ownedFeatureChaining 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedFeatureInverting 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedFeatureMembership 2a43b04f29aea7cb 13 7 +IncludeUseCaseUsage ownedImport 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedIntersecting 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedMember 197e9e6b454cf2b3 13 9 +IncludeUseCaseUsage ownedMembership a7fd15aeae31f7cc 13 9 +IncludeUseCaseUsage ownedRedefinition 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedReferenceSubsetting 9239c0f2ce297089 13 7 +IncludeUseCaseUsage ownedRelationship 12a95946cbd5b9f2 13 13 +IncludeUseCaseUsage ownedSpecialization be267379ed2f5c78 13 13 +IncludeUseCaseUsage ownedSubsetting 775dfcc6e81f7e3e 13 13 +IncludeUseCaseUsage ownedTypeFeaturing 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage ownedTyping c2d61a80d5c1b198 13 3 +IncludeUseCaseUsage ownedUnioning 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage owner 2e558a38b08e38f7 13 13 +IncludeUseCaseUsage owningDefinition e0e9d6f7ed70e25d 13 4 +IncludeUseCaseUsage owningFeatureMembership 6d0c7b2ab26cae25 13 13 +IncludeUseCaseUsage owningMembership 6d0c7b2ab26cae25 13 13 +IncludeUseCaseUsage owningNamespace 2e558a38b08e38f7 13 13 +IncludeUseCaseUsage owningRelationship 6d0c7b2ab26cae25 13 13 +IncludeUseCaseUsage owningType 2e558a38b08e38f7 13 13 +IncludeUseCaseUsage owningUsage 7c47bf376b70aecb 13 9 +IncludeUseCaseUsage parameter 7d2a60c7b22dcd59 13 7 +IncludeUseCaseUsage performedAction f923e57c5eb4118d 13 7 +IncludeUseCaseUsage portionKind 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage qualifiedName e41447295eb719f6 13 13 +IncludeUseCaseUsage result 53daf70a8f6476c9 13 0 +IncludeUseCaseUsage shortName 2edc0bf6a8535831 13 0 +IncludeUseCaseUsage subjectParameter 7dd516e4167e0470 13 7 +IncludeUseCaseUsage textualRepresentation 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage type 3e758271a694f9dc 13 7 +IncludeUseCaseUsage unioningType 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage usage 7e10746bc13e6a9b 13 7 +IncludeUseCaseUsage useCaseDefinition 1f8e79bd9d262ece 13 7 +IncludeUseCaseUsage useCaseIncluded f923e57c5eb4118d 13 7 +IncludeUseCaseUsage variant 8309d3eb1e1bc03c 13 0 +IncludeUseCaseUsage variantMembership 8309d3eb1e1bc03c 13 0 +IndexExpression aliasIds 8d84f1a5bb420eea 35 0 +IndexExpression argument 785c5dab7f958abd 35 35 +IndexExpression behavior 8d84f1a5bb420eea 35 0 +IndexExpression chainingFeature 8d84f1a5bb420eea 35 0 +IndexExpression crossFeature f6423f3a7dd34afd 35 0 +IndexExpression declaredName f6423f3a7dd34afd 35 0 +IndexExpression declaredShortName f6423f3a7dd34afd 35 0 +IndexExpression differencingType 8d84f1a5bb420eea 35 0 +IndexExpression directedFeature f00738a8b1e51522 35 35 +IndexExpression direction f6423f3a7dd34afd 35 0 +IndexExpression documentation 8d84f1a5bb420eea 35 0 +IndexExpression elementId c5c72978d865a524 35 35 +IndexExpression endFeature 8d84f1a5bb420eea 35 0 +IndexExpression endOwningType f6423f3a7dd34afd 35 0 +IndexExpression feature f00738a8b1e51522 35 35 +IndexExpression featureMembership affa8a4e0578eb49 35 35 +IndexExpression featureTarget f08b3dc194489eff 35 0 +IndexExpression featuringType 8d84f1a5bb420eea 35 0 +IndexExpression function f6423f3a7dd34afd 35 0 +IndexExpression importedMembership 8d84f1a5bb420eea 35 0 +IndexExpression inheritedFeature 8d84f1a5bb420eea 35 0 +IndexExpression inheritedMembership 8d84f1a5bb420eea 35 0 +IndexExpression input f00738a8b1e51522 35 35 +IndexExpression instantiatedType 29910b2407a08669 35 35 +IndexExpression intersectingType 8d84f1a5bb420eea 35 0 +IndexExpression isAbstract f6423f3a7dd34afd 35 0 +IndexExpression isComposite f6423f3a7dd34afd 35 0 +IndexExpression isConjugated 76eeaea60a48e147 35 0 +IndexExpression isConstant f6423f3a7dd34afd 35 0 +IndexExpression isDerived f6423f3a7dd34afd 35 0 +IndexExpression isEnd f6423f3a7dd34afd 35 0 +IndexExpression isImpliedIncluded 6d4d08bca8d51816 35 35 +IndexExpression isLibraryElement 76eeaea60a48e147 35 0 +IndexExpression isModelLevelEvaluable 76eeaea60a48e147 35 0 +IndexExpression isOrdered f6423f3a7dd34afd 35 0 +IndexExpression isPortion f6423f3a7dd34afd 35 0 +IndexExpression isSufficient f6423f3a7dd34afd 35 0 +IndexExpression isUnique f6423f3a7dd34afd 35 0 +IndexExpression isVariable f6423f3a7dd34afd 35 0 +IndexExpression member f00738a8b1e51522 35 35 +IndexExpression membership affa8a4e0578eb49 35 35 +IndexExpression multiplicity f6423f3a7dd34afd 35 0 +IndexExpression name f6423f3a7dd34afd 35 0 +IndexExpression operator 2d8df397c9d7df27 35 35 +IndexExpression output 8d84f1a5bb420eea 35 0 +IndexExpression ownedAnnotation 8d84f1a5bb420eea 35 0 +IndexExpression ownedConjugator f6423f3a7dd34afd 35 0 +IndexExpression ownedCrossSubsetting f6423f3a7dd34afd 35 0 +IndexExpression ownedDifferencing 8d84f1a5bb420eea 35 0 +IndexExpression ownedDisjoining 8d84f1a5bb420eea 35 0 +IndexExpression ownedElement f00738a8b1e51522 35 35 +IndexExpression ownedEndFeature 8d84f1a5bb420eea 35 0 +IndexExpression ownedFeature f00738a8b1e51522 35 35 +IndexExpression ownedFeatureChaining 8d84f1a5bb420eea 35 0 +IndexExpression ownedFeatureInverting 8d84f1a5bb420eea 35 0 +IndexExpression ownedFeatureMembership affa8a4e0578eb49 35 35 +IndexExpression ownedImport 8d84f1a5bb420eea 35 0 +IndexExpression ownedIntersecting 8d84f1a5bb420eea 35 0 +IndexExpression ownedMember f00738a8b1e51522 35 35 +IndexExpression ownedMembership affa8a4e0578eb49 35 35 +IndexExpression ownedRedefinition 8d84f1a5bb420eea 35 0 +IndexExpression ownedReferenceSubsetting f6423f3a7dd34afd 35 0 +IndexExpression ownedRelationship affa8a4e0578eb49 35 35 +IndexExpression ownedSpecialization 8d84f1a5bb420eea 35 0 +IndexExpression ownedSubsetting 8d84f1a5bb420eea 35 0 +IndexExpression ownedTypeFeaturing 8d84f1a5bb420eea 35 0 +IndexExpression ownedTyping 8d84f1a5bb420eea 35 0 +IndexExpression ownedUnioning 8d84f1a5bb420eea 35 0 +IndexExpression owner 9b15fc307e9fadc4 35 35 +IndexExpression owningFeatureMembership f6423f3a7dd34afd 35 0 +IndexExpression owningMembership 175c29e534398440 35 35 +IndexExpression owningNamespace 9b15fc307e9fadc4 35 35 +IndexExpression owningRelationship 175c29e534398440 35 35 +IndexExpression owningType f6423f3a7dd34afd 35 0 +IndexExpression parameter f00738a8b1e51522 35 35 +IndexExpression qualifiedName f6423f3a7dd34afd 35 0 +IndexExpression result f08b3dc194489eff 35 0 +IndexExpression shortName f6423f3a7dd34afd 35 0 +IndexExpression textualRepresentation 8d84f1a5bb420eea 35 0 +IndexExpression type 8d84f1a5bb420eea 35 0 +IndexExpression unioningType 8d84f1a5bb420eea 35 0 +InterfaceDefinition aliasIds cdd316f60d465388 17 0 +InterfaceDefinition associationEnd fe274ce111df54dd 17 17 +InterfaceDefinition connectionEnd fe274ce111df54dd 17 17 +InterfaceDefinition declaredName b7697addbaaed61a 17 17 +InterfaceDefinition declaredShortName 0fc8f25e5dc93029 17 0 +InterfaceDefinition differencingType cdd316f60d465388 17 0 +InterfaceDefinition directedFeature cdd316f60d465388 17 0 +InterfaceDefinition directedUsage cdd316f60d465388 17 0 +InterfaceDefinition documentation 8e5f8cc9af28642f 17 1 +InterfaceDefinition elementId e37741fdd29d4550 17 17 +InterfaceDefinition endFeature fe274ce111df54dd 17 17 +InterfaceDefinition feature 9107a47da6fe9c9e 17 17 +InterfaceDefinition featureMembership 157e8e4cb1155bfb 17 17 +InterfaceDefinition importedMembership cdd316f60d465388 17 0 +InterfaceDefinition inheritedFeature cdd316f60d465388 17 0 +InterfaceDefinition inheritedMembership cdd316f60d465388 17 0 +InterfaceDefinition input cdd316f60d465388 17 0 +InterfaceDefinition interfaceEnd fe274ce111df54dd 17 17 +InterfaceDefinition intersectingType cdd316f60d465388 17 0 +InterfaceDefinition isAbstract b93f9d6bd757a4f7 17 0 +InterfaceDefinition isConjugated b93f9d6bd757a4f7 17 0 +InterfaceDefinition isImplied 0fc8f25e5dc93029 17 0 +InterfaceDefinition isImpliedIncluded 07e3af908712af7c 17 17 +InterfaceDefinition isIndividual 0fc8f25e5dc93029 17 0 +InterfaceDefinition isLibraryElement b93f9d6bd757a4f7 17 0 +InterfaceDefinition isSufficient 07e3af908712af7c 17 17 +InterfaceDefinition isVariation b93f9d6bd757a4f7 17 0 +InterfaceDefinition member b0e3e34922aa7509 17 17 +InterfaceDefinition membership eca658f0ac3ef51b 17 17 +InterfaceDefinition multiplicity 0fc8f25e5dc93029 17 0 +InterfaceDefinition name b7697addbaaed61a 17 17 +InterfaceDefinition output cdd316f60d465388 17 0 +InterfaceDefinition ownedAction 6464e2abe56e1877 17 4 +InterfaceDefinition ownedAllocation cdd316f60d465388 17 0 +InterfaceDefinition ownedAnalysisCase cdd316f60d465388 17 0 +InterfaceDefinition ownedAnnotation cdd316f60d465388 17 0 +InterfaceDefinition ownedAttribute 6b6269c87f8af9a3 17 1 +InterfaceDefinition ownedCalculation cdd316f60d465388 17 0 +InterfaceDefinition ownedCase cdd316f60d465388 17 0 +InterfaceDefinition ownedConcern cdd316f60d465388 17 0 +InterfaceDefinition ownedConjugator 0fc8f25e5dc93029 17 0 +InterfaceDefinition ownedConnection eac09c9f8edde3ae 17 7 +InterfaceDefinition ownedConstraint e81bbe16e79ce064 17 1 +InterfaceDefinition ownedDifferencing cdd316f60d465388 17 0 +InterfaceDefinition ownedDisjoining cdd316f60d465388 17 0 +InterfaceDefinition ownedElement b0e3e34922aa7509 17 17 +InterfaceDefinition ownedEndFeature fe274ce111df54dd 17 17 +InterfaceDefinition ownedEnumeration cdd316f60d465388 17 0 +InterfaceDefinition ownedFeature 9107a47da6fe9c9e 17 17 +InterfaceDefinition ownedFeatureMembership 157e8e4cb1155bfb 17 17 +InterfaceDefinition ownedFlow cdd316f60d465388 17 0 +InterfaceDefinition ownedImport cdd316f60d465388 17 0 +InterfaceDefinition ownedInterface d4d6b4d9eef20514 17 1 +InterfaceDefinition ownedIntersecting cdd316f60d465388 17 0 +InterfaceDefinition ownedItem 542ed0e9b6b61ebf 17 3 +InterfaceDefinition ownedMember b0e3e34922aa7509 17 17 +InterfaceDefinition ownedMembership eca658f0ac3ef51b 17 17 +InterfaceDefinition ownedMetadata cdd316f60d465388 17 0 +InterfaceDefinition ownedOccurrence 3b3ad6f9816c6e9b 17 17 +InterfaceDefinition ownedPart 542ed0e9b6b61ebf 17 3 +InterfaceDefinition ownedPort fe274ce111df54dd 17 17 +InterfaceDefinition ownedReference d4d6b4d9eef20514 17 1 +InterfaceDefinition ownedRelatedElement cdd316f60d465388 17 0 +InterfaceDefinition ownedRelationship bec165e008bfd124 17 17 +InterfaceDefinition ownedRendering cdd316f60d465388 17 0 +InterfaceDefinition ownedRequirement cdd316f60d465388 17 0 +InterfaceDefinition ownedSpecialization 195d2872265ee10f 17 17 +InterfaceDefinition ownedState cdd316f60d465388 17 0 +InterfaceDefinition ownedSubclassification 195d2872265ee10f 17 17 +InterfaceDefinition ownedTransition cdd316f60d465388 17 0 +InterfaceDefinition ownedUnioning cdd316f60d465388 17 0 +InterfaceDefinition ownedUsage 9107a47da6fe9c9e 17 17 +InterfaceDefinition ownedUseCase cdd316f60d465388 17 0 +InterfaceDefinition ownedVerificationCase cdd316f60d465388 17 0 +InterfaceDefinition ownedView cdd316f60d465388 17 0 +InterfaceDefinition ownedViewpoint cdd316f60d465388 17 0 +InterfaceDefinition owner 04d2af9970d5c570 17 17 +InterfaceDefinition owningMembership 1129c3d72e847df8 17 17 +InterfaceDefinition owningNamespace 04d2af9970d5c570 17 17 +InterfaceDefinition owningRelatedElement 0fc8f25e5dc93029 17 0 +InterfaceDefinition owningRelationship 1129c3d72e847df8 17 17 +InterfaceDefinition qualifiedName ff178fadb2404dec 17 17 +InterfaceDefinition relatedElement cdd316f60d465388 17 0 +InterfaceDefinition relatedType 1d021f3c0ea35100 17 17 +InterfaceDefinition shortName 0fc8f25e5dc93029 17 0 +InterfaceDefinition source cdd316f60d465388 17 0 +InterfaceDefinition sourceType e39a52e1cbb6421d 17 17 +InterfaceDefinition target cdd316f60d465388 17 0 +InterfaceDefinition targetType 088a1f2a62fa0b7f 17 17 +InterfaceDefinition textualRepresentation cdd316f60d465388 17 0 +InterfaceDefinition unioningType cdd316f60d465388 17 0 +InterfaceDefinition usage 9107a47da6fe9c9e 17 17 +InterfaceDefinition variant cdd316f60d465388 17 0 +InterfaceDefinition variantMembership cdd316f60d465388 17 0 +InterfaceUsage aliasIds be44f1f924740e21 37 0 +InterfaceUsage association 6cf65744fc9a1dd2 37 28 +InterfaceUsage chainingFeature be44f1f924740e21 37 0 +InterfaceUsage connectionDefinition 6cf65744fc9a1dd2 37 28 +InterfaceUsage connectorEnd e258a3d69e834776 37 37 +InterfaceUsage crossFeature 3b5455fa8be77898 37 0 +InterfaceUsage declaredName 6ad2558b8344896e 37 27 +InterfaceUsage declaredShortName 3b5455fa8be77898 37 0 +InterfaceUsage defaultFeaturingType e49ab3d55b3abc62 37 26 +InterfaceUsage definition 6cf65744fc9a1dd2 37 28 +InterfaceUsage differencingType be44f1f924740e21 37 0 +InterfaceUsage directedFeature be44f1f924740e21 37 0 +InterfaceUsage directedUsage be44f1f924740e21 37 0 +InterfaceUsage direction 3b5455fa8be77898 37 0 +InterfaceUsage documentation be44f1f924740e21 37 0 +InterfaceUsage elementId 9cbe5c8a2f6b177c 37 37 +InterfaceUsage endFeature e258a3d69e834776 37 37 +InterfaceUsage endOwningType 3b5455fa8be77898 37 0 +InterfaceUsage feature 243909b86f859720 37 37 +InterfaceUsage featureMembership d250b7b74faa7e4d 37 37 +InterfaceUsage featureTarget 49fbe7de47ac48db 37 0 +InterfaceUsage featuringType be44f1f924740e21 37 0 +InterfaceUsage importedMembership be44f1f924740e21 37 0 +InterfaceUsage individualDefinition 3b5455fa8be77898 37 0 +InterfaceUsage inheritedFeature be44f1f924740e21 37 0 +InterfaceUsage inheritedMembership be44f1f924740e21 37 0 +InterfaceUsage input be44f1f924740e21 37 0 +InterfaceUsage interfaceDefinition 6cf65744fc9a1dd2 37 28 +InterfaceUsage intersectingType be44f1f924740e21 37 0 +InterfaceUsage isAbstract be36ba913f9e1718 37 0 +InterfaceUsage isComposite 41abea483310538f 37 27 +InterfaceUsage isConjugated be36ba913f9e1718 37 0 +InterfaceUsage isConstant be36ba913f9e1718 37 0 +InterfaceUsage isDerived be36ba913f9e1718 37 0 +InterfaceUsage isEnd be36ba913f9e1718 37 0 +InterfaceUsage isImplied 3b5455fa8be77898 37 0 +InterfaceUsage isImpliedIncluded 6a94c47cb64977b9 37 37 +InterfaceUsage isIndividual 3b5455fa8be77898 37 0 +InterfaceUsage isLibraryElement be36ba913f9e1718 37 0 +InterfaceUsage isOrdered be36ba913f9e1718 37 0 +InterfaceUsage isPortion 3b5455fa8be77898 37 0 +InterfaceUsage isReference e71f94c5c2d73b42 37 10 +InterfaceUsage isSufficient 3b5455fa8be77898 37 0 +InterfaceUsage isUnique 6a94c47cb64977b9 37 37 +InterfaceUsage isVariable 3b5455fa8be77898 37 0 +InterfaceUsage isVariation be36ba913f9e1718 37 0 +InterfaceUsage itemDefinition 6cf65744fc9a1dd2 37 28 +InterfaceUsage mayTimeVary 3b5455fa8be77898 37 0 +InterfaceUsage member 00301aa49aeedc08 37 37 +InterfaceUsage membership d6b48f4d440be473 37 37 +InterfaceUsage multiplicity 97a6dec603fdfda0 37 1 +InterfaceUsage name 6ad2558b8344896e 37 27 +InterfaceUsage nestedAction 57c3e14b52c381c8 37 8 +InterfaceUsage nestedAllocation be44f1f924740e21 37 0 +InterfaceUsage nestedAnalysisCase be44f1f924740e21 37 0 +InterfaceUsage nestedAttribute 20af68e84d145844 37 3 +InterfaceUsage nestedCalculation be44f1f924740e21 37 0 +InterfaceUsage nestedCase be44f1f924740e21 37 0 +InterfaceUsage nestedConcern be44f1f924740e21 37 0 +InterfaceUsage nestedConnection b54445d8c5458681 37 9 +InterfaceUsage nestedConstraint be44f1f924740e21 37 0 +InterfaceUsage nestedEnumeration be44f1f924740e21 37 0 +InterfaceUsage nestedFlow be44f1f924740e21 37 0 +InterfaceUsage nestedInterface b83fff065e20a550 37 1 +InterfaceUsage nestedItem 28df52912bcc4422 37 2 +InterfaceUsage nestedMetadata be44f1f924740e21 37 0 +InterfaceUsage nestedOccurrence 2446ff678cde6686 37 37 +InterfaceUsage nestedPart 28df52912bcc4422 37 2 +InterfaceUsage nestedPort e258a3d69e834776 37 37 +InterfaceUsage nestedReference b83fff065e20a550 37 1 +InterfaceUsage nestedRendering be44f1f924740e21 37 0 +InterfaceUsage nestedRequirement be44f1f924740e21 37 0 +InterfaceUsage nestedState be44f1f924740e21 37 0 +InterfaceUsage nestedTransition be44f1f924740e21 37 0 +InterfaceUsage nestedUsage 243909b86f859720 37 37 +InterfaceUsage nestedUseCase be44f1f924740e21 37 0 +InterfaceUsage nestedVerificationCase be44f1f924740e21 37 0 +InterfaceUsage nestedView be44f1f924740e21 37 0 +InterfaceUsage nestedViewpoint be44f1f924740e21 37 0 +InterfaceUsage occurrenceDefinition 6cf65744fc9a1dd2 37 28 +InterfaceUsage output be44f1f924740e21 37 0 +InterfaceUsage ownedAnnotation be44f1f924740e21 37 0 +InterfaceUsage ownedConjugator 3b5455fa8be77898 37 0 +InterfaceUsage ownedCrossSubsetting 3b5455fa8be77898 37 0 +InterfaceUsage ownedDifferencing be44f1f924740e21 37 0 +InterfaceUsage ownedDisjoining be44f1f924740e21 37 0 +InterfaceUsage ownedElement 00301aa49aeedc08 37 37 +InterfaceUsage ownedEndFeature e258a3d69e834776 37 37 +InterfaceUsage ownedFeature 243909b86f859720 37 37 +InterfaceUsage ownedFeatureChaining be44f1f924740e21 37 0 +InterfaceUsage ownedFeatureInverting be44f1f924740e21 37 0 +InterfaceUsage ownedFeatureMembership d250b7b74faa7e4d 37 37 +InterfaceUsage ownedImport be44f1f924740e21 37 0 +InterfaceUsage ownedIntersecting be44f1f924740e21 37 0 +InterfaceUsage ownedMember 00301aa49aeedc08 37 37 +InterfaceUsage ownedMembership d6b48f4d440be473 37 37 +InterfaceUsage ownedRedefinition be44f1f924740e21 37 0 +InterfaceUsage ownedReferenceSubsetting 3b5455fa8be77898 37 0 +InterfaceUsage ownedRelatedElement be44f1f924740e21 37 0 +InterfaceUsage ownedRelationship a3a8d11c7b20150c 37 37 +InterfaceUsage ownedSpecialization 11bf8f4de52ad67a 37 37 +InterfaceUsage ownedSubsetting a4c633c56c9805e0 37 37 +InterfaceUsage ownedTypeFeaturing be44f1f924740e21 37 0 +InterfaceUsage ownedTyping c97c3499e97bb3bd 37 24 +InterfaceUsage ownedUnioning be44f1f924740e21 37 0 +InterfaceUsage owner 378b21224dfbd310 37 37 +InterfaceUsage owningDefinition 52d3645c9a7cfe85 37 2 +InterfaceUsage owningFeatureMembership a8dab75300e199e8 37 27 +InterfaceUsage owningMembership fb8d3e83c68501c8 37 37 +InterfaceUsage owningNamespace 378b21224dfbd310 37 37 +InterfaceUsage owningRelatedElement 3b5455fa8be77898 37 0 +InterfaceUsage owningRelationship fb8d3e83c68501c8 37 37 +InterfaceUsage owningType 4b8a4083de0e31ca 37 27 +InterfaceUsage owningUsage 340b3221cf78abdd 37 25 +InterfaceUsage partDefinition 6cf65744fc9a1dd2 37 28 +InterfaceUsage portionKind 3b5455fa8be77898 37 0 +InterfaceUsage qualifiedName 050bcfedd8d88886 37 27 +InterfaceUsage relatedElement be44f1f924740e21 37 0 +InterfaceUsage relatedFeature 4e2596684b4146dd 37 37 +InterfaceUsage shortName 3b5455fa8be77898 37 0 +InterfaceUsage source be44f1f924740e21 37 0 +InterfaceUsage sourceFeature 499e96ad0266e043 37 37 +InterfaceUsage target be44f1f924740e21 37 0 +InterfaceUsage targetFeature ed197c85ff3f9fbf 37 37 +InterfaceUsage textualRepresentation be44f1f924740e21 37 0 +InterfaceUsage type 6cf65744fc9a1dd2 37 28 +InterfaceUsage unioningType be44f1f924740e21 37 0 +InterfaceUsage usage 243909b86f859720 37 37 +InterfaceUsage variant be44f1f924740e21 37 0 +InterfaceUsage variantMembership be44f1f924740e21 37 0 +InvocationExpression aliasIds d09c16696a9ac033 91 0 +InvocationExpression argument 63e8ba94646eec84 91 91 +InvocationExpression behavior d09c16696a9ac033 91 0 +InvocationExpression chainingFeature d09c16696a9ac033 91 0 +InvocationExpression crossFeature 34c14dcbd1fd3948 91 0 +InvocationExpression declaredName 34c14dcbd1fd3948 91 0 +InvocationExpression declaredShortName 34c14dcbd1fd3948 91 0 +InvocationExpression differencingType d09c16696a9ac033 91 0 +InvocationExpression directedFeature 9816015eb00a7763 91 91 +InvocationExpression direction 34c14dcbd1fd3948 91 0 +InvocationExpression documentation d09c16696a9ac033 91 0 +InvocationExpression elementId e6b2aff3e8b5d698 91 91 +InvocationExpression endFeature d09c16696a9ac033 91 0 +InvocationExpression endOwningType 34c14dcbd1fd3948 91 0 +InvocationExpression feature 9816015eb00a7763 91 91 +InvocationExpression featureMembership 46257b1a815afc16 91 91 +InvocationExpression featureTarget b0710ce49710cd01 91 0 +InvocationExpression featuringType d09c16696a9ac033 91 0 +InvocationExpression function 34c14dcbd1fd3948 91 0 +InvocationExpression importedMembership d09c16696a9ac033 91 0 +InvocationExpression inheritedFeature d09c16696a9ac033 91 0 +InvocationExpression inheritedMembership d09c16696a9ac033 91 0 +InvocationExpression input 9816015eb00a7763 91 91 +InvocationExpression instantiatedType c0b11b2c2dc6116e 91 91 +InvocationExpression intersectingType d09c16696a9ac033 91 0 +InvocationExpression isAbstract 34c14dcbd1fd3948 91 0 +InvocationExpression isComposite 34c14dcbd1fd3948 91 0 +InvocationExpression isConjugated d5beed57138bbcac 91 0 +InvocationExpression isConstant 34c14dcbd1fd3948 91 0 +InvocationExpression isDerived 34c14dcbd1fd3948 91 0 +InvocationExpression isEnd 34c14dcbd1fd3948 91 0 +InvocationExpression isImpliedIncluded 92f3314f864a3953 91 91 +InvocationExpression isLibraryElement d5beed57138bbcac 91 0 +InvocationExpression isModelLevelEvaluable d5beed57138bbcac 91 0 +InvocationExpression isOrdered 34c14dcbd1fd3948 91 0 +InvocationExpression isPortion 34c14dcbd1fd3948 91 0 +InvocationExpression isSufficient 34c14dcbd1fd3948 91 0 +InvocationExpression isUnique 34c14dcbd1fd3948 91 0 +InvocationExpression isVariable 34c14dcbd1fd3948 91 0 +InvocationExpression member 0aa8570be68c2e74 91 91 +InvocationExpression membership 935f4b6c643b35ca 91 91 +InvocationExpression multiplicity 34c14dcbd1fd3948 91 0 +InvocationExpression name 34c14dcbd1fd3948 91 0 +InvocationExpression output d09c16696a9ac033 91 0 +InvocationExpression ownedAnnotation d09c16696a9ac033 91 0 +InvocationExpression ownedConjugator 34c14dcbd1fd3948 91 0 +InvocationExpression ownedCrossSubsetting 34c14dcbd1fd3948 91 0 +InvocationExpression ownedDifferencing d09c16696a9ac033 91 0 +InvocationExpression ownedDisjoining d09c16696a9ac033 91 0 +InvocationExpression ownedElement bec99a9adc1b4656 91 91 +InvocationExpression ownedEndFeature d09c16696a9ac033 91 0 +InvocationExpression ownedFeature 9816015eb00a7763 91 91 +InvocationExpression ownedFeatureChaining d09c16696a9ac033 91 0 +InvocationExpression ownedFeatureInverting d09c16696a9ac033 91 0 +InvocationExpression ownedFeatureMembership 46257b1a815afc16 91 91 +InvocationExpression ownedImport d09c16696a9ac033 91 0 +InvocationExpression ownedIntersecting d09c16696a9ac033 91 0 +InvocationExpression ownedMember bec99a9adc1b4656 91 91 +InvocationExpression ownedMembership 935f4b6c643b35ca 91 91 +InvocationExpression ownedRedefinition d09c16696a9ac033 91 0 +InvocationExpression ownedReferenceSubsetting 34c14dcbd1fd3948 91 0 +InvocationExpression ownedRelationship 935f4b6c643b35ca 91 91 +InvocationExpression ownedSpecialization d09c16696a9ac033 91 0 +InvocationExpression ownedSubsetting d09c16696a9ac033 91 0 +InvocationExpression ownedTypeFeaturing d09c16696a9ac033 91 0 +InvocationExpression ownedTyping d09c16696a9ac033 91 0 +InvocationExpression ownedUnioning d09c16696a9ac033 91 0 +InvocationExpression owner d753732daf9f9d1f 91 91 +InvocationExpression owningFeatureMembership 012d0d38a8f8ca33 91 9 +InvocationExpression owningMembership d1363065601c2661 91 91 +InvocationExpression owningNamespace d753732daf9f9d1f 91 91 +InvocationExpression owningRelationship d1363065601c2661 91 91 +InvocationExpression owningType 17bc808cdef06a5c 91 9 +InvocationExpression parameter 9816015eb00a7763 91 91 +InvocationExpression qualifiedName 34c14dcbd1fd3948 91 0 +InvocationExpression result b0710ce49710cd01 91 0 +InvocationExpression shortName 34c14dcbd1fd3948 91 0 +InvocationExpression textualRepresentation d09c16696a9ac033 91 0 +InvocationExpression type d09c16696a9ac033 91 0 +InvocationExpression unioningType d09c16696a9ac033 91 0 +ItemDefinition aliasIds 1a63a02d78eb1205 84 0 +ItemDefinition declaredName 179fc506d83d1fdc 84 84 +ItemDefinition declaredShortName 6d8b667c5041e203 84 0 +ItemDefinition differencingType 1a63a02d78eb1205 84 0 +ItemDefinition directedFeature 1a63a02d78eb1205 84 0 +ItemDefinition directedUsage 1a63a02d78eb1205 84 0 +ItemDefinition documentation cc7825d54baf4a10 84 4 +ItemDefinition elementId 8bf373c5ac8d31cc 84 84 +ItemDefinition endFeature 1a63a02d78eb1205 84 0 +ItemDefinition feature f1e71cf28cb9b00d 84 31 +ItemDefinition featureMembership 8661fe1ac80c73c7 84 31 +ItemDefinition importedMembership 1a63a02d78eb1205 84 0 +ItemDefinition inheritedFeature 1a63a02d78eb1205 84 0 +ItemDefinition inheritedMembership 1a63a02d78eb1205 84 0 +ItemDefinition input 1a63a02d78eb1205 84 0 +ItemDefinition intersectingType 1a63a02d78eb1205 84 0 +ItemDefinition isAbstract 620b68edc0d3b402 84 1 +ItemDefinition isConjugated dcb5c65d4252c06d 84 0 +ItemDefinition isImpliedIncluded a4c72d5d1d11fa79 84 84 +ItemDefinition isIndividual 469d72fec831effb 84 6 +ItemDefinition isLibraryElement f7373fe65668a2df 84 2 +ItemDefinition isSufficient dcb5c65d4252c06d 84 0 +ItemDefinition isVariation dcb5c65d4252c06d 84 0 +ItemDefinition member 61785f08d7e461a6 84 32 +ItemDefinition membership 049ff4a89e66bb05 84 32 +ItemDefinition multiplicity 6d8b667c5041e203 84 0 +ItemDefinition name 179fc506d83d1fdc 84 84 +ItemDefinition output 1a63a02d78eb1205 84 0 +ItemDefinition ownedAction 1a63a02d78eb1205 84 0 +ItemDefinition ownedAllocation 1a63a02d78eb1205 84 0 +ItemDefinition ownedAnalysisCase 1a63a02d78eb1205 84 0 +ItemDefinition ownedAnnotation 1a63a02d78eb1205 84 0 +ItemDefinition ownedAttribute 1e2594cda6f0e079 84 15 +ItemDefinition ownedCalculation 1a63a02d78eb1205 84 0 +ItemDefinition ownedCase 1a63a02d78eb1205 84 0 +ItemDefinition ownedConcern 1a63a02d78eb1205 84 0 +ItemDefinition ownedConjugator 6d8b667c5041e203 84 0 +ItemDefinition ownedConnection d85096bf2fab3f7f 84 3 +ItemDefinition ownedConstraint 86a356b9e8f1e661 84 1 +ItemDefinition ownedDifferencing 1a63a02d78eb1205 84 0 +ItemDefinition ownedDisjoining 1a63a02d78eb1205 84 0 +ItemDefinition ownedElement 61785f08d7e461a6 84 32 +ItemDefinition ownedEndFeature 1a63a02d78eb1205 84 0 +ItemDefinition ownedEnumeration 1a63a02d78eb1205 84 0 +ItemDefinition ownedFeature f1e71cf28cb9b00d 84 31 +ItemDefinition ownedFeatureMembership 8661fe1ac80c73c7 84 31 +ItemDefinition ownedFlow 1a63a02d78eb1205 84 0 +ItemDefinition ownedImport 1a63a02d78eb1205 84 0 +ItemDefinition ownedInterface c06d7633bad641a7 84 8 +ItemDefinition ownedIntersecting 1a63a02d78eb1205 84 0 +ItemDefinition ownedItem aa05bd6ca224473c 84 13 +ItemDefinition ownedMember 61785f08d7e461a6 84 32 +ItemDefinition ownedMembership 049ff4a89e66bb05 84 32 +ItemDefinition ownedMetadata 1a63a02d78eb1205 84 0 +ItemDefinition ownedOccurrence 747c2e4758cdaaa9 84 17 +ItemDefinition ownedPart 181598126e47a3d6 84 9 +ItemDefinition ownedPort 1a63a02d78eb1205 84 0 +ItemDefinition ownedReference c06d7633bad641a7 84 8 +ItemDefinition ownedRelationship c4bf27b5d48d064a 84 84 +ItemDefinition ownedRendering 1a63a02d78eb1205 84 0 +ItemDefinition ownedRequirement 1a63a02d78eb1205 84 0 +ItemDefinition ownedSpecialization cfb1b562b85ee292 84 84 +ItemDefinition ownedState 1a63a02d78eb1205 84 0 +ItemDefinition ownedSubclassification cfb1b562b85ee292 84 84 +ItemDefinition ownedTransition 1a63a02d78eb1205 84 0 +ItemDefinition ownedUnioning 1a63a02d78eb1205 84 0 +ItemDefinition ownedUsage f1e71cf28cb9b00d 84 31 +ItemDefinition ownedUseCase 1a63a02d78eb1205 84 0 +ItemDefinition ownedVerificationCase 1a63a02d78eb1205 84 0 +ItemDefinition ownedView 1a63a02d78eb1205 84 0 +ItemDefinition ownedViewpoint 1a63a02d78eb1205 84 0 +ItemDefinition owner 1c541373c7ebad18 84 84 +ItemDefinition owningMembership 9cd83210193efb89 84 84 +ItemDefinition owningNamespace 1c541373c7ebad18 84 84 +ItemDefinition owningRelationship 9cd83210193efb89 84 84 +ItemDefinition qualifiedName 830d0a582e7d39da 84 84 +ItemDefinition shortName 6d8b667c5041e203 84 0 +ItemDefinition textualRepresentation 1a63a02d78eb1205 84 0 +ItemDefinition unioningType 1a63a02d78eb1205 84 0 +ItemDefinition usage f1e71cf28cb9b00d 84 31 +ItemDefinition variant 1a63a02d78eb1205 84 0 +ItemDefinition variantMembership 1a63a02d78eb1205 84 0 +ItemUsage aliasIds c416504ade11b787 190 0 +ItemUsage chainingFeature c416504ade11b787 190 0 +ItemUsage crossFeature f527f61415a911eb 190 2 +ItemUsage declaredName 3dd045aa16560b6e 190 153 +ItemUsage declaredShortName 9e1d6a1b166fcab7 190 0 +ItemUsage definition 19253040d2445f61 190 146 +ItemUsage differencingType c416504ade11b787 190 0 +ItemUsage directedFeature c416504ade11b787 190 0 +ItemUsage directedUsage c416504ade11b787 190 0 +ItemUsage direction fa31b2718983b02e 190 104 +ItemUsage documentation b94523b63961f373 190 3 +ItemUsage elementId 3b08a1282c56b100 190 190 +ItemUsage endFeature c416504ade11b787 190 0 +ItemUsage endOwningType 15522e32e91172ef 190 19 +ItemUsage feature ed4d9cc3edc3737a 190 27 +ItemUsage featureMembership 3ce6bd06d453146a 190 27 +ItemUsage featureTarget 93e46e09dde67788 190 0 +ItemUsage featuringType c416504ade11b787 190 0 +ItemUsage importedMembership c416504ade11b787 190 0 +ItemUsage individualDefinition 5626fe3fa39c8e18 190 5 +ItemUsage inheritedFeature c416504ade11b787 190 0 +ItemUsage inheritedMembership c416504ade11b787 190 0 +ItemUsage input c416504ade11b787 190 0 +ItemUsage intersectingType c416504ade11b787 190 0 +ItemUsage isAbstract b7744af4a9615012 190 1 +ItemUsage isComposite 83c1ce1f10393f61 190 52 +ItemUsage isConjugated f011248f589614ad 190 0 +ItemUsage isConstant f6cd9320a3aaae0c 190 19 +ItemUsage isDerived f011248f589614ad 190 0 +ItemUsage isEnd f6cd9320a3aaae0c 190 19 +ItemUsage isImpliedIncluded d187f95f3fceb6d3 190 190 +ItemUsage isIndividual 4d4df075aabf88af 190 4 +ItemUsage isLibraryElement 9388d1f79c50f197 190 2 +ItemUsage isOrdered f011248f589614ad 190 0 +ItemUsage isPortion 9e1d6a1b166fcab7 190 0 +ItemUsage isReference 3dd74fcf882b8c1f 190 138 +ItemUsage isSufficient 9e1d6a1b166fcab7 190 0 +ItemUsage isUnique 2e104bf6fc13d9e9 190 188 +ItemUsage isVariable 7fbe2209ea5f5dcc 190 19 +ItemUsage isVariation f011248f589614ad 190 0 +ItemUsage itemDefinition 1d96a02a0e2b3204 190 143 +ItemUsage mayTimeVary 7fbe2209ea5f5dcc 190 19 +ItemUsage member 9a4db4ce0c44e102 190 82 +ItemUsage membership e45e190600fb6d48 190 82 +ItemUsage multiplicity 9fab231a5f836be1 190 39 +ItemUsage name 0ab0b3c341dea380 190 185 +ItemUsage nestedAction c416504ade11b787 190 0 +ItemUsage nestedAllocation c416504ade11b787 190 0 +ItemUsage nestedAnalysisCase c416504ade11b787 190 0 +ItemUsage nestedAttribute b098cbdeaff36d37 190 7 +ItemUsage nestedCalculation c416504ade11b787 190 0 +ItemUsage nestedCase c416504ade11b787 190 0 +ItemUsage nestedConcern c416504ade11b787 190 0 +ItemUsage nestedConnection c416504ade11b787 190 0 +ItemUsage nestedConstraint c416504ade11b787 190 0 +ItemUsage nestedEnumeration c416504ade11b787 190 0 +ItemUsage nestedFlow c416504ade11b787 190 0 +ItemUsage nestedInterface 41bb748f726a8b18 190 16 +ItemUsage nestedItem 23c7573babf4d30b 190 7 +ItemUsage nestedMetadata c416504ade11b787 190 0 +ItemUsage nestedOccurrence 23c7573babf4d30b 190 7 +ItemUsage nestedPart 8e09a8c7c52d5fb0 190 4 +ItemUsage nestedPort c416504ade11b787 190 0 +ItemUsage nestedReference 41bb748f726a8b18 190 16 +ItemUsage nestedRendering c416504ade11b787 190 0 +ItemUsage nestedRequirement c416504ade11b787 190 0 +ItemUsage nestedState c416504ade11b787 190 0 +ItemUsage nestedTransition c416504ade11b787 190 0 +ItemUsage nestedUsage ed4d9cc3edc3737a 190 27 +ItemUsage nestedUseCase c416504ade11b787 190 0 +ItemUsage nestedVerificationCase c416504ade11b787 190 0 +ItemUsage nestedView c416504ade11b787 190 0 +ItemUsage nestedViewpoint c416504ade11b787 190 0 +ItemUsage occurrenceDefinition 1c07486f49b99efe 190 146 +ItemUsage output c416504ade11b787 190 0 +ItemUsage ownedAnnotation c416504ade11b787 190 0 +ItemUsage ownedConjugator 9e1d6a1b166fcab7 190 0 +ItemUsage ownedCrossSubsetting 2541a8131d37b042 190 2 +ItemUsage ownedDifferencing c416504ade11b787 190 0 +ItemUsage ownedDisjoining c416504ade11b787 190 0 +ItemUsage ownedElement a8eb696dfc763736 190 82 +ItemUsage ownedEndFeature c416504ade11b787 190 0 +ItemUsage ownedFeature ed4d9cc3edc3737a 190 27 +ItemUsage ownedFeatureChaining c416504ade11b787 190 0 +ItemUsage ownedFeatureInverting c416504ade11b787 190 0 +ItemUsage ownedFeatureMembership 3ce6bd06d453146a 190 27 +ItemUsage ownedImport c416504ade11b787 190 0 +ItemUsage ownedIntersecting c416504ade11b787 190 0 +ItemUsage ownedMember 9a4db4ce0c44e102 190 82 +ItemUsage ownedMembership e45e190600fb6d48 190 82 +ItemUsage ownedRedefinition 5ea067a3d7f38a12 190 35 +ItemUsage ownedReferenceSubsetting 9e1d6a1b166fcab7 190 0 +ItemUsage ownedRelationship a5bac30c81105472 190 190 +ItemUsage ownedSpecialization 82ebc6414e95f54d 190 190 +ItemUsage ownedSubsetting 59ae077728f26b43 190 190 +ItemUsage ownedTypeFeaturing c416504ade11b787 190 0 +ItemUsage ownedTyping d0a7ad8834cfb597 190 126 +ItemUsage ownedUnioning c416504ade11b787 190 0 +ItemUsage owner 7b7f164cc92d347a 190 190 +ItemUsage owningDefinition 9113a29a44a35a5c 190 86 +ItemUsage owningFeatureMembership 0a95922380d3ba3f 190 184 +ItemUsage owningMembership d0cbc82f8d33e1f2 190 190 +ItemUsage owningNamespace 7b7f164cc92d347a 190 190 +ItemUsage owningRelationship d0cbc82f8d33e1f2 190 190 +ItemUsage owningType 8bb685480d69b535 190 184 +ItemUsage owningUsage 98c04cc8df362590 190 98 +ItemUsage portionKind 3d121cf96d9d8cb7 190 1 +ItemUsage qualifiedName 0e7ce0219d07b077 190 180 +ItemUsage shortName 9e1d6a1b166fcab7 190 0 +ItemUsage textualRepresentation c416504ade11b787 190 0 +ItemUsage type 19253040d2445f61 190 146 +ItemUsage unioningType c416504ade11b787 190 0 +ItemUsage usage ed4d9cc3edc3737a 190 27 +ItemUsage variant c416504ade11b787 190 0 +ItemUsage variantMembership c416504ade11b787 190 0 +JoinNode actionDefinition c55adb631509aa04 5 0 +JoinNode aliasIds c55adb631509aa04 5 0 +JoinNode behavior c55adb631509aa04 5 0 +JoinNode chainingFeature c55adb631509aa04 5 0 +JoinNode crossFeature 9176e7c3d4189fc5 5 0 +JoinNode declaredName 1b5d3564fcbd4b2a 5 5 +JoinNode declaredShortName 9176e7c3d4189fc5 5 0 +JoinNode definition c55adb631509aa04 5 0 +JoinNode differencingType c55adb631509aa04 5 0 +JoinNode directedFeature c55adb631509aa04 5 0 +JoinNode directedUsage c55adb631509aa04 5 0 +JoinNode direction 9176e7c3d4189fc5 5 0 +JoinNode documentation c55adb631509aa04 5 0 +JoinNode elementId d6e21c83612d4e0c 5 5 +JoinNode endFeature c55adb631509aa04 5 0 +JoinNode endOwningType 9176e7c3d4189fc5 5 0 +JoinNode feature c55adb631509aa04 5 0 +JoinNode featureMembership c55adb631509aa04 5 0 +JoinNode featureTarget 4cd872fef748a05d 5 0 +JoinNode featuringType c55adb631509aa04 5 0 +JoinNode importedMembership c55adb631509aa04 5 0 +JoinNode individualDefinition 9176e7c3d4189fc5 5 0 +JoinNode inheritedFeature c55adb631509aa04 5 0 +JoinNode inheritedMembership c55adb631509aa04 5 0 +JoinNode input c55adb631509aa04 5 0 +JoinNode intersectingType c55adb631509aa04 5 0 +JoinNode isAbstract 265e91ff2e4db70f 5 0 +JoinNode isComposite 3e7b963c150b94f8 5 5 +JoinNode isConjugated 265e91ff2e4db70f 5 0 +JoinNode isConstant 265e91ff2e4db70f 5 0 +JoinNode isDerived 265e91ff2e4db70f 5 0 +JoinNode isEnd 265e91ff2e4db70f 5 0 +JoinNode isImpliedIncluded 3e7b963c150b94f8 5 5 +JoinNode isIndividual 9176e7c3d4189fc5 5 0 +JoinNode isLibraryElement 265e91ff2e4db70f 5 0 +JoinNode isOrdered 265e91ff2e4db70f 5 0 +JoinNode isPortion 9176e7c3d4189fc5 5 0 +JoinNode isReference 265e91ff2e4db70f 5 0 +JoinNode isSufficient 9176e7c3d4189fc5 5 0 +JoinNode isUnique 3e7b963c150b94f8 5 5 +JoinNode isVariable 9176e7c3d4189fc5 5 0 +JoinNode isVariation 265e91ff2e4db70f 5 0 +JoinNode mayTimeVary 9176e7c3d4189fc5 5 0 +JoinNode member c55adb631509aa04 5 0 +JoinNode membership c55adb631509aa04 5 0 +JoinNode multiplicity 9176e7c3d4189fc5 5 0 +JoinNode name 1b5d3564fcbd4b2a 5 5 +JoinNode nestedAction c55adb631509aa04 5 0 +JoinNode nestedAllocation c55adb631509aa04 5 0 +JoinNode nestedAnalysisCase c55adb631509aa04 5 0 +JoinNode nestedAttribute c55adb631509aa04 5 0 +JoinNode nestedCalculation c55adb631509aa04 5 0 +JoinNode nestedCase c55adb631509aa04 5 0 +JoinNode nestedConcern c55adb631509aa04 5 0 +JoinNode nestedConnection c55adb631509aa04 5 0 +JoinNode nestedConstraint c55adb631509aa04 5 0 +JoinNode nestedEnumeration c55adb631509aa04 5 0 +JoinNode nestedFlow c55adb631509aa04 5 0 +JoinNode nestedInterface c55adb631509aa04 5 0 +JoinNode nestedItem c55adb631509aa04 5 0 +JoinNode nestedMetadata c55adb631509aa04 5 0 +JoinNode nestedOccurrence c55adb631509aa04 5 0 +JoinNode nestedPart c55adb631509aa04 5 0 +JoinNode nestedPort c55adb631509aa04 5 0 +JoinNode nestedReference c55adb631509aa04 5 0 +JoinNode nestedRendering c55adb631509aa04 5 0 +JoinNode nestedRequirement c55adb631509aa04 5 0 +JoinNode nestedState c55adb631509aa04 5 0 +JoinNode nestedTransition c55adb631509aa04 5 0 +JoinNode nestedUsage c55adb631509aa04 5 0 +JoinNode nestedUseCase c55adb631509aa04 5 0 +JoinNode nestedVerificationCase c55adb631509aa04 5 0 +JoinNode nestedView c55adb631509aa04 5 0 +JoinNode nestedViewpoint c55adb631509aa04 5 0 +JoinNode occurrenceDefinition c55adb631509aa04 5 0 +JoinNode output c55adb631509aa04 5 0 +JoinNode ownedAnnotation c55adb631509aa04 5 0 +JoinNode ownedConjugator 9176e7c3d4189fc5 5 0 +JoinNode ownedCrossSubsetting 9176e7c3d4189fc5 5 0 +JoinNode ownedDifferencing c55adb631509aa04 5 0 +JoinNode ownedDisjoining c55adb631509aa04 5 0 +JoinNode ownedElement c55adb631509aa04 5 0 +JoinNode ownedEndFeature c55adb631509aa04 5 0 +JoinNode ownedFeature c55adb631509aa04 5 0 +JoinNode ownedFeatureChaining c55adb631509aa04 5 0 +JoinNode ownedFeatureInverting c55adb631509aa04 5 0 +JoinNode ownedFeatureMembership c55adb631509aa04 5 0 +JoinNode ownedImport c55adb631509aa04 5 0 +JoinNode ownedIntersecting c55adb631509aa04 5 0 +JoinNode ownedMember c55adb631509aa04 5 0 +JoinNode ownedMembership c55adb631509aa04 5 0 +JoinNode ownedRedefinition c55adb631509aa04 5 0 +JoinNode ownedReferenceSubsetting 9176e7c3d4189fc5 5 0 +JoinNode ownedRelationship c55adb631509aa04 5 0 +JoinNode ownedSpecialization c55adb631509aa04 5 0 +JoinNode ownedSubsetting c55adb631509aa04 5 0 +JoinNode ownedTypeFeaturing c55adb631509aa04 5 0 +JoinNode ownedTyping c55adb631509aa04 5 0 +JoinNode ownedUnioning c55adb631509aa04 5 0 +JoinNode owner 18367995751586f2 5 5 +JoinNode owningDefinition 9d688a961c02cab1 5 2 +JoinNode owningFeatureMembership a3992427994c1483 5 5 +JoinNode owningMembership a3992427994c1483 5 5 +JoinNode owningNamespace 18367995751586f2 5 5 +JoinNode owningRelationship a3992427994c1483 5 5 +JoinNode owningType 18367995751586f2 5 5 +JoinNode owningUsage 0c44d6c32d2b5c06 5 3 +JoinNode parameter c55adb631509aa04 5 0 +JoinNode portionKind 9176e7c3d4189fc5 5 0 +JoinNode qualifiedName 5ad6628caad8b6aa 5 5 +JoinNode shortName 9176e7c3d4189fc5 5 0 +JoinNode textualRepresentation c55adb631509aa04 5 0 +JoinNode type c55adb631509aa04 5 0 +JoinNode unioningType c55adb631509aa04 5 0 +JoinNode usage c55adb631509aa04 5 0 +JoinNode variant c55adb631509aa04 5 0 +JoinNode variantMembership c55adb631509aa04 5 0 +LibraryPackage aliasIds d76f68a7c55805e7 8 0 +LibraryPackage declaredName 518fd82cde3f2f2d 8 8 +LibraryPackage declaredShortName 8463de2cb7faf681 8 0 +LibraryPackage documentation d76f68a7c55805e7 8 0 +LibraryPackage elementId 2f2996345540cfa4 8 8 +LibraryPackage filterCondition d76f68a7c55805e7 8 0 +LibraryPackage importedMembership d76f68a7c55805e7 8 0 +LibraryPackage isImpliedIncluded 041cfff9a1358f9b 8 8 +LibraryPackage isLibraryElement 041cfff9a1358f9b 8 8 +LibraryPackage isStandard 6b02450e6f3c248b 8 0 +LibraryPackage member b615f040181dc993 8 8 +LibraryPackage membership 0d353f1c493f0e4a 8 8 +LibraryPackage name 518fd82cde3f2f2d 8 8 +LibraryPackage ownedAnnotation d76f68a7c55805e7 8 0 +LibraryPackage ownedElement b615f040181dc993 8 8 +LibraryPackage ownedImport 2cd9354db8658d4f 8 6 +LibraryPackage ownedMember b615f040181dc993 8 8 +LibraryPackage ownedMembership 0d353f1c493f0e4a 8 8 +LibraryPackage ownedRelationship 4278927aaef4a308 8 8 +LibraryPackage owner 0c34088f7dca6d26 8 8 +LibraryPackage owningMembership 2a81cfa87fa1c523 8 8 +LibraryPackage owningNamespace 0c34088f7dca6d26 8 8 +LibraryPackage owningRelationship 2a81cfa87fa1c523 8 8 +LibraryPackage qualifiedName 17df4589cd668252 8 8 +LibraryPackage shortName 8463de2cb7faf681 8 0 +LibraryPackage textualRepresentation d76f68a7c55805e7 8 0 +LiteralBoolean aliasIds ff4729258c8ecd00 35 0 +LiteralBoolean behavior ff4729258c8ecd00 35 0 +LiteralBoolean chainingFeature ff4729258c8ecd00 35 0 +LiteralBoolean crossFeature 10556b05e65bb947 35 0 +LiteralBoolean declaredName 10556b05e65bb947 35 0 +LiteralBoolean declaredShortName 10556b05e65bb947 35 0 +LiteralBoolean differencingType ff4729258c8ecd00 35 0 +LiteralBoolean directedFeature ff4729258c8ecd00 35 0 +LiteralBoolean direction 10556b05e65bb947 35 0 +LiteralBoolean documentation ff4729258c8ecd00 35 0 +LiteralBoolean elementId 47505942728ddc78 35 35 +LiteralBoolean endFeature ff4729258c8ecd00 35 0 +LiteralBoolean endOwningType 10556b05e65bb947 35 0 +LiteralBoolean feature ff4729258c8ecd00 35 0 +LiteralBoolean featureMembership ff4729258c8ecd00 35 0 +LiteralBoolean featureTarget e5f8027001bd7ae7 35 0 +LiteralBoolean featuringType ff4729258c8ecd00 35 0 +LiteralBoolean function 10556b05e65bb947 35 0 +LiteralBoolean importedMembership ff4729258c8ecd00 35 0 +LiteralBoolean inheritedFeature ff4729258c8ecd00 35 0 +LiteralBoolean inheritedMembership ff4729258c8ecd00 35 0 +LiteralBoolean input ff4729258c8ecd00 35 0 +LiteralBoolean intersectingType ff4729258c8ecd00 35 0 +LiteralBoolean isAbstract 10556b05e65bb947 35 0 +LiteralBoolean isComposite 10556b05e65bb947 35 0 +LiteralBoolean isConjugated cf320728b3932735 35 0 +LiteralBoolean isConstant 10556b05e65bb947 35 0 +LiteralBoolean isDerived 10556b05e65bb947 35 0 +LiteralBoolean isEnd 10556b05e65bb947 35 0 +LiteralBoolean isImpliedIncluded bdf27cb55a38458c 35 35 +LiteralBoolean isLibraryElement cf320728b3932735 35 0 +LiteralBoolean isModelLevelEvaluable bdf27cb55a38458c 35 35 +LiteralBoolean isOrdered 10556b05e65bb947 35 0 +LiteralBoolean isPortion 10556b05e65bb947 35 0 +LiteralBoolean isSufficient 10556b05e65bb947 35 0 +LiteralBoolean isUnique 10556b05e65bb947 35 0 +LiteralBoolean isVariable 10556b05e65bb947 35 0 +LiteralBoolean member ff4729258c8ecd00 35 0 +LiteralBoolean membership ff4729258c8ecd00 35 0 +LiteralBoolean multiplicity 10556b05e65bb947 35 0 +LiteralBoolean name 10556b05e65bb947 35 0 +LiteralBoolean output ff4729258c8ecd00 35 0 +LiteralBoolean ownedAnnotation ff4729258c8ecd00 35 0 +LiteralBoolean ownedConjugator 10556b05e65bb947 35 0 +LiteralBoolean ownedCrossSubsetting 10556b05e65bb947 35 0 +LiteralBoolean ownedDifferencing ff4729258c8ecd00 35 0 +LiteralBoolean ownedDisjoining ff4729258c8ecd00 35 0 +LiteralBoolean ownedElement ff4729258c8ecd00 35 0 +LiteralBoolean ownedEndFeature ff4729258c8ecd00 35 0 +LiteralBoolean ownedFeature ff4729258c8ecd00 35 0 +LiteralBoolean ownedFeatureChaining ff4729258c8ecd00 35 0 +LiteralBoolean ownedFeatureInverting ff4729258c8ecd00 35 0 +LiteralBoolean ownedFeatureMembership ff4729258c8ecd00 35 0 +LiteralBoolean ownedImport ff4729258c8ecd00 35 0 +LiteralBoolean ownedIntersecting ff4729258c8ecd00 35 0 +LiteralBoolean ownedMember ff4729258c8ecd00 35 0 +LiteralBoolean ownedMembership ff4729258c8ecd00 35 0 +LiteralBoolean ownedRedefinition ff4729258c8ecd00 35 0 +LiteralBoolean ownedReferenceSubsetting 10556b05e65bb947 35 0 +LiteralBoolean ownedRelationship ff4729258c8ecd00 35 0 +LiteralBoolean ownedSpecialization ff4729258c8ecd00 35 0 +LiteralBoolean ownedSubsetting ff4729258c8ecd00 35 0 +LiteralBoolean ownedTypeFeaturing ff4729258c8ecd00 35 0 +LiteralBoolean ownedTyping ff4729258c8ecd00 35 0 +LiteralBoolean ownedUnioning ff4729258c8ecd00 35 0 +LiteralBoolean owner 21ef8dc943c46d46 35 35 +LiteralBoolean owningFeatureMembership 4a7ebb646a2d6fbd 35 4 +LiteralBoolean owningMembership e07779c4635ec164 35 35 +LiteralBoolean owningNamespace 21ef8dc943c46d46 35 35 +LiteralBoolean owningRelationship e07779c4635ec164 35 35 +LiteralBoolean owningType 02b5a8c84b220384 35 4 +LiteralBoolean parameter ff4729258c8ecd00 35 0 +LiteralBoolean qualifiedName 10556b05e65bb947 35 0 +LiteralBoolean result e5f8027001bd7ae7 35 0 +LiteralBoolean shortName 10556b05e65bb947 35 0 +LiteralBoolean textualRepresentation ff4729258c8ecd00 35 0 +LiteralBoolean type ff4729258c8ecd00 35 0 +LiteralBoolean unioningType ff4729258c8ecd00 35 0 +LiteralBoolean value e646ef9b0a2f0730 35 23 +LiteralInfinity aliasIds c78ecf28df0cb903 119 0 +LiteralInfinity behavior c78ecf28df0cb903 119 0 +LiteralInfinity chainingFeature c78ecf28df0cb903 119 0 +LiteralInfinity crossFeature dc92a411e6726750 119 0 +LiteralInfinity declaredName dc92a411e6726750 119 0 +LiteralInfinity declaredShortName dc92a411e6726750 119 0 +LiteralInfinity differencingType c78ecf28df0cb903 119 0 +LiteralInfinity directedFeature c78ecf28df0cb903 119 0 +LiteralInfinity direction dc92a411e6726750 119 0 +LiteralInfinity documentation c78ecf28df0cb903 119 0 +LiteralInfinity elementId f1b2a48a3722d90c 119 119 +LiteralInfinity endFeature c78ecf28df0cb903 119 0 +LiteralInfinity endOwningType dc92a411e6726750 119 0 +LiteralInfinity feature c78ecf28df0cb903 119 0 +LiteralInfinity featureMembership c78ecf28df0cb903 119 0 +LiteralInfinity featureTarget bab71a5d35f8b401 119 0 +LiteralInfinity featuringType c78ecf28df0cb903 119 0 +LiteralInfinity function dc92a411e6726750 119 0 +LiteralInfinity importedMembership c78ecf28df0cb903 119 0 +LiteralInfinity inheritedFeature c78ecf28df0cb903 119 0 +LiteralInfinity inheritedMembership c78ecf28df0cb903 119 0 +LiteralInfinity input c78ecf28df0cb903 119 0 +LiteralInfinity intersectingType c78ecf28df0cb903 119 0 +LiteralInfinity isAbstract dc92a411e6726750 119 0 +LiteralInfinity isComposite dc92a411e6726750 119 0 +LiteralInfinity isConjugated 12c1c6b99a8f2628 119 0 +LiteralInfinity isConstant dc92a411e6726750 119 0 +LiteralInfinity isDerived dc92a411e6726750 119 0 +LiteralInfinity isEnd dc92a411e6726750 119 0 +LiteralInfinity isImpliedIncluded 75bf1c2267ea921b 119 119 +LiteralInfinity isLibraryElement 9d850c4e1feaf096 119 30 +LiteralInfinity isModelLevelEvaluable 75bf1c2267ea921b 119 119 +LiteralInfinity isOrdered dc92a411e6726750 119 0 +LiteralInfinity isPortion dc92a411e6726750 119 0 +LiteralInfinity isSufficient dc92a411e6726750 119 0 +LiteralInfinity isUnique dc92a411e6726750 119 0 +LiteralInfinity isVariable dc92a411e6726750 119 0 +LiteralInfinity member c78ecf28df0cb903 119 0 +LiteralInfinity membership c78ecf28df0cb903 119 0 +LiteralInfinity multiplicity dc92a411e6726750 119 0 +LiteralInfinity name dc92a411e6726750 119 0 +LiteralInfinity output c78ecf28df0cb903 119 0 +LiteralInfinity ownedAnnotation c78ecf28df0cb903 119 0 +LiteralInfinity ownedConjugator dc92a411e6726750 119 0 +LiteralInfinity ownedCrossSubsetting dc92a411e6726750 119 0 +LiteralInfinity ownedDifferencing c78ecf28df0cb903 119 0 +LiteralInfinity ownedDisjoining c78ecf28df0cb903 119 0 +LiteralInfinity ownedElement c78ecf28df0cb903 119 0 +LiteralInfinity ownedEndFeature c78ecf28df0cb903 119 0 +LiteralInfinity ownedFeature c78ecf28df0cb903 119 0 +LiteralInfinity ownedFeatureChaining c78ecf28df0cb903 119 0 +LiteralInfinity ownedFeatureInverting c78ecf28df0cb903 119 0 +LiteralInfinity ownedFeatureMembership c78ecf28df0cb903 119 0 +LiteralInfinity ownedImport c78ecf28df0cb903 119 0 +LiteralInfinity ownedIntersecting c78ecf28df0cb903 119 0 +LiteralInfinity ownedMember c78ecf28df0cb903 119 0 +LiteralInfinity ownedMembership c78ecf28df0cb903 119 0 +LiteralInfinity ownedRedefinition c78ecf28df0cb903 119 0 +LiteralInfinity ownedReferenceSubsetting dc92a411e6726750 119 0 +LiteralInfinity ownedRelationship c78ecf28df0cb903 119 0 +LiteralInfinity ownedSpecialization c78ecf28df0cb903 119 0 +LiteralInfinity ownedSubsetting c78ecf28df0cb903 119 0 +LiteralInfinity ownedTypeFeaturing c78ecf28df0cb903 119 0 +LiteralInfinity ownedTyping c78ecf28df0cb903 119 0 +LiteralInfinity ownedUnioning c78ecf28df0cb903 119 0 +LiteralInfinity owner 16aebc149cc051c8 119 119 +LiteralInfinity owningFeatureMembership dc92a411e6726750 119 0 +LiteralInfinity owningMembership 38977521c3e310c6 119 119 +LiteralInfinity owningNamespace 16aebc149cc051c8 119 119 +LiteralInfinity owningRelationship 38977521c3e310c6 119 119 +LiteralInfinity owningType dc92a411e6726750 119 0 +LiteralInfinity parameter c78ecf28df0cb903 119 0 +LiteralInfinity qualifiedName dc92a411e6726750 119 0 +LiteralInfinity result bab71a5d35f8b401 119 0 +LiteralInfinity shortName dc92a411e6726750 119 0 +LiteralInfinity textualRepresentation c78ecf28df0cb903 119 0 +LiteralInfinity type c78ecf28df0cb903 119 0 +LiteralInfinity unioningType c78ecf28df0cb903 119 0 +LiteralInteger aliasIds 74b3d03514840f52 1011 0 +LiteralInteger behavior 74b3d03514840f52 1011 0 +LiteralInteger chainingFeature 74b3d03514840f52 1011 0 +LiteralInteger crossFeature 21ad4147b97eeba1 1011 0 +LiteralInteger declaredName 21ad4147b97eeba1 1011 0 +LiteralInteger declaredShortName 21ad4147b97eeba1 1011 0 +LiteralInteger differencingType 74b3d03514840f52 1011 0 +LiteralInteger directedFeature 74b3d03514840f52 1011 0 +LiteralInteger direction 21ad4147b97eeba1 1011 0 +LiteralInteger documentation 74b3d03514840f52 1011 0 +LiteralInteger elementId f8bb651c9f485fc0 1011 1011 +LiteralInteger endFeature 74b3d03514840f52 1011 0 +LiteralInteger endOwningType 21ad4147b97eeba1 1011 0 +LiteralInteger feature 74b3d03514840f52 1011 0 +LiteralInteger featureMembership 74b3d03514840f52 1011 0 +LiteralInteger featureTarget 2cbe6f27ae1e4527 1011 0 +LiteralInteger featuringType 74b3d03514840f52 1011 0 +LiteralInteger function 21ad4147b97eeba1 1011 0 +LiteralInteger importedMembership 74b3d03514840f52 1011 0 +LiteralInteger inheritedFeature 74b3d03514840f52 1011 0 +LiteralInteger inheritedMembership 74b3d03514840f52 1011 0 +LiteralInteger input 74b3d03514840f52 1011 0 +LiteralInteger intersectingType 74b3d03514840f52 1011 0 +LiteralInteger isAbstract 21ad4147b97eeba1 1011 0 +LiteralInteger isComposite 21ad4147b97eeba1 1011 0 +LiteralInteger isConjugated 4eb6314813552aff 1011 0 +LiteralInteger isConstant 21ad4147b97eeba1 1011 0 +LiteralInteger isDerived 21ad4147b97eeba1 1011 0 +LiteralInteger isEnd 21ad4147b97eeba1 1011 0 +LiteralInteger isImpliedIncluded e2222a5bbbba2bce 1011 1011 +LiteralInteger isLibraryElement 80b894db4502e574 1011 17 +LiteralInteger isModelLevelEvaluable e2222a5bbbba2bce 1011 1011 +LiteralInteger isOrdered 21ad4147b97eeba1 1011 0 +LiteralInteger isPortion 21ad4147b97eeba1 1011 0 +LiteralInteger isSufficient 21ad4147b97eeba1 1011 0 +LiteralInteger isUnique 21ad4147b97eeba1 1011 0 +LiteralInteger isVariable 21ad4147b97eeba1 1011 0 +LiteralInteger member 74b3d03514840f52 1011 0 +LiteralInteger membership 74b3d03514840f52 1011 0 +LiteralInteger multiplicity 21ad4147b97eeba1 1011 0 +LiteralInteger name 21ad4147b97eeba1 1011 0 +LiteralInteger output 74b3d03514840f52 1011 0 +LiteralInteger ownedAnnotation 74b3d03514840f52 1011 0 +LiteralInteger ownedConjugator 21ad4147b97eeba1 1011 0 +LiteralInteger ownedCrossSubsetting 21ad4147b97eeba1 1011 0 +LiteralInteger ownedDifferencing 74b3d03514840f52 1011 0 +LiteralInteger ownedDisjoining 74b3d03514840f52 1011 0 +LiteralInteger ownedElement 74b3d03514840f52 1011 0 +LiteralInteger ownedEndFeature 74b3d03514840f52 1011 0 +LiteralInteger ownedFeature 74b3d03514840f52 1011 0 +LiteralInteger ownedFeatureChaining 74b3d03514840f52 1011 0 +LiteralInteger ownedFeatureInverting 74b3d03514840f52 1011 0 +LiteralInteger ownedFeatureMembership 74b3d03514840f52 1011 0 +LiteralInteger ownedImport 74b3d03514840f52 1011 0 +LiteralInteger ownedIntersecting 74b3d03514840f52 1011 0 +LiteralInteger ownedMember 74b3d03514840f52 1011 0 +LiteralInteger ownedMembership 74b3d03514840f52 1011 0 +LiteralInteger ownedRedefinition 74b3d03514840f52 1011 0 +LiteralInteger ownedReferenceSubsetting 21ad4147b97eeba1 1011 0 +LiteralInteger ownedRelationship 74b3d03514840f52 1011 0 +LiteralInteger ownedSpecialization 74b3d03514840f52 1011 0 +LiteralInteger ownedSubsetting 74b3d03514840f52 1011 0 +LiteralInteger ownedTypeFeaturing 74b3d03514840f52 1011 0 +LiteralInteger ownedTyping 74b3d03514840f52 1011 0 +LiteralInteger ownedUnioning 74b3d03514840f52 1011 0 +LiteralInteger owner 5a1e8d3e1a7fe22e 1011 1011 +LiteralInteger owningFeatureMembership 21ad4147b97eeba1 1011 0 +LiteralInteger owningMembership 504ae9b9d2320750 1011 1011 +LiteralInteger owningNamespace 5a1e8d3e1a7fe22e 1011 1011 +LiteralInteger owningRelationship 504ae9b9d2320750 1011 1011 +LiteralInteger owningType 21ad4147b97eeba1 1011 0 +LiteralInteger parameter 74b3d03514840f52 1011 0 +LiteralInteger qualifiedName 21ad4147b97eeba1 1011 0 +LiteralInteger result 2cbe6f27ae1e4527 1011 0 +LiteralInteger shortName 21ad4147b97eeba1 1011 0 +LiteralInteger textualRepresentation 74b3d03514840f52 1011 0 +LiteralInteger type 74b3d03514840f52 1011 0 +LiteralInteger unioningType 74b3d03514840f52 1011 0 +LiteralInteger value 6fb71f1c56856805 1011 1011 +LiteralRational aliasIds f3f3421e925cd97b 109 0 +LiteralRational behavior f3f3421e925cd97b 109 0 +LiteralRational chainingFeature f3f3421e925cd97b 109 0 +LiteralRational crossFeature e15a8d9a2f46ac3a 109 0 +LiteralRational declaredName e15a8d9a2f46ac3a 109 0 +LiteralRational declaredShortName e15a8d9a2f46ac3a 109 0 +LiteralRational differencingType f3f3421e925cd97b 109 0 +LiteralRational directedFeature f3f3421e925cd97b 109 0 +LiteralRational direction e15a8d9a2f46ac3a 109 0 +LiteralRational documentation f3f3421e925cd97b 109 0 +LiteralRational elementId 0720297da2c8c30c 109 109 +LiteralRational endFeature f3f3421e925cd97b 109 0 +LiteralRational endOwningType e15a8d9a2f46ac3a 109 0 +LiteralRational feature f3f3421e925cd97b 109 0 +LiteralRational featureMembership f3f3421e925cd97b 109 0 +LiteralRational featureTarget 550905143afcc867 109 0 +LiteralRational featuringType f3f3421e925cd97b 109 0 +LiteralRational function e15a8d9a2f46ac3a 109 0 +LiteralRational importedMembership f3f3421e925cd97b 109 0 +LiteralRational inheritedFeature f3f3421e925cd97b 109 0 +LiteralRational inheritedMembership f3f3421e925cd97b 109 0 +LiteralRational input f3f3421e925cd97b 109 0 +LiteralRational intersectingType f3f3421e925cd97b 109 0 +LiteralRational isAbstract e15a8d9a2f46ac3a 109 0 +LiteralRational isComposite e15a8d9a2f46ac3a 109 0 +LiteralRational isConjugated f2243fdf46eab0e2 109 0 +LiteralRational isConstant e15a8d9a2f46ac3a 109 0 +LiteralRational isDerived e15a8d9a2f46ac3a 109 0 +LiteralRational isEnd e15a8d9a2f46ac3a 109 0 +LiteralRational isImpliedIncluded a4701d3a4ec5119b 109 109 +LiteralRational isLibraryElement f2243fdf46eab0e2 109 0 +LiteralRational isModelLevelEvaluable a4701d3a4ec5119b 109 109 +LiteralRational isOrdered e15a8d9a2f46ac3a 109 0 +LiteralRational isPortion e15a8d9a2f46ac3a 109 0 +LiteralRational isSufficient e15a8d9a2f46ac3a 109 0 +LiteralRational isUnique e15a8d9a2f46ac3a 109 0 +LiteralRational isVariable e15a8d9a2f46ac3a 109 0 +LiteralRational member f3f3421e925cd97b 109 0 +LiteralRational membership f3f3421e925cd97b 109 0 +LiteralRational multiplicity e15a8d9a2f46ac3a 109 0 +LiteralRational name e15a8d9a2f46ac3a 109 0 +LiteralRational output f3f3421e925cd97b 109 0 +LiteralRational ownedAnnotation f3f3421e925cd97b 109 0 +LiteralRational ownedConjugator e15a8d9a2f46ac3a 109 0 +LiteralRational ownedCrossSubsetting e15a8d9a2f46ac3a 109 0 +LiteralRational ownedDifferencing f3f3421e925cd97b 109 0 +LiteralRational ownedDisjoining f3f3421e925cd97b 109 0 +LiteralRational ownedElement f3f3421e925cd97b 109 0 +LiteralRational ownedEndFeature f3f3421e925cd97b 109 0 +LiteralRational ownedFeature f3f3421e925cd97b 109 0 +LiteralRational ownedFeatureChaining f3f3421e925cd97b 109 0 +LiteralRational ownedFeatureInverting f3f3421e925cd97b 109 0 +LiteralRational ownedFeatureMembership f3f3421e925cd97b 109 0 +LiteralRational ownedImport f3f3421e925cd97b 109 0 +LiteralRational ownedIntersecting f3f3421e925cd97b 109 0 +LiteralRational ownedMember f3f3421e925cd97b 109 0 +LiteralRational ownedMembership f3f3421e925cd97b 109 0 +LiteralRational ownedRedefinition f3f3421e925cd97b 109 0 +LiteralRational ownedReferenceSubsetting e15a8d9a2f46ac3a 109 0 +LiteralRational ownedRelationship f3f3421e925cd97b 109 0 +LiteralRational ownedSpecialization f3f3421e925cd97b 109 0 +LiteralRational ownedSubsetting f3f3421e925cd97b 109 0 +LiteralRational ownedTypeFeaturing f3f3421e925cd97b 109 0 +LiteralRational ownedTyping f3f3421e925cd97b 109 0 +LiteralRational ownedUnioning f3f3421e925cd97b 109 0 +LiteralRational owner 9ab71a0813e703a9 109 109 +LiteralRational owningFeatureMembership e15a8d9a2f46ac3a 109 0 +LiteralRational owningMembership b700c5f360bcc9d2 109 109 +LiteralRational owningNamespace 9ab71a0813e703a9 109 109 +LiteralRational owningRelationship b700c5f360bcc9d2 109 109 +LiteralRational owningType e15a8d9a2f46ac3a 109 0 +LiteralRational parameter f3f3421e925cd97b 109 0 +LiteralRational qualifiedName e15a8d9a2f46ac3a 109 0 +LiteralRational result 550905143afcc867 109 0 +LiteralRational shortName e15a8d9a2f46ac3a 109 0 +LiteralRational textualRepresentation f3f3421e925cd97b 109 0 +LiteralRational type f3f3421e925cd97b 109 0 +LiteralRational unioningType f3f3421e925cd97b 109 0 +LiteralRational value f61f099a624fe865 109 109 +LiteralString aliasIds d9b77a1f6c00ae64 57 0 +LiteralString behavior d9b77a1f6c00ae64 57 0 +LiteralString chainingFeature d9b77a1f6c00ae64 57 0 +LiteralString crossFeature d516443a7f6fefed 57 0 +LiteralString declaredName d516443a7f6fefed 57 0 +LiteralString declaredShortName d516443a7f6fefed 57 0 +LiteralString differencingType d9b77a1f6c00ae64 57 0 +LiteralString directedFeature d9b77a1f6c00ae64 57 0 +LiteralString direction d516443a7f6fefed 57 0 +LiteralString documentation d9b77a1f6c00ae64 57 0 +LiteralString elementId 5979b6d7a7f0f6ec 57 57 +LiteralString endFeature d9b77a1f6c00ae64 57 0 +LiteralString endOwningType d516443a7f6fefed 57 0 +LiteralString feature d9b77a1f6c00ae64 57 0 +LiteralString featureMembership d9b77a1f6c00ae64 57 0 +LiteralString featureTarget 3ad50cc6502d28e9 57 0 +LiteralString featuringType d9b77a1f6c00ae64 57 0 +LiteralString function d516443a7f6fefed 57 0 +LiteralString importedMembership d9b77a1f6c00ae64 57 0 +LiteralString inheritedFeature d9b77a1f6c00ae64 57 0 +LiteralString inheritedMembership d9b77a1f6c00ae64 57 0 +LiteralString input d9b77a1f6c00ae64 57 0 +LiteralString intersectingType d9b77a1f6c00ae64 57 0 +LiteralString isAbstract d516443a7f6fefed 57 0 +LiteralString isComposite d516443a7f6fefed 57 0 +LiteralString isConjugated 50832d025a25db73 57 0 +LiteralString isConstant d516443a7f6fefed 57 0 +LiteralString isDerived d516443a7f6fefed 57 0 +LiteralString isEnd d516443a7f6fefed 57 0 +LiteralString isImpliedIncluded f3488f33ede83e30 57 57 +LiteralString isLibraryElement 534f19c8e30ecf60 57 1 +LiteralString isModelLevelEvaluable f3488f33ede83e30 57 57 +LiteralString isOrdered d516443a7f6fefed 57 0 +LiteralString isPortion d516443a7f6fefed 57 0 +LiteralString isSufficient d516443a7f6fefed 57 0 +LiteralString isUnique d516443a7f6fefed 57 0 +LiteralString isVariable d516443a7f6fefed 57 0 +LiteralString member d9b77a1f6c00ae64 57 0 +LiteralString membership d9b77a1f6c00ae64 57 0 +LiteralString multiplicity d516443a7f6fefed 57 0 +LiteralString name d516443a7f6fefed 57 0 +LiteralString output d9b77a1f6c00ae64 57 0 +LiteralString ownedAnnotation d9b77a1f6c00ae64 57 0 +LiteralString ownedConjugator d516443a7f6fefed 57 0 +LiteralString ownedCrossSubsetting d516443a7f6fefed 57 0 +LiteralString ownedDifferencing d9b77a1f6c00ae64 57 0 +LiteralString ownedDisjoining d9b77a1f6c00ae64 57 0 +LiteralString ownedElement d9b77a1f6c00ae64 57 0 +LiteralString ownedEndFeature d9b77a1f6c00ae64 57 0 +LiteralString ownedFeature d9b77a1f6c00ae64 57 0 +LiteralString ownedFeatureChaining d9b77a1f6c00ae64 57 0 +LiteralString ownedFeatureInverting d9b77a1f6c00ae64 57 0 +LiteralString ownedFeatureMembership d9b77a1f6c00ae64 57 0 +LiteralString ownedImport d9b77a1f6c00ae64 57 0 +LiteralString ownedIntersecting d9b77a1f6c00ae64 57 0 +LiteralString ownedMember d9b77a1f6c00ae64 57 0 +LiteralString ownedMembership d9b77a1f6c00ae64 57 0 +LiteralString ownedRedefinition d9b77a1f6c00ae64 57 0 +LiteralString ownedReferenceSubsetting d516443a7f6fefed 57 0 +LiteralString ownedRelationship d9b77a1f6c00ae64 57 0 +LiteralString ownedSpecialization d9b77a1f6c00ae64 57 0 +LiteralString ownedSubsetting d9b77a1f6c00ae64 57 0 +LiteralString ownedTypeFeaturing d9b77a1f6c00ae64 57 0 +LiteralString ownedTyping d9b77a1f6c00ae64 57 0 +LiteralString ownedUnioning d9b77a1f6c00ae64 57 0 +LiteralString owner 95c27131e5ce82b6 57 57 +LiteralString owningFeatureMembership d516443a7f6fefed 57 0 +LiteralString owningMembership 3cf0cd346738be8f 57 57 +LiteralString owningNamespace 95c27131e5ce82b6 57 57 +LiteralString owningRelationship 3cf0cd346738be8f 57 57 +LiteralString owningType d516443a7f6fefed 57 0 +LiteralString parameter d9b77a1f6c00ae64 57 0 +LiteralString qualifiedName d516443a7f6fefed 57 0 +LiteralString result 3ad50cc6502d28e9 57 0 +LiteralString shortName d516443a7f6fefed 57 0 +LiteralString textualRepresentation d9b77a1f6c00ae64 57 0 +LiteralString type d9b77a1f6c00ae64 57 0 +LiteralString unioningType d9b77a1f6c00ae64 57 0 +LiteralString value 20b5017a7ebc6604 57 57 +Membership aliasIds cdc6131fd0a10d92 2338 0 +Membership declaredName 2c91849a426e4310 2338 0 +Membership declaredShortName 2c91849a426e4310 2338 0 +Membership documentation cdc6131fd0a10d92 2338 0 +Membership elementId 92b6720c23c152c0 2338 2338 +Membership isImplied 3546c530d8fe3960 2338 0 +Membership isImpliedIncluded 5c193ffe27565b5a 2338 2338 +Membership isLibraryElement b6e5c4062e9f399b 2338 23 +Membership memberElement ea64876f395c0050 2338 2338 +Membership memberElementId de5cb443d6141cbe 2338 2338 +Membership memberName 77293393d0e06cb2 2338 1804 +Membership memberShortName 0c5630e34a6faf5b 2338 18 +Membership membershipOwningNamespace 9fa6e56e5526b3ed 2338 2338 +Membership name 2c91849a426e4310 2338 0 +Membership ownedAnnotation cdc6131fd0a10d92 2338 0 +Membership ownedElement a6bb43e371ae9534 2338 15 +Membership ownedRelatedElement cdc6131fd0a10d92 2338 0 +Membership ownedRelationship 06a26a02e1f38966 2338 15 +Membership owner 2c91849a426e4310 2338 0 +Membership owningMembership 2c91849a426e4310 2338 0 +Membership owningNamespace 2c91849a426e4310 2338 0 +Membership owningRelatedElement 9fa6e56e5526b3ed 2338 2338 +Membership owningRelationship 2c91849a426e4310 2338 0 +Membership qualifiedName 2c91849a426e4310 2338 0 +Membership relatedElement ee38927ff15b808d 2338 2338 +Membership shortName 2c91849a426e4310 2338 0 +Membership source 3a66bf1d3423662b 2338 2338 +Membership target b7f483e35b910f20 2338 2338 +Membership textualRepresentation a6bb43e371ae9534 2338 15 +Membership visibility ea0802dcac622600 2338 32 +MembershipExpose aliasIds 5c18716f7d72e78f 3 0 +MembershipExpose declaredName e7affae023d5d998 3 0 +MembershipExpose declaredShortName e7affae023d5d998 3 0 +MembershipExpose documentation 5c18716f7d72e78f 3 0 +MembershipExpose elementId 33eb0e0f9711b4f8 3 3 +MembershipExpose importOwningNamespace 5860bcecfe368b6d 3 3 +MembershipExpose importedElement d77424ede90d0d47 3 3 +MembershipExpose importedMembership e4fb362fb60d620d 3 3 +MembershipExpose isImplied d06c5ade5dba8330 3 0 +MembershipExpose isImpliedIncluded 1b7830f8540cb3d7 3 3 +MembershipExpose isImportAll 1b7830f8540cb3d7 3 3 +MembershipExpose isLibraryElement d06c5ade5dba8330 3 0 +MembershipExpose isRecursive 7327bb3fdf548512 3 2 +MembershipExpose name e7affae023d5d998 3 0 +MembershipExpose ownedAnnotation 5c18716f7d72e78f 3 0 +MembershipExpose ownedElement 5c18716f7d72e78f 3 0 +MembershipExpose ownedRelatedElement 5c18716f7d72e78f 3 0 +MembershipExpose ownedRelationship 5c18716f7d72e78f 3 0 +MembershipExpose owner e7affae023d5d998 3 0 +MembershipExpose owningMembership e7affae023d5d998 3 0 +MembershipExpose owningNamespace e7affae023d5d998 3 0 +MembershipExpose owningRelatedElement 5860bcecfe368b6d 3 3 +MembershipExpose owningRelationship e7affae023d5d998 3 0 +MembershipExpose qualifiedName e7affae023d5d998 3 0 +MembershipExpose relatedElement e21de8f186035c07 3 3 +MembershipExpose shortName e7affae023d5d998 3 0 +MembershipExpose source 1b0784c8a9156809 3 3 +MembershipExpose target d45f9c932585737d 3 3 +MembershipExpose textualRepresentation 5c18716f7d72e78f 3 0 +MembershipExpose visibility f078c849e2546357 3 3 +MembershipImport aliasIds 7377536f8f9d5b6a 174 0 +MembershipImport declaredName 3f33792eff066bf0 174 0 +MembershipImport declaredShortName 3f33792eff066bf0 174 0 +MembershipImport documentation 7377536f8f9d5b6a 174 0 +MembershipImport elementId a1083640dc24aaa8 174 174 +MembershipImport importOwningNamespace 7bcb6fd1f0f843fb 174 174 +MembershipImport importedElement c3d6e46c5683c546 174 174 +MembershipImport importedMembership 138dd0aa60a682fe 174 174 +MembershipImport isImplied 5c08bf3ac3efec34 174 0 +MembershipImport isImpliedIncluded 2b4e7a92e103fa8a 174 174 +MembershipImport isImportAll 5c08bf3ac3efec34 174 0 +MembershipImport isLibraryElement 911ea7dfd93237bd 174 5 +MembershipImport isRecursive a9d8521b5217045b 174 27 +MembershipImport name 3f33792eff066bf0 174 0 +MembershipImport ownedAnnotation 7377536f8f9d5b6a 174 0 +MembershipImport ownedElement 451e6eec1189e1e7 174 2 +MembershipImport ownedRelatedElement 7377536f8f9d5b6a 174 0 +MembershipImport ownedRelationship 3efa775f1d2f4be9 174 2 +MembershipImport owner 3f33792eff066bf0 174 0 +MembershipImport owningMembership 3f33792eff066bf0 174 0 +MembershipImport owningNamespace 3f33792eff066bf0 174 0 +MembershipImport owningRelatedElement 7bcb6fd1f0f843fb 174 174 +MembershipImport owningRelationship 3f33792eff066bf0 174 0 +MembershipImport qualifiedName 3f33792eff066bf0 174 0 +MembershipImport relatedElement 1908229d6e93f8e3 174 174 +MembershipImport shortName 3f33792eff066bf0 174 0 +MembershipImport source f184c0d224cd7451 174 174 +MembershipImport target 182d85a289e9a522 174 174 +MembershipImport textualRepresentation 451e6eec1189e1e7 174 2 +MembershipImport visibility fb69917ef5bd1086 174 174 +MergeNode actionDefinition 634980ae0ed80a19 8 0 +MergeNode aliasIds 634980ae0ed80a19 8 0 +MergeNode behavior 634980ae0ed80a19 8 0 +MergeNode chainingFeature 634980ae0ed80a19 8 0 +MergeNode crossFeature d641eefcc747481f 8 0 +MergeNode declaredName e5fc7357908f14e6 8 8 +MergeNode declaredShortName d641eefcc747481f 8 0 +MergeNode definition 634980ae0ed80a19 8 0 +MergeNode differencingType 634980ae0ed80a19 8 0 +MergeNode directedFeature 634980ae0ed80a19 8 0 +MergeNode directedUsage 634980ae0ed80a19 8 0 +MergeNode direction d641eefcc747481f 8 0 +MergeNode documentation 634980ae0ed80a19 8 0 +MergeNode elementId fdb6889eb3e40a48 8 8 +MergeNode endFeature 634980ae0ed80a19 8 0 +MergeNode endOwningType d641eefcc747481f 8 0 +MergeNode feature 634980ae0ed80a19 8 0 +MergeNode featureMembership 634980ae0ed80a19 8 0 +MergeNode featureTarget 966a4337b75a564a 8 0 +MergeNode featuringType 634980ae0ed80a19 8 0 +MergeNode importedMembership 634980ae0ed80a19 8 0 +MergeNode individualDefinition d641eefcc747481f 8 0 +MergeNode inheritedFeature 634980ae0ed80a19 8 0 +MergeNode inheritedMembership 634980ae0ed80a19 8 0 +MergeNode input 634980ae0ed80a19 8 0 +MergeNode intersectingType 634980ae0ed80a19 8 0 +MergeNode isAbstract 3e70cacce7ba6455 8 0 +MergeNode isComposite 22eba3ce73d4dccd 8 8 +MergeNode isConjugated 3e70cacce7ba6455 8 0 +MergeNode isConstant 3e70cacce7ba6455 8 0 +MergeNode isDerived 3e70cacce7ba6455 8 0 +MergeNode isEnd 3e70cacce7ba6455 8 0 +MergeNode isImpliedIncluded 22eba3ce73d4dccd 8 8 +MergeNode isIndividual d641eefcc747481f 8 0 +MergeNode isLibraryElement 3e70cacce7ba6455 8 0 +MergeNode isOrdered 3e70cacce7ba6455 8 0 +MergeNode isPortion d641eefcc747481f 8 0 +MergeNode isReference 3e70cacce7ba6455 8 0 +MergeNode isSufficient d641eefcc747481f 8 0 +MergeNode isUnique 22eba3ce73d4dccd 8 8 +MergeNode isVariable d641eefcc747481f 8 0 +MergeNode isVariation 3e70cacce7ba6455 8 0 +MergeNode mayTimeVary d641eefcc747481f 8 0 +MergeNode member 93125d92639eec3a 8 1 +MergeNode membership 22f60b1d231b46cf 8 1 +MergeNode multiplicity d641eefcc747481f 8 0 +MergeNode name e5fc7357908f14e6 8 8 +MergeNode nestedAction 634980ae0ed80a19 8 0 +MergeNode nestedAllocation 634980ae0ed80a19 8 0 +MergeNode nestedAnalysisCase 634980ae0ed80a19 8 0 +MergeNode nestedAttribute 634980ae0ed80a19 8 0 +MergeNode nestedCalculation 634980ae0ed80a19 8 0 +MergeNode nestedCase 634980ae0ed80a19 8 0 +MergeNode nestedConcern 634980ae0ed80a19 8 0 +MergeNode nestedConnection 634980ae0ed80a19 8 0 +MergeNode nestedConstraint 634980ae0ed80a19 8 0 +MergeNode nestedEnumeration 634980ae0ed80a19 8 0 +MergeNode nestedFlow 634980ae0ed80a19 8 0 +MergeNode nestedInterface 634980ae0ed80a19 8 0 +MergeNode nestedItem 634980ae0ed80a19 8 0 +MergeNode nestedMetadata 634980ae0ed80a19 8 0 +MergeNode nestedOccurrence 634980ae0ed80a19 8 0 +MergeNode nestedPart 634980ae0ed80a19 8 0 +MergeNode nestedPort 634980ae0ed80a19 8 0 +MergeNode nestedReference 634980ae0ed80a19 8 0 +MergeNode nestedRendering 634980ae0ed80a19 8 0 +MergeNode nestedRequirement 634980ae0ed80a19 8 0 +MergeNode nestedState 634980ae0ed80a19 8 0 +MergeNode nestedTransition 634980ae0ed80a19 8 0 +MergeNode nestedUsage 634980ae0ed80a19 8 0 +MergeNode nestedUseCase 634980ae0ed80a19 8 0 +MergeNode nestedVerificationCase 634980ae0ed80a19 8 0 +MergeNode nestedView 634980ae0ed80a19 8 0 +MergeNode nestedViewpoint 634980ae0ed80a19 8 0 +MergeNode occurrenceDefinition 634980ae0ed80a19 8 0 +MergeNode output 634980ae0ed80a19 8 0 +MergeNode ownedAnnotation 634980ae0ed80a19 8 0 +MergeNode ownedConjugator d641eefcc747481f 8 0 +MergeNode ownedCrossSubsetting d641eefcc747481f 8 0 +MergeNode ownedDifferencing 634980ae0ed80a19 8 0 +MergeNode ownedDisjoining 634980ae0ed80a19 8 0 +MergeNode ownedElement 93125d92639eec3a 8 1 +MergeNode ownedEndFeature 634980ae0ed80a19 8 0 +MergeNode ownedFeature 634980ae0ed80a19 8 0 +MergeNode ownedFeatureChaining 634980ae0ed80a19 8 0 +MergeNode ownedFeatureInverting 634980ae0ed80a19 8 0 +MergeNode ownedFeatureMembership 634980ae0ed80a19 8 0 +MergeNode ownedImport 634980ae0ed80a19 8 0 +MergeNode ownedIntersecting 634980ae0ed80a19 8 0 +MergeNode ownedMember 93125d92639eec3a 8 1 +MergeNode ownedMembership 22f60b1d231b46cf 8 1 +MergeNode ownedRedefinition 634980ae0ed80a19 8 0 +MergeNode ownedReferenceSubsetting d641eefcc747481f 8 0 +MergeNode ownedRelationship 22f60b1d231b46cf 8 1 +MergeNode ownedSpecialization 634980ae0ed80a19 8 0 +MergeNode ownedSubsetting 634980ae0ed80a19 8 0 +MergeNode ownedTypeFeaturing 634980ae0ed80a19 8 0 +MergeNode ownedTyping 634980ae0ed80a19 8 0 +MergeNode ownedUnioning 634980ae0ed80a19 8 0 +MergeNode owner 578f9505712edd33 8 8 +MergeNode owningDefinition 6deb67da42e6ed81 8 2 +MergeNode owningFeatureMembership f4dc4bf2882c3f26 8 8 +MergeNode owningMembership f4dc4bf2882c3f26 8 8 +MergeNode owningNamespace 578f9505712edd33 8 8 +MergeNode owningRelationship f4dc4bf2882c3f26 8 8 +MergeNode owningType 578f9505712edd33 8 8 +MergeNode owningUsage bfe61c27f58f37d1 8 6 +MergeNode parameter 634980ae0ed80a19 8 0 +MergeNode portionKind d641eefcc747481f 8 0 +MergeNode qualifiedName ffc2ad25b5efd8d9 8 8 +MergeNode shortName d641eefcc747481f 8 0 +MergeNode textualRepresentation 634980ae0ed80a19 8 0 +MergeNode type 634980ae0ed80a19 8 0 +MergeNode unioningType 634980ae0ed80a19 8 0 +MergeNode usage 634980ae0ed80a19 8 0 +MergeNode variant 634980ae0ed80a19 8 0 +MergeNode variantMembership 634980ae0ed80a19 8 0 +MetadataAccessExpression aliasIds 025be037db3e3fbc 27 0 +MetadataAccessExpression behavior 025be037db3e3fbc 27 0 +MetadataAccessExpression chainingFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression crossFeature c14f1f14323b3067 27 0 +MetadataAccessExpression declaredName c14f1f14323b3067 27 0 +MetadataAccessExpression declaredShortName c14f1f14323b3067 27 0 +MetadataAccessExpression differencingType 025be037db3e3fbc 27 0 +MetadataAccessExpression directedFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression direction c14f1f14323b3067 27 0 +MetadataAccessExpression documentation 025be037db3e3fbc 27 0 +MetadataAccessExpression elementId bfd14e529967d9e4 27 27 +MetadataAccessExpression endFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression endOwningType c14f1f14323b3067 27 0 +MetadataAccessExpression feature 025be037db3e3fbc 27 0 +MetadataAccessExpression featureMembership 025be037db3e3fbc 27 0 +MetadataAccessExpression featureTarget 99df4ae9f3539ef3 27 0 +MetadataAccessExpression featuringType 025be037db3e3fbc 27 0 +MetadataAccessExpression function c14f1f14323b3067 27 0 +MetadataAccessExpression importedMembership 025be037db3e3fbc 27 0 +MetadataAccessExpression inheritedFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression inheritedMembership 025be037db3e3fbc 27 0 +MetadataAccessExpression input 025be037db3e3fbc 27 0 +MetadataAccessExpression intersectingType 025be037db3e3fbc 27 0 +MetadataAccessExpression isAbstract c14f1f14323b3067 27 0 +MetadataAccessExpression isComposite c14f1f14323b3067 27 0 +MetadataAccessExpression isConjugated 594413c2c0270291 27 0 +MetadataAccessExpression isConstant c14f1f14323b3067 27 0 +MetadataAccessExpression isDerived c14f1f14323b3067 27 0 +MetadataAccessExpression isEnd c14f1f14323b3067 27 0 +MetadataAccessExpression isImpliedIncluded 6ace4c6a191e80c8 27 27 +MetadataAccessExpression isLibraryElement 60ec0eea9544e304 27 23 +MetadataAccessExpression isModelLevelEvaluable 6ace4c6a191e80c8 27 27 +MetadataAccessExpression isOrdered c14f1f14323b3067 27 0 +MetadataAccessExpression isPortion c14f1f14323b3067 27 0 +MetadataAccessExpression isSufficient c14f1f14323b3067 27 0 +MetadataAccessExpression isUnique c14f1f14323b3067 27 0 +MetadataAccessExpression isVariable c14f1f14323b3067 27 0 +MetadataAccessExpression member 08e09584f64ea19f 27 27 +MetadataAccessExpression membership 996ead2137227c74 27 27 +MetadataAccessExpression multiplicity c14f1f14323b3067 27 0 +MetadataAccessExpression name c14f1f14323b3067 27 0 +MetadataAccessExpression output 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedAnnotation 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedConjugator c14f1f14323b3067 27 0 +MetadataAccessExpression ownedCrossSubsetting c14f1f14323b3067 27 0 +MetadataAccessExpression ownedDifferencing 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedDisjoining 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedElement 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedEndFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedFeature 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedFeatureChaining 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedFeatureInverting 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedFeatureMembership 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedImport 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedIntersecting 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedMember 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedMembership 996ead2137227c74 27 27 +MetadataAccessExpression ownedRedefinition 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedReferenceSubsetting c14f1f14323b3067 27 0 +MetadataAccessExpression ownedRelationship 996ead2137227c74 27 27 +MetadataAccessExpression ownedSpecialization 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedSubsetting 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedTypeFeaturing 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedTyping 025be037db3e3fbc 27 0 +MetadataAccessExpression ownedUnioning 025be037db3e3fbc 27 0 +MetadataAccessExpression owner 64c47ecba63cb533 27 27 +MetadataAccessExpression owningFeatureMembership c14f1f14323b3067 27 0 +MetadataAccessExpression owningMembership a014bb17878507fd 27 27 +MetadataAccessExpression owningNamespace 64c47ecba63cb533 27 27 +MetadataAccessExpression owningRelationship a014bb17878507fd 27 27 +MetadataAccessExpression owningType c14f1f14323b3067 27 0 +MetadataAccessExpression parameter 025be037db3e3fbc 27 0 +MetadataAccessExpression qualifiedName c14f1f14323b3067 27 0 +MetadataAccessExpression referencedElement 9d47de90b8cb63a5 27 27 +MetadataAccessExpression result 99df4ae9f3539ef3 27 0 +MetadataAccessExpression shortName c14f1f14323b3067 27 0 +MetadataAccessExpression textualRepresentation 025be037db3e3fbc 27 0 +MetadataAccessExpression type 025be037db3e3fbc 27 0 +MetadataAccessExpression unioningType 025be037db3e3fbc 27 0 +MetadataDefinition aliasIds 53276bf2f7d5db5b 46 0 +MetadataDefinition declaredName eaf84d132d2595b6 46 46 +MetadataDefinition declaredShortName 7d43b88c985d81a1 46 21 +MetadataDefinition differencingType 53276bf2f7d5db5b 46 0 +MetadataDefinition directedFeature 53276bf2f7d5db5b 46 0 +MetadataDefinition directedUsage 53276bf2f7d5db5b 46 0 +MetadataDefinition documentation c7d57041e9d03c9f 46 1 +MetadataDefinition elementId 9d2a3e729633f5e8 46 46 +MetadataDefinition endFeature 53276bf2f7d5db5b 46 0 +MetadataDefinition feature 9e131acb1cc34086 46 39 +MetadataDefinition featureMembership 8b2b8c667640e87b 46 39 +MetadataDefinition importedMembership 53276bf2f7d5db5b 46 0 +MetadataDefinition inheritedFeature 53276bf2f7d5db5b 46 0 +MetadataDefinition inheritedMembership 53276bf2f7d5db5b 46 0 +MetadataDefinition input 53276bf2f7d5db5b 46 0 +MetadataDefinition intersectingType 53276bf2f7d5db5b 46 0 +MetadataDefinition isAbstract 931eecbec2776526 46 1 +MetadataDefinition isConjugated d3abf844d3c61b51 46 0 +MetadataDefinition isImpliedIncluded ba060b1c385f9237 46 46 +MetadataDefinition isIndividual 9d895d5cfdeb1313 46 0 +MetadataDefinition isLibraryElement 372dd93311af11c8 46 27 +MetadataDefinition isSufficient d3abf844d3c61b51 46 0 +MetadataDefinition isVariation d3abf844d3c61b51 46 0 +MetadataDefinition member 5d04a0c332dc4ce8 46 39 +MetadataDefinition membership 2b4df04901fcb452 46 39 +MetadataDefinition multiplicity 9d895d5cfdeb1313 46 0 +MetadataDefinition name eaf84d132d2595b6 46 46 +MetadataDefinition output 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedAction 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedAllocation 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedAnalysisCase 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedAnnotation 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedAttribute fc3a1740ea5ff92b 46 8 +MetadataDefinition ownedCalculation 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedCase 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedConcern 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedConjugator 9d895d5cfdeb1313 46 0 +MetadataDefinition ownedConnection 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedConstraint 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedDifferencing 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedDisjoining 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedElement 5d04a0c332dc4ce8 46 39 +MetadataDefinition ownedEndFeature 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedEnumeration 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedFeature 9e131acb1cc34086 46 39 +MetadataDefinition ownedFeatureMembership 8b2b8c667640e87b 46 39 +MetadataDefinition ownedFlow 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedImport 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedInterface 1d5e547331f3d9ae 46 32 +MetadataDefinition ownedIntersecting 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedItem 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedMember 5d04a0c332dc4ce8 46 39 +MetadataDefinition ownedMembership 2b4df04901fcb452 46 39 +MetadataDefinition ownedMetadata 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedOccurrence 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedPart 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedPort 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedReference 1d5e547331f3d9ae 46 32 +MetadataDefinition ownedRelationship 6b2d672f98db2334 46 46 +MetadataDefinition ownedRendering 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedRequirement 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedSpecialization ab61b26088e5d537 46 46 +MetadataDefinition ownedState 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedSubclassification ab61b26088e5d537 46 46 +MetadataDefinition ownedTransition 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedUnioning 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedUsage 9e131acb1cc34086 46 39 +MetadataDefinition ownedUseCase 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedVerificationCase 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedView 53276bf2f7d5db5b 46 0 +MetadataDefinition ownedViewpoint 53276bf2f7d5db5b 46 0 +MetadataDefinition owner 7b39d1249d2754ea 46 46 +MetadataDefinition owningMembership a80aa7917ee5be2d 46 46 +MetadataDefinition owningNamespace 7b39d1249d2754ea 46 46 +MetadataDefinition owningRelationship a80aa7917ee5be2d 46 46 +MetadataDefinition qualifiedName 8ca823a908b3f538 46 46 +MetadataDefinition shortName 7d43b88c985d81a1 46 21 +MetadataDefinition textualRepresentation 53276bf2f7d5db5b 46 0 +MetadataDefinition unioningType 53276bf2f7d5db5b 46 0 +MetadataDefinition usage 9e131acb1cc34086 46 39 +MetadataDefinition variant 53276bf2f7d5db5b 46 0 +MetadataDefinition variantMembership 53276bf2f7d5db5b 46 0 +MetadataUsage aliasIds 3520314ea7a1d36d 179 0 +MetadataUsage annotatedElement 89550060f6f8a186 179 179 +MetadataUsage annotation 4a8d46cc4a0dbb9a 179 7 +MetadataUsage chainingFeature 3520314ea7a1d36d 179 0 +MetadataUsage crossFeature e27d4c669cbaaf9e 179 0 +MetadataUsage declaredName c010ffcf934cbb37 179 2 +MetadataUsage declaredShortName e27d4c669cbaaf9e 179 0 +MetadataUsage definition 3ebe7f44ee1fc6e9 179 179 +MetadataUsage differencingType 3520314ea7a1d36d 179 0 +MetadataUsage directedFeature 3520314ea7a1d36d 179 0 +MetadataUsage directedUsage 3520314ea7a1d36d 179 0 +MetadataUsage direction e27d4c669cbaaf9e 179 0 +MetadataUsage documentation 3520314ea7a1d36d 179 0 +MetadataUsage elementId 4c1a0832f9872774 179 179 +MetadataUsage endFeature 3520314ea7a1d36d 179 0 +MetadataUsage endOwningType e27d4c669cbaaf9e 179 0 +MetadataUsage feature 0a7a7c935a9b2e8c 179 61 +MetadataUsage featureMembership a9ae062b6ba45a0e 179 61 +MetadataUsage featureTarget 6db39301335fe331 179 0 +MetadataUsage featuringType 3520314ea7a1d36d 179 0 +MetadataUsage importedMembership 3520314ea7a1d36d 179 0 +MetadataUsage individualDefinition e27d4c669cbaaf9e 179 0 +MetadataUsage inheritedFeature 3520314ea7a1d36d 179 0 +MetadataUsage inheritedMembership 3520314ea7a1d36d 179 0 +MetadataUsage input 3520314ea7a1d36d 179 0 +MetadataUsage intersectingType 3520314ea7a1d36d 179 0 +MetadataUsage isAbstract a055a35c415b4f0a 179 0 +MetadataUsage isComposite 761ff93ecfd8a0d6 179 0 +MetadataUsage isConjugated 761ff93ecfd8a0d6 179 0 +MetadataUsage isConstant a055a35c415b4f0a 179 0 +MetadataUsage isDerived a055a35c415b4f0a 179 0 +MetadataUsage isEnd a055a35c415b4f0a 179 0 +MetadataUsage isImpliedIncluded 5d3644f223ae6935 179 179 +MetadataUsage isIndividual e27d4c669cbaaf9e 179 0 +MetadataUsage isLibraryElement 1143389b33170b4a 179 20 +MetadataUsage isOrdered a055a35c415b4f0a 179 0 +MetadataUsage isPortion e27d4c669cbaaf9e 179 0 +MetadataUsage isReference 5d3644f223ae6935 179 179 +MetadataUsage isSufficient e27d4c669cbaaf9e 179 0 +MetadataUsage isUnique f4f5132200b1e5e5 179 63 +MetadataUsage isVariable e27d4c669cbaaf9e 179 0 +MetadataUsage isVariation 761ff93ecfd8a0d6 179 0 +MetadataUsage itemDefinition 3ebe7f44ee1fc6e9 179 179 +MetadataUsage mayTimeVary e27d4c669cbaaf9e 179 0 +MetadataUsage member ced30e20d27900a1 179 61 +MetadataUsage membership dd025f5a4b552ed3 179 61 +MetadataUsage metaclass 0d4d87ff91c1b80d 179 179 +MetadataUsage metadataDefinition 0d4d87ff91c1b80d 179 179 +MetadataUsage multiplicity e27d4c669cbaaf9e 179 0 +MetadataUsage name c010ffcf934cbb37 179 2 +MetadataUsage nestedAction 3520314ea7a1d36d 179 0 +MetadataUsage nestedAllocation 3520314ea7a1d36d 179 0 +MetadataUsage nestedAnalysisCase 3520314ea7a1d36d 179 0 +MetadataUsage nestedAttribute 3520314ea7a1d36d 179 0 +MetadataUsage nestedCalculation 3520314ea7a1d36d 179 0 +MetadataUsage nestedCase 3520314ea7a1d36d 179 0 +MetadataUsage nestedConcern 3520314ea7a1d36d 179 0 +MetadataUsage nestedConnection 3520314ea7a1d36d 179 0 +MetadataUsage nestedConstraint 3520314ea7a1d36d 179 0 +MetadataUsage nestedEnumeration 3520314ea7a1d36d 179 0 +MetadataUsage nestedFlow 3520314ea7a1d36d 179 0 +MetadataUsage nestedInterface 0a7a7c935a9b2e8c 179 61 +MetadataUsage nestedItem 3520314ea7a1d36d 179 0 +MetadataUsage nestedMetadata 3520314ea7a1d36d 179 0 +MetadataUsage nestedOccurrence 3520314ea7a1d36d 179 0 +MetadataUsage nestedPart 3520314ea7a1d36d 179 0 +MetadataUsage nestedPort 3520314ea7a1d36d 179 0 +MetadataUsage nestedReference 0a7a7c935a9b2e8c 179 61 +MetadataUsage nestedRendering 3520314ea7a1d36d 179 0 +MetadataUsage nestedRequirement 3520314ea7a1d36d 179 0 +MetadataUsage nestedState 3520314ea7a1d36d 179 0 +MetadataUsage nestedTransition 3520314ea7a1d36d 179 0 +MetadataUsage nestedUsage 0a7a7c935a9b2e8c 179 61 +MetadataUsage nestedUseCase 3520314ea7a1d36d 179 0 +MetadataUsage nestedVerificationCase 3520314ea7a1d36d 179 0 +MetadataUsage nestedView 3520314ea7a1d36d 179 0 +MetadataUsage nestedViewpoint 3520314ea7a1d36d 179 0 +MetadataUsage occurrenceDefinition 3ebe7f44ee1fc6e9 179 179 +MetadataUsage output 3520314ea7a1d36d 179 0 +MetadataUsage ownedAnnotatingRelationship 4a8d46cc4a0dbb9a 179 7 +MetadataUsage ownedAnnotation 3520314ea7a1d36d 179 0 +MetadataUsage ownedConjugator e27d4c669cbaaf9e 179 0 +MetadataUsage ownedCrossSubsetting e27d4c669cbaaf9e 179 0 +MetadataUsage ownedDifferencing 3520314ea7a1d36d 179 0 +MetadataUsage ownedDisjoining 3520314ea7a1d36d 179 0 +MetadataUsage ownedElement ced30e20d27900a1 179 61 +MetadataUsage ownedEndFeature 3520314ea7a1d36d 179 0 +MetadataUsage ownedFeature 0a7a7c935a9b2e8c 179 61 +MetadataUsage ownedFeatureChaining 3520314ea7a1d36d 179 0 +MetadataUsage ownedFeatureInverting 3520314ea7a1d36d 179 0 +MetadataUsage ownedFeatureMembership a9ae062b6ba45a0e 179 61 +MetadataUsage ownedImport 3520314ea7a1d36d 179 0 +MetadataUsage ownedIntersecting 3520314ea7a1d36d 179 0 +MetadataUsage ownedMember ced30e20d27900a1 179 61 +MetadataUsage ownedMembership dd025f5a4b552ed3 179 61 +MetadataUsage ownedRedefinition 3520314ea7a1d36d 179 0 +MetadataUsage ownedReferenceSubsetting e27d4c669cbaaf9e 179 0 +MetadataUsage ownedRelationship e3df85749e1eadf2 179 179 +MetadataUsage ownedSpecialization 0642df554af82739 179 179 +MetadataUsage ownedSubsetting eb6968a1621fc4b8 179 179 +MetadataUsage ownedTypeFeaturing 3520314ea7a1d36d 179 0 +MetadataUsage ownedTyping dfbd602650db3e18 179 179 +MetadataUsage ownedUnioning 3520314ea7a1d36d 179 0 +MetadataUsage owner 971c66fc13268aa7 179 179 +MetadataUsage owningAnnotatingRelationship e27d4c669cbaaf9e 179 0 +MetadataUsage owningDefinition e27d4c669cbaaf9e 179 0 +MetadataUsage owningFeatureMembership e27d4c669cbaaf9e 179 0 +MetadataUsage owningMembership 597ad30bfe8cf0e7 179 179 +MetadataUsage owningNamespace 971c66fc13268aa7 179 179 +MetadataUsage owningRelationship 597ad30bfe8cf0e7 179 179 +MetadataUsage owningType e27d4c669cbaaf9e 179 0 +MetadataUsage owningUsage e27d4c669cbaaf9e 179 0 +MetadataUsage portionKind e27d4c669cbaaf9e 179 0 +MetadataUsage qualifiedName e7121f6aece21c79 179 2 +MetadataUsage shortName e27d4c669cbaaf9e 179 0 +MetadataUsage textualRepresentation 3520314ea7a1d36d 179 0 +MetadataUsage type 3ebe7f44ee1fc6e9 179 179 +MetadataUsage unioningType 3520314ea7a1d36d 179 0 +MetadataUsage usage 0a7a7c935a9b2e8c 179 61 +MetadataUsage variant 3520314ea7a1d36d 179 0 +MetadataUsage variantMembership 3520314ea7a1d36d 179 0 +MultiplicityRange aliasIds 62185e122e4519f8 576 0 +MultiplicityRange bound 83c38c3a1fd53ea2 576 576 +MultiplicityRange chainingFeature 62185e122e4519f8 576 0 +MultiplicityRange crossFeature 64ddbbf33acaebb8 576 0 +MultiplicityRange declaredName 64ddbbf33acaebb8 576 0 +MultiplicityRange declaredShortName 64ddbbf33acaebb8 576 0 +MultiplicityRange differencingType 62185e122e4519f8 576 0 +MultiplicityRange directedFeature 62185e122e4519f8 576 0 +MultiplicityRange direction 64ddbbf33acaebb8 576 0 +MultiplicityRange documentation 62185e122e4519f8 576 0 +MultiplicityRange elementId 6732ee06787c916c 576 576 +MultiplicityRange endFeature 62185e122e4519f8 576 0 +MultiplicityRange endOwningType 64ddbbf33acaebb8 576 0 +MultiplicityRange feature 62185e122e4519f8 576 0 +MultiplicityRange featureMembership 62185e122e4519f8 576 0 +MultiplicityRange featureTarget bf1020147dc7a02c 576 0 +MultiplicityRange featuringType 62185e122e4519f8 576 0 +MultiplicityRange importedMembership 62185e122e4519f8 576 0 +MultiplicityRange inheritedFeature 62185e122e4519f8 576 0 +MultiplicityRange inheritedMembership 62185e122e4519f8 576 0 +MultiplicityRange input 62185e122e4519f8 576 0 +MultiplicityRange intersectingType 62185e122e4519f8 576 0 +MultiplicityRange isAbstract 64ddbbf33acaebb8 576 0 +MultiplicityRange isComposite 64ddbbf33acaebb8 576 0 +MultiplicityRange isConjugated af8e25ed92db23a0 576 0 +MultiplicityRange isConstant 64ddbbf33acaebb8 576 0 +MultiplicityRange isDerived 64ddbbf33acaebb8 576 0 +MultiplicityRange isEnd 64ddbbf33acaebb8 576 0 +MultiplicityRange isImpliedIncluded 6bc3284d49e01e80 576 576 +MultiplicityRange isLibraryElement e7ee5a598da883ca 576 34 +MultiplicityRange isOrdered 64ddbbf33acaebb8 576 0 +MultiplicityRange isPortion 64ddbbf33acaebb8 576 0 +MultiplicityRange isSufficient 64ddbbf33acaebb8 576 0 +MultiplicityRange isUnique 64ddbbf33acaebb8 576 0 +MultiplicityRange isVariable 64ddbbf33acaebb8 576 0 +MultiplicityRange lowerBound bc642c30a3bb9c5f 576 116 +MultiplicityRange member 83c38c3a1fd53ea2 576 576 +MultiplicityRange membership 5238f10af7a6408f 576 576 +MultiplicityRange multiplicity 64ddbbf33acaebb8 576 0 +MultiplicityRange name 64ddbbf33acaebb8 576 0 +MultiplicityRange output 62185e122e4519f8 576 0 +MultiplicityRange ownedAnnotation 62185e122e4519f8 576 0 +MultiplicityRange ownedConjugator 64ddbbf33acaebb8 576 0 +MultiplicityRange ownedCrossSubsetting 64ddbbf33acaebb8 576 0 +MultiplicityRange ownedDifferencing 62185e122e4519f8 576 0 +MultiplicityRange ownedDisjoining 62185e122e4519f8 576 0 +MultiplicityRange ownedElement 83c38c3a1fd53ea2 576 576 +MultiplicityRange ownedEndFeature 62185e122e4519f8 576 0 +MultiplicityRange ownedFeature 62185e122e4519f8 576 0 +MultiplicityRange ownedFeatureChaining 62185e122e4519f8 576 0 +MultiplicityRange ownedFeatureInverting 62185e122e4519f8 576 0 +MultiplicityRange ownedFeatureMembership 62185e122e4519f8 576 0 +MultiplicityRange ownedImport 62185e122e4519f8 576 0 +MultiplicityRange ownedIntersecting 62185e122e4519f8 576 0 +MultiplicityRange ownedMember 83c38c3a1fd53ea2 576 576 +MultiplicityRange ownedMembership 5238f10af7a6408f 576 576 +MultiplicityRange ownedRedefinition 62185e122e4519f8 576 0 +MultiplicityRange ownedReferenceSubsetting 64ddbbf33acaebb8 576 0 +MultiplicityRange ownedRelationship 5238f10af7a6408f 576 576 +MultiplicityRange ownedSpecialization 62185e122e4519f8 576 0 +MultiplicityRange ownedSubsetting 62185e122e4519f8 576 0 +MultiplicityRange ownedTypeFeaturing 62185e122e4519f8 576 0 +MultiplicityRange ownedTyping 62185e122e4519f8 576 0 +MultiplicityRange ownedUnioning 62185e122e4519f8 576 0 +MultiplicityRange owner 1fcb0810a091eada 576 576 +MultiplicityRange owningFeatureMembership 64ddbbf33acaebb8 576 0 +MultiplicityRange owningMembership 43cd19d23e0ce562 576 576 +MultiplicityRange owningNamespace 1fcb0810a091eada 576 576 +MultiplicityRange owningRelationship 43cd19d23e0ce562 576 576 +MultiplicityRange owningType 64ddbbf33acaebb8 576 0 +MultiplicityRange qualifiedName 64ddbbf33acaebb8 576 0 +MultiplicityRange shortName 64ddbbf33acaebb8 576 0 +MultiplicityRange textualRepresentation 62185e122e4519f8 576 0 +MultiplicityRange type 62185e122e4519f8 576 0 +MultiplicityRange unioningType 62185e122e4519f8 576 0 +MultiplicityRange upperBound 4937ddd7fe6d53a3 576 576 +Namespace aliasIds 138431ff31f5a43b 251 0 +Namespace declaredName bb853accf161986c 251 0 +Namespace declaredShortName bb853accf161986c 251 0 +Namespace documentation 138431ff31f5a43b 251 0 +Namespace elementId 097f97c2e57a5eb4 251 251 +Namespace importedMembership 138431ff31f5a43b 251 0 +Namespace isImpliedIncluded 6666ced7ed9346d3 251 251 +Namespace isLibraryElement b2d3c354d574427c 251 0 +Namespace member 1c7af73d7f8de0ca 251 251 +Namespace membership 6634e7a464d5209e 251 251 +Namespace name bb853accf161986c 251 0 +Namespace ownedAnnotation 138431ff31f5a43b 251 0 +Namespace ownedElement 1c7af73d7f8de0ca 251 251 +Namespace ownedImport ee1900fb572e50f0 251 2 +Namespace ownedMember 1c7af73d7f8de0ca 251 251 +Namespace ownedMembership 6634e7a464d5209e 251 251 +Namespace ownedRelationship e94a5265bec7d32f 251 251 +Namespace owner bb853accf161986c 251 0 +Namespace owningMembership bb853accf161986c 251 0 +Namespace owningNamespace bb853accf161986c 251 0 +Namespace owningRelationship bb853accf161986c 251 0 +Namespace qualifiedName bb853accf161986c 251 0 +Namespace shortName bb853accf161986c 251 0 +Namespace textualRepresentation 138431ff31f5a43b 251 0 +NamespaceExpose aliasIds 4fe810b8c495b2b4 6 0 +NamespaceExpose declaredName 353965bac3638292 6 0 +NamespaceExpose declaredShortName 353965bac3638292 6 0 +NamespaceExpose documentation 4fe810b8c495b2b4 6 0 +NamespaceExpose elementId 959e63c014ea56b4 6 6 +NamespaceExpose importOwningNamespace 3e3d3bc295fd83fb 6 6 +NamespaceExpose importedElement 69f06c76871f0e09 6 6 +NamespaceExpose importedNamespace 69f06c76871f0e09 6 6 +NamespaceExpose isImplied f1f517dec9b401be 6 0 +NamespaceExpose isImpliedIncluded c8daae6bbda7541c 6 6 +NamespaceExpose isImportAll c8daae6bbda7541c 6 6 +NamespaceExpose isLibraryElement f1f517dec9b401be 6 0 +NamespaceExpose isRecursive 3a1cba6e005b6433 6 1 +NamespaceExpose name 353965bac3638292 6 0 +NamespaceExpose ownedAnnotation 4fe810b8c495b2b4 6 0 +NamespaceExpose ownedElement 4fe810b8c495b2b4 6 0 +NamespaceExpose ownedRelatedElement 94d99c1dc009ffd3 6 4 +NamespaceExpose ownedRelationship 4fe810b8c495b2b4 6 0 +NamespaceExpose owner 353965bac3638292 6 0 +NamespaceExpose owningMembership 353965bac3638292 6 0 +NamespaceExpose owningNamespace 353965bac3638292 6 0 +NamespaceExpose owningRelatedElement 3e3d3bc295fd83fb 6 6 +NamespaceExpose owningRelationship 353965bac3638292 6 0 +NamespaceExpose qualifiedName 353965bac3638292 6 0 +NamespaceExpose relatedElement 26a449dacf13fa74 6 6 +NamespaceExpose shortName 353965bac3638292 6 0 +NamespaceExpose source 0e1111e5c5af4665 6 6 +NamespaceExpose target ce0c3ab9e46d6d4f 6 6 +NamespaceExpose textualRepresentation 4fe810b8c495b2b4 6 0 +NamespaceExpose visibility 29e204c5f6305260 6 6 +NamespaceImport aliasIds 481f35856d75b66b 383 0 +NamespaceImport declaredName fab3bcd935720d80 383 0 +NamespaceImport declaredShortName fab3bcd935720d80 383 0 +NamespaceImport documentation 481f35856d75b66b 383 0 +NamespaceImport elementId 5810bf55cdfe54e0 383 383 +NamespaceImport importOwningNamespace 58c95cb295996562 383 383 +NamespaceImport importedElement 842e1822086addfe 383 383 +NamespaceImport importedNamespace 842e1822086addfe 383 383 +NamespaceImport isImplied ad17d9322fd0ff70 383 0 +NamespaceImport isImpliedIncluded 4108a528e2a90e5b 383 383 +NamespaceImport isImportAll ba95fd09bb3d1c15 383 1 +NamespaceImport isLibraryElement 941eb8c85a0fe2b3 383 7 +NamespaceImport isRecursive 28c34304c73f34c5 383 1 +NamespaceImport name fab3bcd935720d80 383 0 +NamespaceImport ownedAnnotation 481f35856d75b66b 383 0 +NamespaceImport ownedElement 481f35856d75b66b 383 0 +NamespaceImport ownedRelatedElement 0c36839dd7249e89 383 6 +NamespaceImport ownedRelationship 481f35856d75b66b 383 0 +NamespaceImport owner fab3bcd935720d80 383 0 +NamespaceImport owningMembership fab3bcd935720d80 383 0 +NamespaceImport owningNamespace fab3bcd935720d80 383 0 +NamespaceImport owningRelatedElement 58c95cb295996562 383 383 +NamespaceImport owningRelationship fab3bcd935720d80 383 0 +NamespaceImport qualifiedName fab3bcd935720d80 383 0 +NamespaceImport relatedElement 28067378ffb68ad1 383 383 +NamespaceImport shortName fab3bcd935720d80 383 0 +NamespaceImport source 9ca9988752c61508 383 383 +NamespaceImport target bcedd16d3b498958 383 383 +NamespaceImport textualRepresentation 481f35856d75b66b 383 0 +NamespaceImport visibility 1ea6724886e4315e 383 383 +NullExpression aliasIds 0c8041cb836844b7 10 0 +NullExpression behavior 0c8041cb836844b7 10 0 +NullExpression chainingFeature 0c8041cb836844b7 10 0 +NullExpression crossFeature f3f79feecf93e1ff 10 0 +NullExpression declaredName f3f79feecf93e1ff 10 0 +NullExpression declaredShortName f3f79feecf93e1ff 10 0 +NullExpression differencingType 0c8041cb836844b7 10 0 +NullExpression directedFeature 0c8041cb836844b7 10 0 +NullExpression direction f3f79feecf93e1ff 10 0 +NullExpression documentation 0c8041cb836844b7 10 0 +NullExpression elementId 87c9cfbf188051a0 10 10 +NullExpression endFeature 0c8041cb836844b7 10 0 +NullExpression endOwningType f3f79feecf93e1ff 10 0 +NullExpression feature 0c8041cb836844b7 10 0 +NullExpression featureMembership 0c8041cb836844b7 10 0 +NullExpression featureTarget 007a80fa010e5bb4 10 0 +NullExpression featuringType 0c8041cb836844b7 10 0 +NullExpression function f3f79feecf93e1ff 10 0 +NullExpression importedMembership 0c8041cb836844b7 10 0 +NullExpression inheritedFeature 0c8041cb836844b7 10 0 +NullExpression inheritedMembership 0c8041cb836844b7 10 0 +NullExpression input 0c8041cb836844b7 10 0 +NullExpression intersectingType 0c8041cb836844b7 10 0 +NullExpression isAbstract f3f79feecf93e1ff 10 0 +NullExpression isComposite f3f79feecf93e1ff 10 0 +NullExpression isConjugated f2c0ab4228abc629 10 0 +NullExpression isConstant f3f79feecf93e1ff 10 0 +NullExpression isDerived f3f79feecf93e1ff 10 0 +NullExpression isEnd f3f79feecf93e1ff 10 0 +NullExpression isImpliedIncluded 08283dc51ce9493b 10 10 +NullExpression isLibraryElement f2c0ab4228abc629 10 0 +NullExpression isModelLevelEvaluable 08283dc51ce9493b 10 10 +NullExpression isOrdered f3f79feecf93e1ff 10 0 +NullExpression isPortion f3f79feecf93e1ff 10 0 +NullExpression isSufficient f3f79feecf93e1ff 10 0 +NullExpression isUnique f3f79feecf93e1ff 10 0 +NullExpression isVariable f3f79feecf93e1ff 10 0 +NullExpression member 0c8041cb836844b7 10 0 +NullExpression membership 0c8041cb836844b7 10 0 +NullExpression multiplicity f3f79feecf93e1ff 10 0 +NullExpression name f3f79feecf93e1ff 10 0 +NullExpression output 0c8041cb836844b7 10 0 +NullExpression ownedAnnotation 0c8041cb836844b7 10 0 +NullExpression ownedConjugator f3f79feecf93e1ff 10 0 +NullExpression ownedCrossSubsetting f3f79feecf93e1ff 10 0 +NullExpression ownedDifferencing 0c8041cb836844b7 10 0 +NullExpression ownedDisjoining 0c8041cb836844b7 10 0 +NullExpression ownedElement 0c8041cb836844b7 10 0 +NullExpression ownedEndFeature 0c8041cb836844b7 10 0 +NullExpression ownedFeature 0c8041cb836844b7 10 0 +NullExpression ownedFeatureChaining 0c8041cb836844b7 10 0 +NullExpression ownedFeatureInverting 0c8041cb836844b7 10 0 +NullExpression ownedFeatureMembership 0c8041cb836844b7 10 0 +NullExpression ownedImport 0c8041cb836844b7 10 0 +NullExpression ownedIntersecting 0c8041cb836844b7 10 0 +NullExpression ownedMember 0c8041cb836844b7 10 0 +NullExpression ownedMembership 0c8041cb836844b7 10 0 +NullExpression ownedRedefinition 0c8041cb836844b7 10 0 +NullExpression ownedReferenceSubsetting f3f79feecf93e1ff 10 0 +NullExpression ownedRelationship 0c8041cb836844b7 10 0 +NullExpression ownedSpecialization 0c8041cb836844b7 10 0 +NullExpression ownedSubsetting 0c8041cb836844b7 10 0 +NullExpression ownedTypeFeaturing 0c8041cb836844b7 10 0 +NullExpression ownedTyping 0c8041cb836844b7 10 0 +NullExpression ownedUnioning 0c8041cb836844b7 10 0 +NullExpression owner b48c490df5138bbd 10 10 +NullExpression owningFeatureMembership f3f79feecf93e1ff 10 0 +NullExpression owningMembership c1518978dac5af38 10 10 +NullExpression owningNamespace b48c490df5138bbd 10 10 +NullExpression owningRelationship c1518978dac5af38 10 10 +NullExpression owningType f3f79feecf93e1ff 10 0 +NullExpression parameter 0c8041cb836844b7 10 0 +NullExpression qualifiedName f3f79feecf93e1ff 10 0 +NullExpression result 007a80fa010e5bb4 10 0 +NullExpression shortName f3f79feecf93e1ff 10 0 +NullExpression textualRepresentation 0c8041cb836844b7 10 0 +NullExpression type 0c8041cb836844b7 10 0 +NullExpression unioningType 0c8041cb836844b7 10 0 +ObjectiveMembership aliasIds 1b0710b50f91aeb1 26 0 +ObjectiveMembership declaredName 24a537eabb7dd169 26 0 +ObjectiveMembership declaredShortName 24a537eabb7dd169 26 0 +ObjectiveMembership documentation 1b0710b50f91aeb1 26 0 +ObjectiveMembership elementId 19a4a4957eda6a5c 26 26 +ObjectiveMembership isImplied 86522e148347f74b 26 0 +ObjectiveMembership isImpliedIncluded e40205b914196fdd 26 26 +ObjectiveMembership isLibraryElement 86522e148347f74b 26 0 +ObjectiveMembership memberElement 02825a13bc3471a7 26 26 +ObjectiveMembership memberElementId 1eba0c813ea4c0b3 26 26 +ObjectiveMembership memberName 5b7746134d62fe82 26 26 +ObjectiveMembership memberShortName 24a537eabb7dd169 26 0 +ObjectiveMembership membershipOwningNamespace 6952a3d574b2169b 26 26 +ObjectiveMembership name 24a537eabb7dd169 26 0 +ObjectiveMembership ownedAnnotation 1b0710b50f91aeb1 26 0 +ObjectiveMembership ownedElement 1b0710b50f91aeb1 26 0 +ObjectiveMembership ownedMemberElement 02825a13bc3471a7 26 26 +ObjectiveMembership ownedMemberElementId 1eba0c813ea4c0b3 26 26 +ObjectiveMembership ownedMemberFeature 02825a13bc3471a7 26 26 +ObjectiveMembership ownedMemberName 5b7746134d62fe82 26 26 +ObjectiveMembership ownedMemberShortName 24a537eabb7dd169 26 0 +ObjectiveMembership ownedObjectiveRequirement 02825a13bc3471a7 26 26 +ObjectiveMembership ownedRelatedElement 19a5276d1a537813 26 26 +ObjectiveMembership ownedRelationship 1b0710b50f91aeb1 26 0 +ObjectiveMembership owner 24a537eabb7dd169 26 0 +ObjectiveMembership owningMembership 24a537eabb7dd169 26 0 +ObjectiveMembership owningNamespace 24a537eabb7dd169 26 0 +ObjectiveMembership owningRelatedElement 6952a3d574b2169b 26 26 +ObjectiveMembership owningRelationship 24a537eabb7dd169 26 0 +ObjectiveMembership owningType 6952a3d574b2169b 26 26 +ObjectiveMembership qualifiedName 24a537eabb7dd169 26 0 +ObjectiveMembership relatedElement 772f61ea833849e7 26 26 +ObjectiveMembership shortName 24a537eabb7dd169 26 0 +ObjectiveMembership source 0fbadfa8bf3b3a3f 26 26 +ObjectiveMembership target 19a5276d1a537813 26 26 +ObjectiveMembership textualRepresentation 1b0710b50f91aeb1 26 0 +ObjectiveMembership visibility e3599dbf433df8a5 26 26 +OccurrenceDefinition aliasIds 2440ae8a9a25448e 40 0 +OccurrenceDefinition declaredName 700e394d3b88c9c4 40 40 +OccurrenceDefinition declaredShortName c293ef302434504a 40 0 +OccurrenceDefinition differencingType 2440ae8a9a25448e 40 0 +OccurrenceDefinition directedFeature db2d86198fbdf0b3 40 1 +OccurrenceDefinition directedUsage db2d86198fbdf0b3 40 1 +OccurrenceDefinition documentation 2440ae8a9a25448e 40 0 +OccurrenceDefinition elementId 28897df7df23f4a8 40 40 +OccurrenceDefinition endFeature 2440ae8a9a25448e 40 0 +OccurrenceDefinition feature 9ce4b7ad9bb62e35 40 19 +OccurrenceDefinition featureMembership eb5bc34d082d2425 40 19 +OccurrenceDefinition importedMembership 2440ae8a9a25448e 40 0 +OccurrenceDefinition inheritedFeature 2440ae8a9a25448e 40 0 +OccurrenceDefinition inheritedMembership 2440ae8a9a25448e 40 0 +OccurrenceDefinition input db2d86198fbdf0b3 40 1 +OccurrenceDefinition intersectingType 2440ae8a9a25448e 40 0 +OccurrenceDefinition isAbstract 8d9cd844dbff5b3a 40 4 +OccurrenceDefinition isConjugated 748e9cd0abb5a1c6 40 0 +OccurrenceDefinition isImpliedIncluded d78dc48f061da096 40 40 +OccurrenceDefinition isIndividual 387ccc092cc88e73 40 25 +OccurrenceDefinition isLibraryElement b1dda7a661bd6c59 40 7 +OccurrenceDefinition isSufficient 748e9cd0abb5a1c6 40 0 +OccurrenceDefinition isVariation 748e9cd0abb5a1c6 40 0 +OccurrenceDefinition member e64c72a7c259e9a1 40 19 +OccurrenceDefinition membership 4bd335da6555fd4e 40 19 +OccurrenceDefinition multiplicity c293ef302434504a 40 0 +OccurrenceDefinition name 700e394d3b88c9c4 40 40 +OccurrenceDefinition output 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedAction 6beb1792c22d65a2 40 7 +OccurrenceDefinition ownedAllocation 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedAnalysisCase 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedAnnotation 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedAttribute 04a046e3b4ab6667 40 10 +OccurrenceDefinition ownedCalculation 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedCase 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedConcern 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedConjugator c293ef302434504a 40 0 +OccurrenceDefinition ownedConnection dbf1f11f19410665 40 7 +OccurrenceDefinition ownedConstraint 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedDifferencing 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedDisjoining 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedElement e64c72a7c259e9a1 40 19 +OccurrenceDefinition ownedEndFeature 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedEnumeration 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedFeature 9ce4b7ad9bb62e35 40 19 +OccurrenceDefinition ownedFeatureMembership eb5bc34d082d2425 40 19 +OccurrenceDefinition ownedFlow 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedImport 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedInterface 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedIntersecting 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedItem 5e89ae8b11576755 40 8 +OccurrenceDefinition ownedMember e64c72a7c259e9a1 40 19 +OccurrenceDefinition ownedMembership 4bd335da6555fd4e 40 19 +OccurrenceDefinition ownedMetadata 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedOccurrence b1bd7cb688e80965 40 10 +OccurrenceDefinition ownedPart 44709eda49718dd5 40 8 +OccurrenceDefinition ownedPort 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedReference 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedRelationship 9073ee1f40252483 40 40 +OccurrenceDefinition ownedRendering 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedRequirement 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedSpecialization 2fd90c9f4714ede5 40 40 +OccurrenceDefinition ownedState 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedSubclassification 2fd90c9f4714ede5 40 40 +OccurrenceDefinition ownedTransition 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedUnioning 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedUsage 9ce4b7ad9bb62e35 40 19 +OccurrenceDefinition ownedUseCase 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedVerificationCase 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedView 2440ae8a9a25448e 40 0 +OccurrenceDefinition ownedViewpoint 2440ae8a9a25448e 40 0 +OccurrenceDefinition owner fd3349fc7268346f 40 40 +OccurrenceDefinition owningMembership 7249034ea46bc555 40 40 +OccurrenceDefinition owningNamespace fd3349fc7268346f 40 40 +OccurrenceDefinition owningRelationship 7249034ea46bc555 40 40 +OccurrenceDefinition qualifiedName def64b40ef211261 40 40 +OccurrenceDefinition shortName c293ef302434504a 40 0 +OccurrenceDefinition textualRepresentation 2440ae8a9a25448e 40 0 +OccurrenceDefinition unioningType 2440ae8a9a25448e 40 0 +OccurrenceDefinition usage 9ce4b7ad9bb62e35 40 19 +OccurrenceDefinition variant 2440ae8a9a25448e 40 0 +OccurrenceDefinition variantMembership 2440ae8a9a25448e 40 0 +OccurrenceUsage aliasIds 7e900f60cfb83537 113 0 +OccurrenceUsage chainingFeature 7e900f60cfb83537 113 0 +OccurrenceUsage crossFeature 7f79ce2c604b7372 113 0 +OccurrenceUsage declaredName 1d5508fbaf423b54 113 93 +OccurrenceUsage declaredShortName 7f79ce2c604b7372 113 0 +OccurrenceUsage definition 1a333ea3057effcc 113 78 +OccurrenceUsage differencingType 7e900f60cfb83537 113 0 +OccurrenceUsage directedFeature 51761173c9402f9f 113 1 +OccurrenceUsage directedUsage 51761173c9402f9f 113 1 +OccurrenceUsage direction 8f0c816697b0dc42 113 2 +OccurrenceUsage documentation c2c5174ef18cb0c2 113 8 +OccurrenceUsage elementId 6afeb69a0552bedc 113 113 +OccurrenceUsage endFeature 7e900f60cfb83537 113 0 +OccurrenceUsage endOwningType 7f79ce2c604b7372 113 0 +OccurrenceUsage feature 04e9b7eed33d7920 113 67 +OccurrenceUsage featureMembership 88f7d73c60f18fc1 113 67 +OccurrenceUsage featureTarget 3eb2140487c4a6b7 113 0 +OccurrenceUsage featuringType 7e900f60cfb83537 113 0 +OccurrenceUsage importedMembership 7e900f60cfb83537 113 0 +OccurrenceUsage individualDefinition 848d99f96042bc52 113 46 +OccurrenceUsage inheritedFeature 7e900f60cfb83537 113 0 +OccurrenceUsage inheritedMembership 7e900f60cfb83537 113 0 +OccurrenceUsage input 7e900f60cfb83537 113 0 +OccurrenceUsage intersectingType 7e900f60cfb83537 113 0 +OccurrenceUsage isAbstract 393926c48f57342d 113 7 +OccurrenceUsage isComposite 194a560e53c1bb0e 113 84 +OccurrenceUsage isConjugated 3add13fc6f651c62 113 0 +OccurrenceUsage isConstant 3add13fc6f651c62 113 0 +OccurrenceUsage isDerived 3add13fc6f651c62 113 0 +OccurrenceUsage isEnd 3add13fc6f651c62 113 0 +OccurrenceUsage isImpliedIncluded b1631afe3fcedabf 113 113 +OccurrenceUsage isIndividual 86b03d97e14c9859 113 19 +OccurrenceUsage isLibraryElement af72603aba96a40b 113 13 +OccurrenceUsage isOrdered 411db72b02410847 113 1 +OccurrenceUsage isPortion 7f79ce2c604b7372 113 0 +OccurrenceUsage isReference d2f5d8ec5b723c13 113 29 +OccurrenceUsage isSufficient 7f79ce2c604b7372 113 0 +OccurrenceUsage isUnique 48fbc807c3c9fbba 113 104 +OccurrenceUsage isVariable 7f79ce2c604b7372 113 0 +OccurrenceUsage isVariation 3add13fc6f651c62 113 0 +OccurrenceUsage mayTimeVary 7f79ce2c604b7372 113 0 +OccurrenceUsage member 1434315939cba6cb 113 82 +OccurrenceUsage membership 4cf2c0cc80164345 113 82 +OccurrenceUsage multiplicity 9dca5481f252db3c 113 12 +OccurrenceUsage name ecb3abf919bc27b9 113 112 +OccurrenceUsage nestedAction b9b45b99e52c87b8 113 7 +OccurrenceUsage nestedAllocation 7e900f60cfb83537 113 0 +OccurrenceUsage nestedAnalysisCase 7e900f60cfb83537 113 0 +OccurrenceUsage nestedAttribute 6b145da8fb66e28e 113 6 +OccurrenceUsage nestedCalculation 7e900f60cfb83537 113 0 +OccurrenceUsage nestedCase 7e900f60cfb83537 113 0 +OccurrenceUsage nestedConcern 7e900f60cfb83537 113 0 +OccurrenceUsage nestedConnection 55b443421c212b9c 113 5 +OccurrenceUsage nestedConstraint 7e900f60cfb83537 113 0 +OccurrenceUsage nestedEnumeration 7e900f60cfb83537 113 0 +OccurrenceUsage nestedFlow 7e900f60cfb83537 113 0 +OccurrenceUsage nestedInterface a92589b4ee6a8cb3 113 30 +OccurrenceUsage nestedItem aa122b46fe182a43 113 10 +OccurrenceUsage nestedMetadata 7e900f60cfb83537 113 0 +OccurrenceUsage nestedOccurrence 8ea67f44becca1c4 113 44 +OccurrenceUsage nestedPart 6b7717da4dd80005 113 4 +OccurrenceUsage nestedPort 7e900f60cfb83537 113 0 +OccurrenceUsage nestedReference a92589b4ee6a8cb3 113 30 +OccurrenceUsage nestedRendering 7e900f60cfb83537 113 0 +OccurrenceUsage nestedRequirement 7e900f60cfb83537 113 0 +OccurrenceUsage nestedState 4cb1af492b7f624b 113 3 +OccurrenceUsage nestedTransition 7e900f60cfb83537 113 0 +OccurrenceUsage nestedUsage 04e9b7eed33d7920 113 67 +OccurrenceUsage nestedUseCase 7e900f60cfb83537 113 0 +OccurrenceUsage nestedVerificationCase 7e900f60cfb83537 113 0 +OccurrenceUsage nestedView 7e900f60cfb83537 113 0 +OccurrenceUsage nestedViewpoint 7e900f60cfb83537 113 0 +OccurrenceUsage occurrenceDefinition 6937c5aedd2072b5 113 78 +OccurrenceUsage output 51761173c9402f9f 113 1 +OccurrenceUsage ownedAnnotation 7e900f60cfb83537 113 0 +OccurrenceUsage ownedConjugator 7f79ce2c604b7372 113 0 +OccurrenceUsage ownedCrossSubsetting 7f79ce2c604b7372 113 0 +OccurrenceUsage ownedDifferencing 7e900f60cfb83537 113 0 +OccurrenceUsage ownedDisjoining 7e900f60cfb83537 113 0 +OccurrenceUsage ownedElement dbd35b96ec282cb0 113 82 +OccurrenceUsage ownedEndFeature 7e900f60cfb83537 113 0 +OccurrenceUsage ownedFeature 04e9b7eed33d7920 113 67 +OccurrenceUsage ownedFeatureChaining 7e900f60cfb83537 113 0 +OccurrenceUsage ownedFeatureInverting 7e900f60cfb83537 113 0 +OccurrenceUsage ownedFeatureMembership 88f7d73c60f18fc1 113 67 +OccurrenceUsage ownedImport 7e900f60cfb83537 113 0 +OccurrenceUsage ownedIntersecting 7e900f60cfb83537 113 0 +OccurrenceUsage ownedMember 1434315939cba6cb 113 82 +OccurrenceUsage ownedMembership 4cf2c0cc80164345 113 82 +OccurrenceUsage ownedRedefinition 5884d28d612b33b4 113 25 +OccurrenceUsage ownedReferenceSubsetting 7f79ce2c604b7372 113 0 +OccurrenceUsage ownedRelationship e4358f73d6aaec56 113 113 +OccurrenceUsage ownedSpecialization 88069c3a9b9a7f64 113 113 +OccurrenceUsage ownedSubsetting 6c6cf08c7bc94c04 113 113 +OccurrenceUsage ownedTypeFeaturing 7e900f60cfb83537 113 0 +OccurrenceUsage ownedTyping 39fb6db8c3646dc7 113 61 +OccurrenceUsage ownedUnioning 7e900f60cfb83537 113 0 +OccurrenceUsage owner 92b5d1b76602fcf4 113 113 +OccurrenceUsage owningDefinition 51203af280b1a396 113 26 +OccurrenceUsage owningFeatureMembership 1e03ff2c0648c1c1 113 90 +OccurrenceUsage owningMembership bcf220a5e4199f28 113 113 +OccurrenceUsage owningNamespace 92b5d1b76602fcf4 113 113 +OccurrenceUsage owningRelationship bcf220a5e4199f28 113 113 +OccurrenceUsage owningType fd2636cf945a8d7e 113 90 +OccurrenceUsage owningUsage 2b7fca0973f45d5a 113 64 +OccurrenceUsage portionKind 1ae4f626bd944795 113 64 +OccurrenceUsage qualifiedName 10b9df3de9e5dc36 113 108 +OccurrenceUsage shortName 7f79ce2c604b7372 113 0 +OccurrenceUsage textualRepresentation 7e900f60cfb83537 113 0 +OccurrenceUsage type 1a333ea3057effcc 113 78 +OccurrenceUsage unioningType 7e900f60cfb83537 113 0 +OccurrenceUsage usage 04e9b7eed33d7920 113 67 +OccurrenceUsage variant 7e900f60cfb83537 113 0 +OccurrenceUsage variantMembership 7e900f60cfb83537 113 0 +OperatorExpression aliasIds 0e965a577af286a9 931 0 +OperatorExpression argument 505693806f759c60 931 930 +OperatorExpression behavior 0e965a577af286a9 931 0 +OperatorExpression chainingFeature 0e965a577af286a9 931 0 +OperatorExpression crossFeature c55b67f7dff0d016 931 0 +OperatorExpression declaredName c55b67f7dff0d016 931 0 +OperatorExpression declaredShortName c55b67f7dff0d016 931 0 +OperatorExpression differencingType 0e965a577af286a9 931 0 +OperatorExpression directedFeature 729bf7be46a6af3b 931 931 +OperatorExpression direction c55b67f7dff0d016 931 0 +OperatorExpression documentation 0e965a577af286a9 931 0 +OperatorExpression elementId 95e21e88e2f9a058 931 931 +OperatorExpression endFeature 0e965a577af286a9 931 0 +OperatorExpression endOwningType c55b67f7dff0d016 931 0 +OperatorExpression feature 729bf7be46a6af3b 931 931 +OperatorExpression featureMembership 803fdde61e604daf 931 931 +OperatorExpression featureTarget 3cd90ffd2b5bae19 931 0 +OperatorExpression featuringType 0e965a577af286a9 931 0 +OperatorExpression function c55b67f7dff0d016 931 0 +OperatorExpression importedMembership 0e965a577af286a9 931 0 +OperatorExpression inheritedFeature 0e965a577af286a9 931 0 +OperatorExpression inheritedMembership 0e965a577af286a9 931 0 +OperatorExpression input 3945d5b868c02bf5 931 930 +OperatorExpression instantiatedType e541d3aa736e6d07 931 931 +OperatorExpression intersectingType 0e965a577af286a9 931 0 +OperatorExpression isAbstract c55b67f7dff0d016 931 0 +OperatorExpression isComposite c55b67f7dff0d016 931 0 +OperatorExpression isConjugated f9193a67c434b5da 931 0 +OperatorExpression isConstant c55b67f7dff0d016 931 0 +OperatorExpression isDerived c55b67f7dff0d016 931 0 +OperatorExpression isEnd c55b67f7dff0d016 931 0 +OperatorExpression isImpliedIncluded 3f1db5763953c0d1 931 931 +OperatorExpression isLibraryElement 1b817acfde253415 931 23 +OperatorExpression isModelLevelEvaluable a63894d1973721c9 931 403 +OperatorExpression isOrdered c55b67f7dff0d016 931 0 +OperatorExpression isPortion c55b67f7dff0d016 931 0 +OperatorExpression isSufficient c55b67f7dff0d016 931 0 +OperatorExpression isUnique c55b67f7dff0d016 931 0 +OperatorExpression isVariable c55b67f7dff0d016 931 0 +OperatorExpression member 729bf7be46a6af3b 931 931 +OperatorExpression membership 803fdde61e604daf 931 931 +OperatorExpression multiplicity c55b67f7dff0d016 931 0 +OperatorExpression name c55b67f7dff0d016 931 0 +OperatorExpression operator fb79d89612d1bb57 931 931 +OperatorExpression output ea55a66c994311bb 931 39 +OperatorExpression ownedAnnotation 0e965a577af286a9 931 0 +OperatorExpression ownedConjugator c55b67f7dff0d016 931 0 +OperatorExpression ownedCrossSubsetting c55b67f7dff0d016 931 0 +OperatorExpression ownedDifferencing 0e965a577af286a9 931 0 +OperatorExpression ownedDisjoining 0e965a577af286a9 931 0 +OperatorExpression ownedElement 729bf7be46a6af3b 931 931 +OperatorExpression ownedEndFeature 0e965a577af286a9 931 0 +OperatorExpression ownedFeature 729bf7be46a6af3b 931 931 +OperatorExpression ownedFeatureChaining 0e965a577af286a9 931 0 +OperatorExpression ownedFeatureInverting 0e965a577af286a9 931 0 +OperatorExpression ownedFeatureMembership 803fdde61e604daf 931 931 +OperatorExpression ownedImport 0e965a577af286a9 931 0 +OperatorExpression ownedIntersecting 0e965a577af286a9 931 0 +OperatorExpression ownedMember 729bf7be46a6af3b 931 931 +OperatorExpression ownedMembership 803fdde61e604daf 931 931 +OperatorExpression ownedRedefinition 0e965a577af286a9 931 0 +OperatorExpression ownedReferenceSubsetting c55b67f7dff0d016 931 0 +OperatorExpression ownedRelationship 803fdde61e604daf 931 931 +OperatorExpression ownedSpecialization 0e965a577af286a9 931 0 +OperatorExpression ownedSubsetting 0e965a577af286a9 931 0 +OperatorExpression ownedTypeFeaturing 0e965a577af286a9 931 0 +OperatorExpression ownedTyping 0e965a577af286a9 931 0 +OperatorExpression ownedUnioning 0e965a577af286a9 931 0 +OperatorExpression owner 16f6b92df0a5c47b 931 931 +OperatorExpression owningFeatureMembership 6e5422dd60e9d7e6 931 110 +OperatorExpression owningMembership c9a7a73556fea81f 931 931 +OperatorExpression owningNamespace 16f6b92df0a5c47b 931 931 +OperatorExpression owningRelationship c9a7a73556fea81f 931 931 +OperatorExpression owningType 184c094fbdae7f4e 931 110 +OperatorExpression parameter 729bf7be46a6af3b 931 931 +OperatorExpression qualifiedName c55b67f7dff0d016 931 0 +OperatorExpression result 711ca624ba9a9560 931 39 +OperatorExpression shortName c55b67f7dff0d016 931 0 +OperatorExpression textualRepresentation 0e965a577af286a9 931 0 +OperatorExpression type 0e965a577af286a9 931 0 +OperatorExpression unioningType 0e965a577af286a9 931 0 +OwningMembership aliasIds 2325a113fc80714e 4567 0 +OwningMembership declaredName 57a73d82414f132d 4567 0 +OwningMembership declaredShortName 57a73d82414f132d 4567 0 +OwningMembership documentation 2325a113fc80714e 4567 0 +OwningMembership elementId cd60b6c740d85f94 4567 4567 +OwningMembership isImplied 92acf88fe348bf57 4567 0 +OwningMembership isImpliedIncluded b115fc6959646cb2 4567 4567 +OwningMembership isLibraryElement 8220fa21e8f944f9 4567 202 +OwningMembership memberElement 9555d613492e87b2 4567 4567 +OwningMembership memberElementId cf951ef8b6c394eb 4567 4567 +OwningMembership memberName b0ba9349c5d361b2 4567 2509 +OwningMembership memberShortName d91a85a6c1800a21 4567 45 +OwningMembership membershipOwningNamespace d025b40c99c7672d 4567 4567 +OwningMembership name 57a73d82414f132d 4567 0 +OwningMembership ownedAnnotation 2325a113fc80714e 4567 0 +OwningMembership ownedElement 2325a113fc80714e 4567 0 +OwningMembership ownedMemberElement 9555d613492e87b2 4567 4567 +OwningMembership ownedMemberElementId cf951ef8b6c394eb 4567 4567 +OwningMembership ownedMemberName b0ba9349c5d361b2 4567 2509 +OwningMembership ownedMemberShortName d91a85a6c1800a21 4567 45 +OwningMembership ownedRelatedElement 4508cd9e2e1b8d9a 4567 4567 +OwningMembership ownedRelationship 2325a113fc80714e 4567 0 +OwningMembership owner 57a73d82414f132d 4567 0 +OwningMembership owningMembership 57a73d82414f132d 4567 0 +OwningMembership owningNamespace 57a73d82414f132d 4567 0 +OwningMembership owningRelatedElement d025b40c99c7672d 4567 4567 +OwningMembership owningRelationship 57a73d82414f132d 4567 0 +OwningMembership qualifiedName 57a73d82414f132d 4567 0 +OwningMembership relatedElement 3f3d562c6052500f 4567 4567 +OwningMembership shortName 57a73d82414f132d 4567 0 +OwningMembership source 771a6ec19e69b77b 4567 4567 +OwningMembership target 4508cd9e2e1b8d9a 4567 4567 +OwningMembership textualRepresentation 2325a113fc80714e 4567 0 +OwningMembership visibility 50b00c2f3b935f7d 4567 3798 +Package aliasIds 2217fc747ddc9e04 473 0 +Package declaredName 7a374c3e3ae3808b 473 463 +Package declaredShortName 74a917432c024721 473 0 +Package documentation 706284d00e142da8 473 14 +Package elementId 7b198af4ae31408c 473 473 +Package filterCondition bfe9a6236df86290 473 20 +Package importedMembership 2217fc747ddc9e04 473 0 +Package isImpliedIncluded e0ed46019e00ba70 473 473 +Package isLibraryElement 20fa4ecadbf9ba1b 473 0 +Package member dc5de8cf2d0d30af 473 457 +Package membership e18d544c3a79bb22 473 457 +Package name 7a374c3e3ae3808b 473 463 +Package ownedAnnotation 2217fc747ddc9e04 473 0 +Package ownedElement f2fa21c5dca6deda 473 456 +Package ownedImport 9515d2426cab42ad 473 254 +Package ownedMember a05409a4a7271928 473 456 +Package ownedMembership e18d544c3a79bb22 473 457 +Package ownedRelationship 68219c1c2bcdc173 473 462 +Package owner 628d36a4236c1177 473 473 +Package owningMembership b3b79a51091c4a95 473 463 +Package owningNamespace 577e60c6548e5fa9 473 463 +Package owningRelationship bd4bf086e349acb7 473 473 +Package qualifiedName bba42356e16d41e7 473 463 +Package shortName 74a917432c024721 473 0 +Package textualRepresentation 2217fc747ddc9e04 473 0 +ParameterMembership aliasIds 20fb09fdfcf0b4e1 3104 0 +ParameterMembership declaredName b14524a63016df07 3104 0 +ParameterMembership declaredShortName b14524a63016df07 3104 0 +ParameterMembership documentation 20fb09fdfcf0b4e1 3104 0 +ParameterMembership elementId 0943963b05dc7c30 3104 3104 +ParameterMembership isImplied b8f82c5a68662bc5 3104 0 +ParameterMembership isImpliedIncluded a360c09df49c6255 3104 3104 +ParameterMembership isLibraryElement 93aca2db78047438 3104 23 +ParameterMembership memberElement 4362c0c8cba71811 3104 3104 +ParameterMembership memberElementId 665a788822ff273f 3104 3104 +ParameterMembership memberName 8100886aa344dc4e 3104 280 +ParameterMembership memberShortName b14524a63016df07 3104 0 +ParameterMembership membershipOwningNamespace 1f8f41e5ca9c1978 3104 3104 +ParameterMembership name b14524a63016df07 3104 0 +ParameterMembership ownedAnnotation 20fb09fdfcf0b4e1 3104 0 +ParameterMembership ownedElement 20fb09fdfcf0b4e1 3104 0 +ParameterMembership ownedMemberElement 4362c0c8cba71811 3104 3104 +ParameterMembership ownedMemberElementId 665a788822ff273f 3104 3104 +ParameterMembership ownedMemberFeature 4362c0c8cba71811 3104 3104 +ParameterMembership ownedMemberName fda411b9e1f2fd76 3104 338 +ParameterMembership ownedMemberParameter 4362c0c8cba71811 3104 3104 +ParameterMembership ownedMemberShortName b14524a63016df07 3104 0 +ParameterMembership ownedRelatedElement 3a26825f9315d679 3104 3104 +ParameterMembership ownedRelationship 20fb09fdfcf0b4e1 3104 0 +ParameterMembership owner b14524a63016df07 3104 0 +ParameterMembership owningMembership b14524a63016df07 3104 0 +ParameterMembership owningNamespace b14524a63016df07 3104 0 +ParameterMembership owningRelatedElement 1f8f41e5ca9c1978 3104 3104 +ParameterMembership owningRelationship b14524a63016df07 3104 0 +ParameterMembership owningType 1f8f41e5ca9c1978 3104 3104 +ParameterMembership qualifiedName b14524a63016df07 3104 0 +ParameterMembership relatedElement 4009e0f6c181b012 3104 3104 +ParameterMembership shortName b14524a63016df07 3104 0 +ParameterMembership source 7def3d251b478526 3104 3104 +ParameterMembership target 3a26825f9315d679 3104 3104 +ParameterMembership textualRepresentation 20fb09fdfcf0b4e1 3104 0 +ParameterMembership visibility 89275c136e52c99f 3104 2444 +PartDefinition aliasIds 9c77a1738aa587dd 501 0 +PartDefinition declaredName 84a01a7ae7ceb3e0 501 501 +PartDefinition declaredShortName 7181cd23aae50299 501 1 +PartDefinition differencingType 9c77a1738aa587dd 501 0 +PartDefinition directedFeature 87825239ddad3534 501 2 +PartDefinition directedUsage 87825239ddad3534 501 2 +PartDefinition documentation 602cf01f5fcff8a6 501 14 +PartDefinition elementId 3f37a2867fb0f8a0 501 501 +PartDefinition endFeature 9c77a1738aa587dd 501 0 +PartDefinition feature 2a212e3423fee9d6 501 219 +PartDefinition featureMembership 14ef076b6f9db76c 501 219 +PartDefinition importedMembership 9c77a1738aa587dd 501 0 +PartDefinition inheritedFeature 9c77a1738aa587dd 501 0 +PartDefinition inheritedMembership 9c77a1738aa587dd 501 0 +PartDefinition input 71d8be0fddfb9679 501 1 +PartDefinition intersectingType 9c77a1738aa587dd 501 0 +PartDefinition isAbstract 79c0f5f4a46e2b46 501 10 +PartDefinition isConjugated 312b6839aa16ab54 501 0 +PartDefinition isImpliedIncluded 0169eca0f40cd49d 501 501 +PartDefinition isIndividual 54c60b3734d74904 501 12 +PartDefinition isLibraryElement 39403c441589cd9a 501 6 +PartDefinition isSufficient 312b6839aa16ab54 501 0 +PartDefinition isVariation 8ff23b270ab06b68 501 4 +PartDefinition member daa6e4bd9befcc99 501 228 +PartDefinition membership b79e76c9c2d3e69c 501 228 +PartDefinition multiplicity f1c6e9ab3417dd14 501 0 +PartDefinition name 84a01a7ae7ceb3e0 501 501 +PartDefinition output b221359d8a572698 501 1 +PartDefinition ownedAction 425e542093a50bba 501 30 +PartDefinition ownedAllocation 9c77a1738aa587dd 501 0 +PartDefinition ownedAnalysisCase 9c77a1738aa587dd 501 0 +PartDefinition ownedAnnotation 9c77a1738aa587dd 501 0 +PartDefinition ownedAttribute 75b37578e86ed0fc 501 97 +PartDefinition ownedCalculation dbf74ba732b18737 501 1 +PartDefinition ownedCase 9c77a1738aa587dd 501 0 +PartDefinition ownedConcern 9c77a1738aa587dd 501 0 +PartDefinition ownedConjugator f1c6e9ab3417dd14 501 0 +PartDefinition ownedConnection c062d8465f278886 501 8 +PartDefinition ownedConstraint d74fa9efa0682ead 501 14 +PartDefinition ownedDifferencing 9c77a1738aa587dd 501 0 +PartDefinition ownedDisjoining 9c77a1738aa587dd 501 0 +PartDefinition ownedElement 772c2f13f7f9d032 501 228 +PartDefinition ownedEndFeature 9c77a1738aa587dd 501 0 +PartDefinition ownedEnumeration 9c77a1738aa587dd 501 0 +PartDefinition ownedFeature 2a212e3423fee9d6 501 219 +PartDefinition ownedFeatureMembership 14ef076b6f9db76c 501 219 +PartDefinition ownedFlow 9c77a1738aa587dd 501 0 +PartDefinition ownedImport 625b8d8cde16e9d4 501 2 +PartDefinition ownedInterface 16762b1b1a71d18e 501 26 +PartDefinition ownedIntersecting 9c77a1738aa587dd 501 0 +PartDefinition ownedItem e1c5ec2382a2c5ec 501 74 +PartDefinition ownedMember 772c2f13f7f9d032 501 228 +PartDefinition ownedMembership b79e76c9c2d3e69c 501 228 +PartDefinition ownedMetadata 9c77a1738aa587dd 501 0 +PartDefinition ownedOccurrence 66ed6b3ebb5bc37a 501 138 +PartDefinition ownedPart c87b83fdc1d661e1 501 69 +PartDefinition ownedPort eebe36c173fa4b92 501 51 +PartDefinition ownedReference 16762b1b1a71d18e 501 26 +PartDefinition ownedRelationship f9c87fdba988cb3c 501 501 +PartDefinition ownedRendering 9c77a1738aa587dd 501 0 +PartDefinition ownedRequirement 9c77a1738aa587dd 501 0 +PartDefinition ownedSpecialization aadc8047c68c31bc 501 501 +PartDefinition ownedState 93e3695f48bf2377 501 15 +PartDefinition ownedSubclassification aadc8047c68c31bc 501 501 +PartDefinition ownedTransition 9c77a1738aa587dd 501 0 +PartDefinition ownedUnioning 9c77a1738aa587dd 501 0 +PartDefinition ownedUsage 2a212e3423fee9d6 501 219 +PartDefinition ownedUseCase 9c77a1738aa587dd 501 0 +PartDefinition ownedVerificationCase 9c77a1738aa587dd 501 0 +PartDefinition ownedView 9c77a1738aa587dd 501 0 +PartDefinition ownedViewpoint 9c77a1738aa587dd 501 0 +PartDefinition owner 209aa5d9b58441da 501 501 +PartDefinition owningMembership 06e4add15e7c1730 501 501 +PartDefinition owningNamespace 209aa5d9b58441da 501 501 +PartDefinition owningRelationship 06e4add15e7c1730 501 501 +PartDefinition qualifiedName 57813f1ca225bf1d 501 501 +PartDefinition shortName 7181cd23aae50299 501 1 +PartDefinition textualRepresentation 9c77a1738aa587dd 501 0 +PartDefinition unioningType 9c77a1738aa587dd 501 0 +PartDefinition usage 2a212e3423fee9d6 501 219 +PartDefinition variant 14d0e96e4f9bddf8 501 4 +PartDefinition variantMembership 1d6259f5fa933bd1 501 4 +PartUsage aliasIds 4db41e2874afe6bd 1083 0 +PartUsage chainingFeature 4db41e2874afe6bd 1083 0 +PartUsage crossFeature 9526d1ebaa6b1526 1083 0 +PartUsage declaredName 28f035b7d0972ede 1083 925 +PartUsage declaredShortName cfebcc30956ca5f6 1083 1 +PartUsage definition 3976896771655cc4 1083 731 +PartUsage differencingType 4db41e2874afe6bd 1083 0 +PartUsage directedFeature 3456b4d2276c18b0 1083 6 +PartUsage directedUsage 3456b4d2276c18b0 1083 6 +PartUsage direction 43f71700a48420bd 1083 64 +PartUsage documentation b014c311c6fcf5ae 1083 8 +PartUsage elementId 386f6242ad0ef03c 1083 1083 +PartUsage endFeature 4db41e2874afe6bd 1083 0 +PartUsage endOwningType d7eb527bef0c2fb0 1083 2 +PartUsage feature 4dfb2573949a60ea 1083 554 +PartUsage featureMembership 82f9458f5bf2f89c 1083 554 +PartUsage featureTarget cc7b8cb4f8cb27a9 1083 0 +PartUsage featuringType 4db41e2874afe6bd 1083 0 +PartUsage importedMembership 4db41e2874afe6bd 1083 0 +PartUsage individualDefinition b07bd83a545062f4 1083 6 +PartUsage inheritedFeature 4db41e2874afe6bd 1083 0 +PartUsage inheritedMembership 4db41e2874afe6bd 1083 0 +PartUsage input 0f266b30b79d3e45 1083 6 +PartUsage intersectingType 4db41e2874afe6bd 1083 0 +PartUsage isAbstract b49fecd1ca4bf1be 1083 24 +PartUsage isComposite c1c742630dc06e96 1083 704 +PartUsage isConjugated 60b4d6c1d2c45ace 1083 0 +PartUsage isConstant 9d2170c4e70f10a8 1083 2 +PartUsage isDerived 60b4d6c1d2c45ace 1083 0 +PartUsage isEnd 9d2170c4e70f10a8 1083 2 +PartUsage isImpliedIncluded a98e49541f2e084d 1083 1083 +PartUsage isIndividual 02052547ec8659fc 1083 6 +PartUsage isLibraryElement e058b3abe40ca521 1083 7 +PartUsage isOrdered c8a78db4399dd256 1083 8 +PartUsage isPortion 9526d1ebaa6b1526 1083 0 +PartUsage isReference 487bddb2e431f485 1083 379 +PartUsage isSufficient 9526d1ebaa6b1526 1083 0 +PartUsage isUnique a98e49541f2e084d 1083 1083 +PartUsage isVariable 116c067429bc7e90 1083 2 +PartUsage isVariation 946bf826f01036e4 1083 14 +PartUsage itemDefinition d633d180c1e79a47 1083 731 +PartUsage mayTimeVary 116c067429bc7e90 1083 2 +PartUsage member 369e5f6378e834d5 1083 805 +PartUsage membership f513c98e97e208c2 1083 805 +PartUsage multiplicity 8622706f03b7eaa6 1083 222 +PartUsage name a9ff6e66ff752cb2 1083 1081 +PartUsage nestedAction e136c8e8c9af147d 1083 114 +PartUsage nestedAllocation 0177a4f3b6f2f8c1 1083 2 +PartUsage nestedAnalysisCase cc217c0abb26a04a 1083 7 +PartUsage nestedAttribute b541e8e39f880554 1083 125 +PartUsage nestedCalculation e9151eb165afefef 1083 10 +PartUsage nestedCase 78a31d1f6991cd7b 1083 9 +PartUsage nestedConcern 4db41e2874afe6bd 1083 0 +PartUsage nestedConnection 8186dda48908d005 1083 79 +PartUsage nestedConstraint 65b75ed3c73bfa90 1083 28 +PartUsage nestedEnumeration 4db41e2874afe6bd 1083 0 +PartUsage nestedFlow 4db41e2874afe6bd 1083 0 +PartUsage nestedInterface 3b29f30e912ef301 1083 31 +PartUsage nestedItem 081f7c8a1f628663 1083 298 +PartUsage nestedMetadata 4db41e2874afe6bd 1083 0 +PartUsage nestedOccurrence 9a955fe98f6a303a 1083 476 +PartUsage nestedPart 3ed66e26ec3eb955 1083 274 +PartUsage nestedPort 0bea72864bfef0b2 1083 96 +PartUsage nestedReference 3b29f30e912ef301 1083 31 +PartUsage nestedRendering 4db41e2874afe6bd 1083 0 +PartUsage nestedRequirement 2f5a996b3ef49823 1083 13 +PartUsage nestedState f916d9882bef759b 1083 13 +PartUsage nestedTransition 4db41e2874afe6bd 1083 0 +PartUsage nestedUsage 4dfb2573949a60ea 1083 554 +PartUsage nestedUseCase 67bd5634e0e74610 1083 1 +PartUsage nestedVerificationCase e02c8730b6e3b49b 1083 1 +PartUsage nestedView 4db41e2874afe6bd 1083 0 +PartUsage nestedViewpoint 4db41e2874afe6bd 1083 0 +PartUsage occurrenceDefinition f71fe191856121d1 1083 731 +PartUsage output ab1f8ae3695e8348 1083 6 +PartUsage ownedAnnotation 4db41e2874afe6bd 1083 0 +PartUsage ownedConjugator 9526d1ebaa6b1526 1083 0 +PartUsage ownedCrossSubsetting 9526d1ebaa6b1526 1083 0 +PartUsage ownedDifferencing 4db41e2874afe6bd 1083 0 +PartUsage ownedDisjoining 4db41e2874afe6bd 1083 0 +PartUsage ownedElement 0088c024127b8e99 1083 805 +PartUsage ownedEndFeature 4db41e2874afe6bd 1083 0 +PartUsage ownedFeature 4dfb2573949a60ea 1083 554 +PartUsage ownedFeatureChaining 4db41e2874afe6bd 1083 0 +PartUsage ownedFeatureInverting 4db41e2874afe6bd 1083 0 +PartUsage ownedFeatureMembership 82f9458f5bf2f89c 1083 554 +PartUsage ownedImport dcb52109b1747e03 1083 3 +PartUsage ownedIntersecting 4db41e2874afe6bd 1083 0 +PartUsage ownedMember e6e3ddfe397de358 1083 805 +PartUsage ownedMembership f513c98e97e208c2 1083 805 +PartUsage ownedRedefinition b265df4f01100d25 1083 182 +PartUsage ownedReferenceSubsetting 9526d1ebaa6b1526 1083 0 +PartUsage ownedRelationship 7c70c2c707f1fab4 1083 1083 +PartUsage ownedSpecialization ce970e61d622dd8d 1083 1083 +PartUsage ownedSubsetting f93aac4ace1119ae 1083 1083 +PartUsage ownedTypeFeaturing 4db41e2874afe6bd 1083 0 +PartUsage ownedTyping 3e4fc2e2622c418e 1083 538 +PartUsage ownedUnioning 4db41e2874afe6bd 1083 0 +PartUsage owner ffddb225eaebd5d6 1083 1083 +PartUsage owningDefinition 6fcd6536c0be6ef3 1083 158 +PartUsage owningFeatureMembership e21aaac9c3cbb05e 1083 775 +PartUsage owningMembership d81a7888ed5c52fe 1083 1083 +PartUsage owningNamespace ffddb225eaebd5d6 1083 1083 +PartUsage owningRelationship d81a7888ed5c52fe 1083 1083 +PartUsage owningType 700b1f5f75ecd928 1083 775 +PartUsage owningUsage 95648c145f997f5b 1083 617 +PartUsage partDefinition 4df14483ed8ec82c 1083 726 +PartUsage portionKind e2d67e0c72f41a62 1083 4 +PartUsage qualifiedName c658f0f745e7d799 1083 1078 +PartUsage shortName cfebcc30956ca5f6 1083 1 +PartUsage textualRepresentation 4db41e2874afe6bd 1083 0 +PartUsage type 3976896771655cc4 1083 731 +PartUsage unioningType 4db41e2874afe6bd 1083 0 +PartUsage usage 4dfb2573949a60ea 1083 554 +PartUsage variant c62a26347f850646 1083 14 +PartUsage variantMembership 7261ab67d6d61a3d 1083 14 +PayloadFeature aliasIds dd28ff24ddad4d13 48 0 +PayloadFeature chainingFeature dd28ff24ddad4d13 48 0 +PayloadFeature crossFeature 48330bffc17b72d1 48 0 +PayloadFeature declaredName 62d272130ddae978 48 6 +PayloadFeature declaredShortName 48330bffc17b72d1 48 0 +PayloadFeature differencingType dd28ff24ddad4d13 48 0 +PayloadFeature directedFeature dd28ff24ddad4d13 48 0 +PayloadFeature direction 48330bffc17b72d1 48 0 +PayloadFeature documentation dd28ff24ddad4d13 48 0 +PayloadFeature elementId 27ddfe905f5208b4 48 48 +PayloadFeature endFeature dd28ff24ddad4d13 48 0 +PayloadFeature endOwningType 48330bffc17b72d1 48 0 +PayloadFeature feature dd28ff24ddad4d13 48 0 +PayloadFeature featureMembership dd28ff24ddad4d13 48 0 +PayloadFeature featureTarget ad4862c945aaad92 48 0 +PayloadFeature featuringType dd28ff24ddad4d13 48 0 +PayloadFeature importedMembership dd28ff24ddad4d13 48 0 +PayloadFeature inheritedFeature dd28ff24ddad4d13 48 0 +PayloadFeature inheritedMembership dd28ff24ddad4d13 48 0 +PayloadFeature input dd28ff24ddad4d13 48 0 +PayloadFeature intersectingType dd28ff24ddad4d13 48 0 +PayloadFeature isAbstract 48330bffc17b72d1 48 0 +PayloadFeature isComposite 48330bffc17b72d1 48 0 +PayloadFeature isConjugated b0366a8bbd30cf27 48 0 +PayloadFeature isConstant 48330bffc17b72d1 48 0 +PayloadFeature isDerived 48330bffc17b72d1 48 0 +PayloadFeature isEnd 48330bffc17b72d1 48 0 +PayloadFeature isImpliedIncluded 36855aff8e9e0e07 48 48 +PayloadFeature isLibraryElement b0366a8bbd30cf27 48 0 +PayloadFeature isOrdered 48330bffc17b72d1 48 0 +PayloadFeature isPortion 48330bffc17b72d1 48 0 +PayloadFeature isSufficient 48330bffc17b72d1 48 0 +PayloadFeature isUnique 48330bffc17b72d1 48 0 +PayloadFeature isVariable 48330bffc17b72d1 48 0 +PayloadFeature member 90273a846b1c45a0 48 10 +PayloadFeature membership a1f3d64479f76941 48 10 +PayloadFeature multiplicity 1af1961bed861163 48 9 +PayloadFeature name 4cfa7793e06af92e 48 48 +PayloadFeature output dd28ff24ddad4d13 48 0 +PayloadFeature ownedAnnotation dd28ff24ddad4d13 48 0 +PayloadFeature ownedConjugator 48330bffc17b72d1 48 0 +PayloadFeature ownedCrossSubsetting 48330bffc17b72d1 48 0 +PayloadFeature ownedDifferencing dd28ff24ddad4d13 48 0 +PayloadFeature ownedDisjoining dd28ff24ddad4d13 48 0 +PayloadFeature ownedElement 90273a846b1c45a0 48 10 +PayloadFeature ownedEndFeature dd28ff24ddad4d13 48 0 +PayloadFeature ownedFeature dd28ff24ddad4d13 48 0 +PayloadFeature ownedFeatureChaining dd28ff24ddad4d13 48 0 +PayloadFeature ownedFeatureInverting dd28ff24ddad4d13 48 0 +PayloadFeature ownedFeatureMembership dd28ff24ddad4d13 48 0 +PayloadFeature ownedImport dd28ff24ddad4d13 48 0 +PayloadFeature ownedIntersecting dd28ff24ddad4d13 48 0 +PayloadFeature ownedMember 90273a846b1c45a0 48 10 +PayloadFeature ownedMembership a1f3d64479f76941 48 10 +PayloadFeature ownedRedefinition dd28ff24ddad4d13 48 0 +PayloadFeature ownedReferenceSubsetting 48330bffc17b72d1 48 0 +PayloadFeature ownedRelationship 3f33d7297555c1be 48 48 +PayloadFeature ownedSpecialization 407b4579272ea4da 48 48 +PayloadFeature ownedSubsetting dd28ff24ddad4d13 48 0 +PayloadFeature ownedTypeFeaturing dd28ff24ddad4d13 48 0 +PayloadFeature ownedTyping 407b4579272ea4da 48 48 +PayloadFeature ownedUnioning dd28ff24ddad4d13 48 0 +PayloadFeature owner db44ca11e90f0217 48 48 +PayloadFeature owningFeatureMembership 36e10c917e23b442 48 48 +PayloadFeature owningMembership 36e10c917e23b442 48 48 +PayloadFeature owningNamespace db44ca11e90f0217 48 48 +PayloadFeature owningRelationship 36e10c917e23b442 48 48 +PayloadFeature owningType db44ca11e90f0217 48 48 +PayloadFeature qualifiedName 887a05fe2afb273a 48 37 +PayloadFeature shortName 48330bffc17b72d1 48 0 +PayloadFeature textualRepresentation dd28ff24ddad4d13 48 0 +PayloadFeature type 2e3d7e6c7453ecb9 48 48 +PayloadFeature unioningType dd28ff24ddad4d13 48 0 +PerformActionUsage actionDefinition f46eaaea37765a1b 153 59 +PerformActionUsage aliasIds 240b0155f6d100c0 153 0 +PerformActionUsage behavior f46eaaea37765a1b 153 59 +PerformActionUsage chainingFeature 240b0155f6d100c0 153 0 +PerformActionUsage crossFeature 0fba2e9807953621 153 0 +PerformActionUsage declaredName 24cdcb6d6b5276cf 153 51 +PerformActionUsage declaredShortName 0fba2e9807953621 153 0 +PerformActionUsage definition f46eaaea37765a1b 153 59 +PerformActionUsage differencingType 240b0155f6d100c0 153 0 +PerformActionUsage directedFeature 8abbc347b49fb008 153 25 +PerformActionUsage directedUsage 8abbc347b49fb008 153 25 +PerformActionUsage direction 0fba2e9807953621 153 0 +PerformActionUsage documentation 0ef8b9ae9feb66d9 153 4 +PerformActionUsage elementId 955d9f24f38b87b8 153 153 +PerformActionUsage endFeature 240b0155f6d100c0 153 0 +PerformActionUsage endOwningType 0fba2e9807953621 153 0 +PerformActionUsage eventOccurrence 02c706c75ec61168 153 96 +PerformActionUsage feature 2e8f856a3b00f91c 153 40 +PerformActionUsage featureMembership 6d81a8c87e33c73c 153 40 +PerformActionUsage featureTarget b6308601882d85e5 153 0 +PerformActionUsage featuringType 240b0155f6d100c0 153 0 +PerformActionUsage importedMembership 240b0155f6d100c0 153 0 +PerformActionUsage individualDefinition 0fba2e9807953621 153 0 +PerformActionUsage inheritedFeature 240b0155f6d100c0 153 0 +PerformActionUsage inheritedMembership 240b0155f6d100c0 153 0 +PerformActionUsage input 15161493621878c9 153 20 +PerformActionUsage intersectingType 240b0155f6d100c0 153 0 +PerformActionUsage isAbstract f67e936d5f55da1c 153 1 +PerformActionUsage isComposite 5ad8aa497247c997 153 0 +PerformActionUsage isConjugated 5ad8aa497247c997 153 0 +PerformActionUsage isConstant 5ad8aa497247c997 153 0 +PerformActionUsage isDerived 5ad8aa497247c997 153 0 +PerformActionUsage isEnd 5ad8aa497247c997 153 0 +PerformActionUsage isImpliedIncluded fef814ed260a0b34 153 153 +PerformActionUsage isIndividual 0fba2e9807953621 153 0 +PerformActionUsage isLibraryElement 5ad8aa497247c997 153 0 +PerformActionUsage isOrdered c299bac7c336abac 153 1 +PerformActionUsage isPortion 0fba2e9807953621 153 0 +PerformActionUsage isReference fef814ed260a0b34 153 153 +PerformActionUsage isSufficient 0fba2e9807953621 153 0 +PerformActionUsage isUnique fef814ed260a0b34 153 153 +PerformActionUsage isVariable 0fba2e9807953621 153 0 +PerformActionUsage isVariation f67e936d5f55da1c 153 1 +PerformActionUsage mayTimeVary 0fba2e9807953621 153 0 +PerformActionUsage member 35dce1e575235702 153 51 +PerformActionUsage membership 6f2b7e1842b0ef26 153 51 +PerformActionUsage multiplicity 3c4ffbbdb26751f5 153 2 +PerformActionUsage name b300f61d198b8e8b 153 151 +PerformActionUsage nestedAction 2f799a567f106c3c 153 15 +PerformActionUsage nestedAllocation 240b0155f6d100c0 153 0 +PerformActionUsage nestedAnalysisCase 240b0155f6d100c0 153 0 +PerformActionUsage nestedAttribute 240b0155f6d100c0 153 0 +PerformActionUsage nestedCalculation 240b0155f6d100c0 153 0 +PerformActionUsage nestedCase 240b0155f6d100c0 153 0 +PerformActionUsage nestedConcern 240b0155f6d100c0 153 0 +PerformActionUsage nestedConnection 30706bcc950fa87b 153 10 +PerformActionUsage nestedConstraint 240b0155f6d100c0 153 0 +PerformActionUsage nestedEnumeration 240b0155f6d100c0 153 0 +PerformActionUsage nestedFlow 240b0155f6d100c0 153 0 +PerformActionUsage nestedInterface 2e1fad956117f0a7 153 22 +PerformActionUsage nestedItem c71043dd4d96907b 153 3 +PerformActionUsage nestedMetadata 240b0155f6d100c0 153 0 +PerformActionUsage nestedOccurrence 4256a8e33b72e987 153 20 +PerformActionUsage nestedPart c71043dd4d96907b 153 3 +PerformActionUsage nestedPort 240b0155f6d100c0 153 0 +PerformActionUsage nestedReference 2e1fad956117f0a7 153 22 +PerformActionUsage nestedRendering 240b0155f6d100c0 153 0 +PerformActionUsage nestedRequirement 240b0155f6d100c0 153 0 +PerformActionUsage nestedState 240b0155f6d100c0 153 0 +PerformActionUsage nestedTransition 71cbb2fd71f3a756 153 2 +PerformActionUsage nestedUsage 2e8f856a3b00f91c 153 40 +PerformActionUsage nestedUseCase 240b0155f6d100c0 153 0 +PerformActionUsage nestedVerificationCase 240b0155f6d100c0 153 0 +PerformActionUsage nestedView 240b0155f6d100c0 153 0 +PerformActionUsage nestedViewpoint 240b0155f6d100c0 153 0 +PerformActionUsage occurrenceDefinition f46eaaea37765a1b 153 59 +PerformActionUsage output 64eee948ea9af997 153 14 +PerformActionUsage ownedAnnotation 240b0155f6d100c0 153 0 +PerformActionUsage ownedConjugator 0fba2e9807953621 153 0 +PerformActionUsage ownedCrossSubsetting 0fba2e9807953621 153 0 +PerformActionUsage ownedDifferencing 240b0155f6d100c0 153 0 +PerformActionUsage ownedDisjoining 240b0155f6d100c0 153 0 +PerformActionUsage ownedElement 9a1e1847b48f5180 153 96 +PerformActionUsage ownedEndFeature 240b0155f6d100c0 153 0 +PerformActionUsage ownedFeature 2e8f856a3b00f91c 153 40 +PerformActionUsage ownedFeatureChaining 240b0155f6d100c0 153 0 +PerformActionUsage ownedFeatureInverting 240b0155f6d100c0 153 0 +PerformActionUsage ownedFeatureMembership 6d81a8c87e33c73c 153 40 +PerformActionUsage ownedImport 240b0155f6d100c0 153 0 +PerformActionUsage ownedIntersecting 240b0155f6d100c0 153 0 +PerformActionUsage ownedMember 50de368cf7043a9b 153 51 +PerformActionUsage ownedMembership 6f2b7e1842b0ef26 153 51 +PerformActionUsage ownedRedefinition 0730af9b27de399c 153 18 +PerformActionUsage ownedReferenceSubsetting 5c86dcc795352686 153 96 +PerformActionUsage ownedRelationship 0037adfba5e173f8 153 153 +PerformActionUsage ownedSpecialization cb6276174854b580 153 153 +PerformActionUsage ownedSubsetting 3af2e13db816c4cb 153 153 +PerformActionUsage ownedTypeFeaturing 240b0155f6d100c0 153 0 +PerformActionUsage ownedTyping a5c6f21c43228b7f 153 9 +PerformActionUsage ownedUnioning 240b0155f6d100c0 153 0 +PerformActionUsage owner 0ff854039c790201 153 153 +PerformActionUsage owningDefinition f534032cdff15b19 153 18 +PerformActionUsage owningFeatureMembership 69beb3e9851046c8 153 151 +PerformActionUsage owningMembership be80859ef3ec51d9 153 153 +PerformActionUsage owningNamespace 0ff854039c790201 153 153 +PerformActionUsage owningRelationship be80859ef3ec51d9 153 153 +PerformActionUsage owningType 0d2d57b9b335323d 153 151 +PerformActionUsage owningUsage 27b38324dad90d45 153 133 +PerformActionUsage parameter 8abbc347b49fb008 153 25 +PerformActionUsage performedAction 02c706c75ec61168 153 96 +PerformActionUsage portionKind 0fba2e9807953621 153 0 +PerformActionUsage qualifiedName 19c53dc022b0d77f 153 147 +PerformActionUsage shortName 0fba2e9807953621 153 0 +PerformActionUsage textualRepresentation 240b0155f6d100c0 153 0 +PerformActionUsage type f46eaaea37765a1b 153 59 +PerformActionUsage unioningType 240b0155f6d100c0 153 0 +PerformActionUsage usage 2e8f856a3b00f91c 153 40 +PerformActionUsage variant 52463f91ef678fce 153 1 +PerformActionUsage variantMembership 7ad7e71beb72d113 153 1 +PortConjugation aliasIds a090dea588dcd8bd 91 0 +PortConjugation conjugatedPortDefinition 5fa280f4d6befdc9 91 91 +PortConjugation conjugatedType 5fa280f4d6befdc9 91 91 +PortConjugation declaredName 6139e15483c47bbe 91 0 +PortConjugation declaredShortName 6139e15483c47bbe 91 0 +PortConjugation documentation a090dea588dcd8bd 91 0 +PortConjugation elementId 57fdfe885942ef7c 91 91 +PortConjugation isImplied 887edaef2a175cce 91 0 +PortConjugation isImpliedIncluded d68e52fa33e4aaf5 91 91 +PortConjugation isLibraryElement 94bcac114b9112c1 91 7 +PortConjugation name 6139e15483c47bbe 91 0 +PortConjugation originalPortDefinition 868df5b79e5bdd10 91 91 +PortConjugation originalType 868df5b79e5bdd10 91 91 +PortConjugation ownedAnnotation a090dea588dcd8bd 91 0 +PortConjugation ownedElement a090dea588dcd8bd 91 0 +PortConjugation ownedRelatedElement a090dea588dcd8bd 91 0 +PortConjugation ownedRelationship a090dea588dcd8bd 91 0 +PortConjugation owner 6139e15483c47bbe 91 0 +PortConjugation owningMembership 6139e15483c47bbe 91 0 +PortConjugation owningNamespace 6139e15483c47bbe 91 0 +PortConjugation owningRelatedElement 5fa280f4d6befdc9 91 91 +PortConjugation owningRelationship 6139e15483c47bbe 91 0 +PortConjugation owningType 5fa280f4d6befdc9 91 91 +PortConjugation qualifiedName 6139e15483c47bbe 91 0 +PortConjugation relatedElement 9ef7032d37a0873a 91 91 +PortConjugation shortName 6139e15483c47bbe 91 0 +PortConjugation source 99ccdd3ab995bfd1 91 91 +PortConjugation target 0cba3bc72b2c6102 91 91 +PortConjugation textualRepresentation a090dea588dcd8bd 91 0 +PortDefinition aliasIds 6f20e08b58daa1f6 91 0 +PortDefinition conjugatedPortDefinition eaebcc4c52da5efa 91 91 +PortDefinition declaredName 3492063f8bd4d3ee 91 91 +PortDefinition declaredShortName 9a9bc8fe57c25ded 91 0 +PortDefinition differencingType 6f20e08b58daa1f6 91 0 +PortDefinition directedFeature 411ff10d5d27a7a5 91 25 +PortDefinition directedUsage 411ff10d5d27a7a5 91 25 +PortDefinition documentation ecdd6af978628997 91 4 +PortDefinition elementId 994cded2e970d0fc 91 91 +PortDefinition endFeature 6f20e08b58daa1f6 91 0 +PortDefinition feature 7c54cfd0441d2884 91 35 +PortDefinition featureMembership d390bd1991680821 91 35 +PortDefinition importedMembership 6f20e08b58daa1f6 91 0 +PortDefinition inheritedFeature 6f20e08b58daa1f6 91 0 +PortDefinition inheritedMembership 6f20e08b58daa1f6 91 0 +PortDefinition input ddadd604ba17e5e6 91 16 +PortDefinition intersectingType 6f20e08b58daa1f6 91 0 +PortDefinition isAbstract 8c454c6d8aa73be3 91 0 +PortDefinition isConjugated 8c454c6d8aa73be3 91 0 +PortDefinition isImpliedIncluded b7afe0333ce83c62 91 91 +PortDefinition isIndividual 9a9bc8fe57c25ded 91 0 +PortDefinition isLibraryElement 1adff28f94ed90c6 91 7 +PortDefinition isSufficient 8c454c6d8aa73be3 91 0 +PortDefinition isVariation 8c454c6d8aa73be3 91 0 +PortDefinition member aa36fc51e7666f24 91 91 +PortDefinition membership ecfceac217e49b1a 91 91 +PortDefinition multiplicity 9a9bc8fe57c25ded 91 0 +PortDefinition name 3492063f8bd4d3ee 91 91 +PortDefinition output 7d1eb92f520e71db 91 15 +PortDefinition ownedAction 6f20e08b58daa1f6 91 0 +PortDefinition ownedAllocation 6f20e08b58daa1f6 91 0 +PortDefinition ownedAnalysisCase 6f20e08b58daa1f6 91 0 +PortDefinition ownedAnnotation 6f20e08b58daa1f6 91 0 +PortDefinition ownedAttribute 2887433b3cc65ce6 91 8 +PortDefinition ownedCalculation 6f20e08b58daa1f6 91 0 +PortDefinition ownedCase 6f20e08b58daa1f6 91 0 +PortDefinition ownedConcern 6f20e08b58daa1f6 91 0 +PortDefinition ownedConjugator 9a9bc8fe57c25ded 91 0 +PortDefinition ownedConnection 6f20e08b58daa1f6 91 0 +PortDefinition ownedConstraint 6f20e08b58daa1f6 91 0 +PortDefinition ownedDifferencing 6f20e08b58daa1f6 91 0 +PortDefinition ownedDisjoining 6f20e08b58daa1f6 91 0 +PortDefinition ownedElement 9e04a43d46fdb8da 91 91 +PortDefinition ownedEndFeature 6f20e08b58daa1f6 91 0 +PortDefinition ownedEnumeration 6f20e08b58daa1f6 91 0 +PortDefinition ownedFeature 7c54cfd0441d2884 91 35 +PortDefinition ownedFeatureMembership d390bd1991680821 91 35 +PortDefinition ownedFlow 6f20e08b58daa1f6 91 0 +PortDefinition ownedImport 6f20e08b58daa1f6 91 0 +PortDefinition ownedInterface a98e49aa874b3b79 91 13 +PortDefinition ownedIntersecting 6f20e08b58daa1f6 91 0 +PortDefinition ownedItem 06b287ee2eb70e22 91 12 +PortDefinition ownedMember 9e04a43d46fdb8da 91 91 +PortDefinition ownedMembership ecfceac217e49b1a 91 91 +PortDefinition ownedMetadata 6f20e08b58daa1f6 91 0 +PortDefinition ownedOccurrence 9074e4d2d2a31c7b 91 18 +PortDefinition ownedPart 6f20e08b58daa1f6 91 0 +PortDefinition ownedPort f8e33d6ffcc6b04f 91 6 +PortDefinition ownedReference a98e49aa874b3b79 91 13 +PortDefinition ownedRelationship c8858d35f2bd9cb1 91 91 +PortDefinition ownedRendering 6f20e08b58daa1f6 91 0 +PortDefinition ownedRequirement 6f20e08b58daa1f6 91 0 +PortDefinition ownedSpecialization 13fbb04a6bab5bcd 91 91 +PortDefinition ownedState 6f20e08b58daa1f6 91 0 +PortDefinition ownedSubclassification 13fbb04a6bab5bcd 91 91 +PortDefinition ownedTransition 6f20e08b58daa1f6 91 0 +PortDefinition ownedUnioning 6f20e08b58daa1f6 91 0 +PortDefinition ownedUsage 7c54cfd0441d2884 91 35 +PortDefinition ownedUseCase 6f20e08b58daa1f6 91 0 +PortDefinition ownedVerificationCase 6f20e08b58daa1f6 91 0 +PortDefinition ownedView 6f20e08b58daa1f6 91 0 +PortDefinition ownedViewpoint 6f20e08b58daa1f6 91 0 +PortDefinition owner 41ec8d9fc1f244c2 91 91 +PortDefinition owningMembership f8e530e28c6fb137 91 91 +PortDefinition owningNamespace 41ec8d9fc1f244c2 91 91 +PortDefinition owningRelationship f8e530e28c6fb137 91 91 +PortDefinition qualifiedName a71bf087f186f165 91 91 +PortDefinition shortName 9a9bc8fe57c25ded 91 0 +PortDefinition textualRepresentation 6f20e08b58daa1f6 91 0 +PortDefinition unioningType 6f20e08b58daa1f6 91 0 +PortDefinition usage 7c54cfd0441d2884 91 35 +PortDefinition variant 6f20e08b58daa1f6 91 0 +PortDefinition variantMembership 6f20e08b58daa1f6 91 0 +PortUsage aliasIds 006f585500af6d8e 365 0 +PortUsage chainingFeature 006f585500af6d8e 365 0 +PortUsage crossFeature 6c773ae1772df27b 365 0 +PortUsage declaredName 21e057f7aa9ac310 365 268 +PortUsage declaredShortName 6c773ae1772df27b 365 0 +PortUsage definition e520de610ca5a77d 365 305 +PortUsage differencingType 006f585500af6d8e 365 0 +PortUsage directedFeature de1fc5db42249bdd 365 36 +PortUsage directedUsage de1fc5db42249bdd 365 36 +PortUsage direction 6c773ae1772df27b 365 0 +PortUsage documentation 18f825ee799b46b5 365 1 +PortUsage elementId f6bead333770d630 365 365 +PortUsage endFeature 006f585500af6d8e 365 0 +PortUsage endOwningType facf0ba33618cde5 365 82 +PortUsage feature 61727fee7204e7cb 365 70 +PortUsage featureMembership a7f1c2da3b8b94ae 365 70 +PortUsage featureTarget 3600292f0d49daf1 365 0 +PortUsage featuringType 006f585500af6d8e 365 0 +PortUsage importedMembership 006f585500af6d8e 365 0 +PortUsage individualDefinition 6c773ae1772df27b 365 0 +PortUsage inheritedFeature 006f585500af6d8e 365 0 +PortUsage inheritedMembership 006f585500af6d8e 365 0 +PortUsage input a8447d64df6c54c8 365 25 +PortUsage intersectingType 006f585500af6d8e 365 0 +PortUsage isAbstract 226be4e7317218e2 365 1 +PortUsage isComposite 3b1c20ef2e1066a0 365 35 +PortUsage isConjugated d10223e08220b669 365 0 +PortUsage isConstant 35cd9f99e94ff617 365 118 +PortUsage isDerived eea6d8191866a50d 365 0 +PortUsage isEnd 35cd9f99e94ff617 365 118 +PortUsage isImpliedIncluded a18614943a8fc24a 365 365 +PortUsage isIndividual 6c773ae1772df27b 365 0 +PortUsage isLibraryElement 08d8e141b557da92 365 5 +PortUsage isOrdered eea6d8191866a50d 365 0 +PortUsage isPortion 6c773ae1772df27b 365 0 +PortUsage isReference 376c17858ea01213 365 330 +PortUsage isSufficient 6c773ae1772df27b 365 0 +PortUsage isUnique a03ac45a99c6bf5a 365 289 +PortUsage isVariable df75e84e5ae24913 365 118 +PortUsage isVariation 04c730ae9b2c2a3e 365 1 +PortUsage mayTimeVary df75e84e5ae24913 365 118 +PortUsage member a186dd91888a88f5 365 111 +PortUsage membership f5606ac29f27c31b 365 111 +PortUsage multiplicity ffe2cf723ac25b90 365 34 +PortUsage name 646a4e3caf4ee6f2 365 364 +PortUsage nestedAction 006f585500af6d8e 365 0 +PortUsage nestedAllocation 006f585500af6d8e 365 0 +PortUsage nestedAnalysisCase 006f585500af6d8e 365 0 +PortUsage nestedAttribute 759fb15be3ea76b1 365 3 +PortUsage nestedCalculation 006f585500af6d8e 365 0 +PortUsage nestedCase 006f585500af6d8e 365 0 +PortUsage nestedConcern 006f585500af6d8e 365 0 +PortUsage nestedConnection 5684e961c68301fc 365 1 +PortUsage nestedConstraint 006f585500af6d8e 365 0 +PortUsage nestedEnumeration 006f585500af6d8e 365 0 +PortUsage nestedFlow 006f585500af6d8e 365 0 +PortUsage nestedInterface 64496cdae7fd8a9c 365 30 +PortUsage nestedItem cccf5d5f96a2096c 365 5 +PortUsage nestedMetadata 006f585500af6d8e 365 0 +PortUsage nestedOccurrence 144b6c89b9624366 365 37 +PortUsage nestedPart 006f585500af6d8e 365 0 +PortUsage nestedPort b82f0a70386527df 365 16 +PortUsage nestedReference 64496cdae7fd8a9c 365 30 +PortUsage nestedRendering 006f585500af6d8e 365 0 +PortUsage nestedRequirement 006f585500af6d8e 365 0 +PortUsage nestedState 006f585500af6d8e 365 0 +PortUsage nestedTransition 006f585500af6d8e 365 0 +PortUsage nestedUsage 61727fee7204e7cb 365 70 +PortUsage nestedUseCase 006f585500af6d8e 365 0 +PortUsage nestedVerificationCase 006f585500af6d8e 365 0 +PortUsage nestedView 006f585500af6d8e 365 0 +PortUsage nestedViewpoint 006f585500af6d8e 365 0 +PortUsage occurrenceDefinition e520de610ca5a77d 365 305 +PortUsage output 38dc7e163e235999 365 19 +PortUsage ownedAnnotation 006f585500af6d8e 365 0 +PortUsage ownedConjugator 6c773ae1772df27b 365 0 +PortUsage ownedCrossSubsetting 6c773ae1772df27b 365 0 +PortUsage ownedDifferencing 006f585500af6d8e 365 0 +PortUsage ownedDisjoining 006f585500af6d8e 365 0 +PortUsage ownedElement 412496c390c368a6 365 179 +PortUsage ownedEndFeature 006f585500af6d8e 365 0 +PortUsage ownedFeature 61727fee7204e7cb 365 70 +PortUsage ownedFeatureChaining 006f585500af6d8e 365 0 +PortUsage ownedFeatureInverting 006f585500af6d8e 365 0 +PortUsage ownedFeatureMembership a7f1c2da3b8b94ae 365 70 +PortUsage ownedImport 006f585500af6d8e 365 0 +PortUsage ownedIntersecting 006f585500af6d8e 365 0 +PortUsage ownedMember a186dd91888a88f5 365 111 +PortUsage ownedMembership f5606ac29f27c31b 365 111 +PortUsage ownedRedefinition c77287fe50a15471 365 67 +PortUsage ownedReferenceSubsetting 879d0b34d085f8b9 365 80 +PortUsage ownedRelationship 40e4d7dd7260f688 365 365 +PortUsage ownedSpecialization 44ac2aae675fb875 365 365 +PortUsage ownedSubsetting c0163a71ffeb116b 365 365 +PortUsage ownedTypeFeaturing 006f585500af6d8e 365 0 +PortUsage ownedTyping 585a89a6a2726384 365 185 +PortUsage ownedUnioning 006f585500af6d8e 365 0 +PortUsage owner c61d32e3533e42ef 365 365 +PortUsage owningDefinition 1a21029fdf4b4546 365 120 +PortUsage owningFeatureMembership e843f9660bb39c00 365 361 +PortUsage owningMembership 06250d4df2c84205 365 365 +PortUsage owningNamespace c61d32e3533e42ef 365 365 +PortUsage owningRelationship 06250d4df2c84205 365 365 +PortUsage owningType e340a8bc40899bc5 365 361 +PortUsage owningUsage 3596e0fdd86c48fa 365 241 +PortUsage portDefinition e520de610ca5a77d 365 305 +PortUsage portionKind 6c773ae1772df27b 365 0 +PortUsage qualifiedName 5dd552ad24dbe4e3 365 342 +PortUsage shortName 6c773ae1772df27b 365 0 +PortUsage textualRepresentation 006f585500af6d8e 365 0 +PortUsage type e520de610ca5a77d 365 305 +PortUsage unioningType 006f585500af6d8e 365 0 +PortUsage usage 61727fee7204e7cb 365 70 +PortUsage variant ef618121b171b03c 365 1 +PortUsage variantMembership 0e2e60d8ff28354d 365 1 +Redefinition aliasIds b14afcd20400b321 1304 0 +Redefinition declaredName 494d8946e1d7e57f 1304 0 +Redefinition declaredShortName 494d8946e1d7e57f 1304 0 +Redefinition documentation b14afcd20400b321 1304 0 +Redefinition elementId fc71d187a6116fdc 1304 1304 +Redefinition general 321d69595f5f4bbf 1304 1304 +Redefinition isImplied df68572e01aea7dd 1304 0 +Redefinition isImpliedIncluded 32966bb3325292c5 1304 1304 +Redefinition isLibraryElement daa9f48a757b85e0 1304 39 +Redefinition name 494d8946e1d7e57f 1304 0 +Redefinition ownedAnnotation b14afcd20400b321 1304 0 +Redefinition ownedElement 5b7b39d8ff36ba86 1304 24 +Redefinition ownedRelatedElement b4bfca2c38834c99 1304 6 +Redefinition ownedRelationship 9f47c4843fe03885 1304 24 +Redefinition owner 494d8946e1d7e57f 1304 0 +Redefinition owningFeature ed0f2030db69f7a8 1304 1304 +Redefinition owningMembership 494d8946e1d7e57f 1304 0 +Redefinition owningNamespace 494d8946e1d7e57f 1304 0 +Redefinition owningRelatedElement ed0f2030db69f7a8 1304 1304 +Redefinition owningRelationship 494d8946e1d7e57f 1304 0 +Redefinition owningType ed0f2030db69f7a8 1304 1304 +Redefinition qualifiedName 494d8946e1d7e57f 1304 0 +Redefinition redefinedFeature 321d69595f5f4bbf 1304 1304 +Redefinition redefiningFeature ed0f2030db69f7a8 1304 1304 +Redefinition relatedElement 2f50dc03373f9308 1304 1304 +Redefinition shortName 494d8946e1d7e57f 1304 0 +Redefinition source 8d505ac0bd7d87e2 1304 1304 +Redefinition specific ed0f2030db69f7a8 1304 1304 +Redefinition subsettedFeature 321d69595f5f4bbf 1304 1304 +Redefinition subsettingFeature ed0f2030db69f7a8 1304 1304 +Redefinition target 11a6a56632d9cf4f 1304 1304 +Redefinition textualRepresentation 5b7b39d8ff36ba86 1304 24 +ReferenceSubsetting aliasIds 7c8932dd086c471b 1164 0 +ReferenceSubsetting declaredName 2bce54be67db2b25 1164 0 +ReferenceSubsetting declaredShortName 2bce54be67db2b25 1164 0 +ReferenceSubsetting documentation 7c8932dd086c471b 1164 0 +ReferenceSubsetting elementId 786f03f006215d18 1164 1164 +ReferenceSubsetting general fcb6c4c1ae75be5a 1164 1164 +ReferenceSubsetting isImplied bc0260da9cc7cacb 1164 0 +ReferenceSubsetting isImpliedIncluded 8c63431cbd9f7e4f 1164 1164 +ReferenceSubsetting isLibraryElement bc0260da9cc7cacb 1164 0 +ReferenceSubsetting name 2bce54be67db2b25 1164 0 +ReferenceSubsetting ownedAnnotation 7c8932dd086c471b 1164 0 +ReferenceSubsetting ownedElement bedaf0ada9a6f594 1164 10 +ReferenceSubsetting ownedRelatedElement 5ec99b6b78dc6286 1164 495 +ReferenceSubsetting ownedRelationship 30a1b4c2e88769a0 1164 10 +ReferenceSubsetting owner 2bce54be67db2b25 1164 0 +ReferenceSubsetting owningFeature 846bafbe73517293 1164 1164 +ReferenceSubsetting owningMembership 2bce54be67db2b25 1164 0 +ReferenceSubsetting owningNamespace 2bce54be67db2b25 1164 0 +ReferenceSubsetting owningRelatedElement 846bafbe73517293 1164 1164 +ReferenceSubsetting owningRelationship 2bce54be67db2b25 1164 0 +ReferenceSubsetting owningType 846bafbe73517293 1164 1164 +ReferenceSubsetting qualifiedName 2bce54be67db2b25 1164 0 +ReferenceSubsetting referencedFeature fcb6c4c1ae75be5a 1164 1164 +ReferenceSubsetting referencingFeature 846bafbe73517293 1164 1164 +ReferenceSubsetting relatedElement 7f54deb5e8f7cbec 1164 1164 +ReferenceSubsetting shortName 2bce54be67db2b25 1164 0 +ReferenceSubsetting source 500aa6b407b68cef 1164 1164 +ReferenceSubsetting specific 846bafbe73517293 1164 1164 +ReferenceSubsetting subsettedFeature fcb6c4c1ae75be5a 1164 1164 +ReferenceSubsetting subsettingFeature 846bafbe73517293 1164 1164 +ReferenceSubsetting target 2ab4230e602bb8a4 1164 1164 +ReferenceSubsetting textualRepresentation bedaf0ada9a6f594 1164 10 +ReferenceUsage aliasIds b2e28eeca2859c0c 3074 0 +ReferenceUsage chainingFeature b2e28eeca2859c0c 3074 0 +ReferenceUsage crossFeature d9d0348954fc86be 3074 0 +ReferenceUsage declaredName 39661a7321d6adfc 3074 1028 +ReferenceUsage declaredShortName d9d0348954fc86be 3074 0 +ReferenceUsage definition 5841841adc9e3259 3074 1522 +ReferenceUsage differencingType b2e28eeca2859c0c 3074 0 +ReferenceUsage directedFeature b2e28eeca2859c0c 3074 0 +ReferenceUsage directedUsage b2e28eeca2859c0c 3074 0 +ReferenceUsage direction 9a1ed50a0bc08744 3074 1243 +ReferenceUsage documentation 8349ab004b77ba23 3074 3 +ReferenceUsage elementId 7613b3d32f9af500 3074 3074 +ReferenceUsage endFeature b2e28eeca2859c0c 3074 0 +ReferenceUsage endOwningType a91e6dc313c7a041 3074 1052 +ReferenceUsage feature 281a3b70801aa733 3074 34 +ReferenceUsage featureMembership f524cce76d690742 3074 34 +ReferenceUsage featureTarget aa51a76548bcfbaa 3074 0 +ReferenceUsage featuringType b2e28eeca2859c0c 3074 0 +ReferenceUsage importedMembership b2e28eeca2859c0c 3074 0 +ReferenceUsage inheritedFeature b2e28eeca2859c0c 3074 0 +ReferenceUsage inheritedMembership b2e28eeca2859c0c 3074 0 +ReferenceUsage input b2e28eeca2859c0c 3074 0 +ReferenceUsage intersectingType b2e28eeca2859c0c 3074 0 +ReferenceUsage isAbstract 97aaa822180a00c4 3074 2 +ReferenceUsage isComposite 827776558f4475b8 3074 0 +ReferenceUsage isConjugated cc6fb1314ea68cba 3074 0 +ReferenceUsage isConstant 42dceba9e8758160 3074 1052 +ReferenceUsage isDerived f443f1b6684d76ea 3074 0 +ReferenceUsage isEnd 42dceba9e8758160 3074 1052 +ReferenceUsage isImpliedIncluded 2e908618a80cbc5c 3074 3074 +ReferenceUsage isLibraryElement fbe2398abeb6663a 3074 48 +ReferenceUsage isOrdered f443f1b6684d76ea 3074 0 +ReferenceUsage isPortion d9d0348954fc86be 3074 0 +ReferenceUsage isReference 57f13ea6ba5f151c 3074 2844 +ReferenceUsage isSufficient d9d0348954fc86be 3074 0 +ReferenceUsage isUnique 018a8ebef5793ed6 3074 1388 +ReferenceUsage isVariable 6ff755d8a1d4c334 3074 1052 +ReferenceUsage isVariation cc6fb1314ea68cba 3074 0 +ReferenceUsage mayTimeVary 6ff755d8a1d4c334 3074 1052 +ReferenceUsage member 14f2322e0465504a 3074 929 +ReferenceUsage membership 05b95428f3622efa 3074 929 +ReferenceUsage multiplicity 0024a2d7e1e342a4 3074 108 +ReferenceUsage name 8307e8a334911694 3074 2779 +ReferenceUsage nestedAction b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedAllocation b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedAnalysisCase b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedAttribute 70c5842af8cef12d 3074 1 +ReferenceUsage nestedCalculation b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedCase b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedConcern b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedConnection b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedConstraint a711eb1b55cd1a50 3074 4 +ReferenceUsage nestedEnumeration b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedFlow b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedInterface de6d1e2e258c9c6f 3074 26 +ReferenceUsage nestedItem 99f462ee9e504142 3074 3 +ReferenceUsage nestedMetadata b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedOccurrence 3eacb6f0a6ca51af 3074 7 +ReferenceUsage nestedPart 99f462ee9e504142 3074 3 +ReferenceUsage nestedPort c4c76f9f0ac8ddcf 3074 2 +ReferenceUsage nestedReference de6d1e2e258c9c6f 3074 26 +ReferenceUsage nestedRendering b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedRequirement b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedState b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedTransition b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedUsage 281a3b70801aa733 3074 34 +ReferenceUsage nestedUseCase b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedVerificationCase b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedView b2e28eeca2859c0c 3074 0 +ReferenceUsage nestedViewpoint b2e28eeca2859c0c 3074 0 +ReferenceUsage output b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedAnnotation b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedConjugator d9d0348954fc86be 3074 0 +ReferenceUsage ownedCrossSubsetting d9d0348954fc86be 3074 0 +ReferenceUsage ownedDifferencing b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedDisjoining b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedElement 1a0342976f8ca8cb 3074 1125 +ReferenceUsage ownedEndFeature b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedFeature 281a3b70801aa733 3074 34 +ReferenceUsage ownedFeatureChaining b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedFeatureInverting b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedFeatureMembership f524cce76d690742 3074 34 +ReferenceUsage ownedImport b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedIntersecting b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedMember 14f2322e0465504a 3074 929 +ReferenceUsage ownedMembership 05b95428f3622efa 3074 929 +ReferenceUsage ownedRedefinition ec0c1d2fc95fd3a0 3074 628 +ReferenceUsage ownedReferenceSubsetting 9543488fa87c651d 3074 583 +ReferenceUsage ownedRelationship 6d6228b6c38642ee 3074 2404 +ReferenceUsage ownedSpecialization 08c972a1ec93c31e 3074 1953 +ReferenceUsage ownedSubsetting 6fddebee52a896e3 3074 1277 +ReferenceUsage ownedTypeFeaturing b2e28eeca2859c0c 3074 0 +ReferenceUsage ownedTyping a96c56cf0acb7835 3074 733 +ReferenceUsage ownedUnioning b2e28eeca2859c0c 3074 0 +ReferenceUsage owner 940ac453a828863f 3074 3074 +ReferenceUsage owningDefinition 6660f001f33ed25f 3074 540 +ReferenceUsage owningFeatureMembership e6d84a2ad469c783 3074 3017 +ReferenceUsage owningMembership 9d500fc08cf05fa9 3074 3074 +ReferenceUsage owningNamespace 940ac453a828863f 3074 3074 +ReferenceUsage owningRelationship 9d500fc08cf05fa9 3074 3074 +ReferenceUsage owningType 8e8657068e0f6188 3074 3017 +ReferenceUsage owningUsage 9e8043f5f0536ff4 3074 2221 +ReferenceUsage qualifiedName 2c2ee2bf6eff0ad6 3074 1490 +ReferenceUsage shortName b51f1735ff0bb0df 3074 1 +ReferenceUsage textualRepresentation b2e28eeca2859c0c 3074 0 +ReferenceUsage type 5841841adc9e3259 3074 1522 +ReferenceUsage unioningType b2e28eeca2859c0c 3074 0 +ReferenceUsage usage 281a3b70801aa733 3074 34 +ReferenceUsage variant b2e28eeca2859c0c 3074 0 +ReferenceUsage variantMembership b2e28eeca2859c0c 3074 0 +RenderingDefinition aliasIds 46bd8d533727e761 1 0 +RenderingDefinition declaredName 4b639867d1de95f1 1 1 +RenderingDefinition declaredShortName 3e957a329570a258 1 0 +RenderingDefinition differencingType 46bd8d533727e761 1 0 +RenderingDefinition directedFeature 46bd8d533727e761 1 0 +RenderingDefinition directedUsage 46bd8d533727e761 1 0 +RenderingDefinition documentation 46bd8d533727e761 1 0 +RenderingDefinition elementId 37476e0610085234 1 1 +RenderingDefinition endFeature 46bd8d533727e761 1 0 +RenderingDefinition feature 46bd8d533727e761 1 0 +RenderingDefinition featureMembership 46bd8d533727e761 1 0 +RenderingDefinition importedMembership 46bd8d533727e761 1 0 +RenderingDefinition inheritedFeature 46bd8d533727e761 1 0 +RenderingDefinition inheritedMembership 46bd8d533727e761 1 0 +RenderingDefinition input 46bd8d533727e761 1 0 +RenderingDefinition intersectingType 46bd8d533727e761 1 0 +RenderingDefinition isAbstract 68a3c8d8df79989c 1 0 +RenderingDefinition isConjugated 68a3c8d8df79989c 1 0 +RenderingDefinition isImpliedIncluded 1930c5df46692381 1 1 +RenderingDefinition isIndividual 3e957a329570a258 1 0 +RenderingDefinition isLibraryElement 68a3c8d8df79989c 1 0 +RenderingDefinition isSufficient 68a3c8d8df79989c 1 0 +RenderingDefinition isVariation 68a3c8d8df79989c 1 0 +RenderingDefinition member 46bd8d533727e761 1 0 +RenderingDefinition membership 46bd8d533727e761 1 0 +RenderingDefinition multiplicity 3e957a329570a258 1 0 +RenderingDefinition name 4b639867d1de95f1 1 1 +RenderingDefinition output 46bd8d533727e761 1 0 +RenderingDefinition ownedAction 46bd8d533727e761 1 0 +RenderingDefinition ownedAllocation 46bd8d533727e761 1 0 +RenderingDefinition ownedAnalysisCase 46bd8d533727e761 1 0 +RenderingDefinition ownedAnnotation 46bd8d533727e761 1 0 +RenderingDefinition ownedAttribute 46bd8d533727e761 1 0 +RenderingDefinition ownedCalculation 46bd8d533727e761 1 0 +RenderingDefinition ownedCase 46bd8d533727e761 1 0 +RenderingDefinition ownedConcern 46bd8d533727e761 1 0 +RenderingDefinition ownedConjugator 3e957a329570a258 1 0 +RenderingDefinition ownedConnection 46bd8d533727e761 1 0 +RenderingDefinition ownedConstraint 46bd8d533727e761 1 0 +RenderingDefinition ownedDifferencing 46bd8d533727e761 1 0 +RenderingDefinition ownedDisjoining 46bd8d533727e761 1 0 +RenderingDefinition ownedElement 46bd8d533727e761 1 0 +RenderingDefinition ownedEndFeature 46bd8d533727e761 1 0 +RenderingDefinition ownedEnumeration 46bd8d533727e761 1 0 +RenderingDefinition ownedFeature 46bd8d533727e761 1 0 +RenderingDefinition ownedFeatureMembership 46bd8d533727e761 1 0 +RenderingDefinition ownedFlow 46bd8d533727e761 1 0 +RenderingDefinition ownedImport 46bd8d533727e761 1 0 +RenderingDefinition ownedInterface 46bd8d533727e761 1 0 +RenderingDefinition ownedIntersecting 46bd8d533727e761 1 0 +RenderingDefinition ownedItem 46bd8d533727e761 1 0 +RenderingDefinition ownedMember 46bd8d533727e761 1 0 +RenderingDefinition ownedMembership 46bd8d533727e761 1 0 +RenderingDefinition ownedMetadata 46bd8d533727e761 1 0 +RenderingDefinition ownedOccurrence 46bd8d533727e761 1 0 +RenderingDefinition ownedPart 46bd8d533727e761 1 0 +RenderingDefinition ownedPort 46bd8d533727e761 1 0 +RenderingDefinition ownedReference 46bd8d533727e761 1 0 +RenderingDefinition ownedRelationship 4ed6111d4a105f51 1 1 +RenderingDefinition ownedRendering 46bd8d533727e761 1 0 +RenderingDefinition ownedRequirement 46bd8d533727e761 1 0 +RenderingDefinition ownedSpecialization 4ed6111d4a105f51 1 1 +RenderingDefinition ownedState 46bd8d533727e761 1 0 +RenderingDefinition ownedSubclassification 4ed6111d4a105f51 1 1 +RenderingDefinition ownedTransition 46bd8d533727e761 1 0 +RenderingDefinition ownedUnioning 46bd8d533727e761 1 0 +RenderingDefinition ownedUsage 46bd8d533727e761 1 0 +RenderingDefinition ownedUseCase 46bd8d533727e761 1 0 +RenderingDefinition ownedVerificationCase 46bd8d533727e761 1 0 +RenderingDefinition ownedView 46bd8d533727e761 1 0 +RenderingDefinition ownedViewpoint 46bd8d533727e761 1 0 +RenderingDefinition owner f3978bad9d40c716 1 1 +RenderingDefinition owningMembership 704458c12a677a91 1 1 +RenderingDefinition owningNamespace f3978bad9d40c716 1 1 +RenderingDefinition owningRelationship 704458c12a677a91 1 1 +RenderingDefinition qualifiedName 526b382d758e6350 1 1 +RenderingDefinition rendering 46bd8d533727e761 1 0 +RenderingDefinition shortName 3e957a329570a258 1 0 +RenderingDefinition textualRepresentation 46bd8d533727e761 1 0 +RenderingDefinition unioningType 46bd8d533727e761 1 0 +RenderingDefinition usage 46bd8d533727e761 1 0 +RenderingDefinition variant 46bd8d533727e761 1 0 +RenderingDefinition variantMembership 46bd8d533727e761 1 0 +RenderingUsage aliasIds f88374922a60e41e 14 0 +RenderingUsage chainingFeature f88374922a60e41e 14 0 +RenderingUsage crossFeature e914bbcdd1aa38f4 14 0 +RenderingUsage declaredName b9946dd565145a82 14 4 +RenderingUsage declaredShortName e914bbcdd1aa38f4 14 0 +RenderingUsage definition c60f15cd1d2e1093 14 13 +RenderingUsage differencingType f88374922a60e41e 14 0 +RenderingUsage directedFeature f88374922a60e41e 14 0 +RenderingUsage directedUsage f88374922a60e41e 14 0 +RenderingUsage direction e914bbcdd1aa38f4 14 0 +RenderingUsage documentation f88374922a60e41e 14 0 +RenderingUsage elementId e2b8646db46581d4 14 14 +RenderingUsage endFeature f88374922a60e41e 14 0 +RenderingUsage endOwningType e914bbcdd1aa38f4 14 0 +RenderingUsage feature c20f640416afaa83 14 2 +RenderingUsage featureMembership f806491f33a4ec02 14 2 +RenderingUsage featureTarget 992f7988c2f24d92 14 0 +RenderingUsage featuringType f88374922a60e41e 14 0 +RenderingUsage importedMembership f88374922a60e41e 14 0 +RenderingUsage individualDefinition e914bbcdd1aa38f4 14 0 +RenderingUsage inheritedFeature f88374922a60e41e 14 0 +RenderingUsage inheritedMembership f88374922a60e41e 14 0 +RenderingUsage input f88374922a60e41e 14 0 +RenderingUsage intersectingType f88374922a60e41e 14 0 +RenderingUsage isAbstract f4ac3cd6336f4328 14 0 +RenderingUsage isComposite b908f6da6f289344 14 12 +RenderingUsage isConjugated f4ac3cd6336f4328 14 0 +RenderingUsage isConstant f4ac3cd6336f4328 14 0 +RenderingUsage isDerived f4ac3cd6336f4328 14 0 +RenderingUsage isEnd f4ac3cd6336f4328 14 0 +RenderingUsage isImpliedIncluded ac4a9908769295ce 14 14 +RenderingUsage isIndividual e914bbcdd1aa38f4 14 0 +RenderingUsage isLibraryElement f4ac3cd6336f4328 14 0 +RenderingUsage isOrdered f4ac3cd6336f4328 14 0 +RenderingUsage isPortion e914bbcdd1aa38f4 14 0 +RenderingUsage isReference e7eddf043ad945b2 14 2 +RenderingUsage isSufficient e914bbcdd1aa38f4 14 0 +RenderingUsage isUnique ac4a9908769295ce 14 14 +RenderingUsage isVariable e914bbcdd1aa38f4 14 0 +RenderingUsage isVariation f4ac3cd6336f4328 14 0 +RenderingUsage itemDefinition 6121e270fe5868ff 14 13 +RenderingUsage mayTimeVary e914bbcdd1aa38f4 14 0 +RenderingUsage member 742e831be33a8fcd 14 3 +RenderingUsage membership 455d02e4d65f2fcd 14 3 +RenderingUsage multiplicity 460bf8ff9f2a0c3d 14 1 +RenderingUsage name e12ad6362f11e0a6 14 14 +RenderingUsage nestedAction f88374922a60e41e 14 0 +RenderingUsage nestedAllocation f88374922a60e41e 14 0 +RenderingUsage nestedAnalysisCase f88374922a60e41e 14 0 +RenderingUsage nestedAttribute f88374922a60e41e 14 0 +RenderingUsage nestedCalculation f88374922a60e41e 14 0 +RenderingUsage nestedCase f88374922a60e41e 14 0 +RenderingUsage nestedConcern f88374922a60e41e 14 0 +RenderingUsage nestedConnection f88374922a60e41e 14 0 +RenderingUsage nestedConstraint f88374922a60e41e 14 0 +RenderingUsage nestedEnumeration f88374922a60e41e 14 0 +RenderingUsage nestedFlow f88374922a60e41e 14 0 +RenderingUsage nestedInterface f88374922a60e41e 14 0 +RenderingUsage nestedItem c20f640416afaa83 14 2 +RenderingUsage nestedMetadata f88374922a60e41e 14 0 +RenderingUsage nestedOccurrence c20f640416afaa83 14 2 +RenderingUsage nestedPart c20f640416afaa83 14 2 +RenderingUsage nestedPort f88374922a60e41e 14 0 +RenderingUsage nestedReference f88374922a60e41e 14 0 +RenderingUsage nestedRendering f88374922a60e41e 14 0 +RenderingUsage nestedRequirement f88374922a60e41e 14 0 +RenderingUsage nestedState f88374922a60e41e 14 0 +RenderingUsage nestedTransition f88374922a60e41e 14 0 +RenderingUsage nestedUsage c20f640416afaa83 14 2 +RenderingUsage nestedUseCase f88374922a60e41e 14 0 +RenderingUsage nestedVerificationCase f88374922a60e41e 14 0 +RenderingUsage nestedView c20f640416afaa83 14 2 +RenderingUsage nestedViewpoint f88374922a60e41e 14 0 +RenderingUsage occurrenceDefinition 5cc8758578ddc299 14 13 +RenderingUsage output f88374922a60e41e 14 0 +RenderingUsage ownedAnnotation f88374922a60e41e 14 0 +RenderingUsage ownedConjugator e914bbcdd1aa38f4 14 0 +RenderingUsage ownedCrossSubsetting e914bbcdd1aa38f4 14 0 +RenderingUsage ownedDifferencing f88374922a60e41e 14 0 +RenderingUsage ownedDisjoining f88374922a60e41e 14 0 +RenderingUsage ownedElement 742e831be33a8fcd 14 3 +RenderingUsage ownedEndFeature f88374922a60e41e 14 0 +RenderingUsage ownedFeature c20f640416afaa83 14 2 +RenderingUsage ownedFeatureChaining f88374922a60e41e 14 0 +RenderingUsage ownedFeatureInverting f88374922a60e41e 14 0 +RenderingUsage ownedFeatureMembership f806491f33a4ec02 14 2 +RenderingUsage ownedImport f88374922a60e41e 14 0 +RenderingUsage ownedIntersecting f88374922a60e41e 14 0 +RenderingUsage ownedMember 742e831be33a8fcd 14 3 +RenderingUsage ownedMembership 455d02e4d65f2fcd 14 3 +RenderingUsage ownedRedefinition f88374922a60e41e 14 0 +RenderingUsage ownedReferenceSubsetting 0f9ba48f2c8df4d1 14 10 +RenderingUsage ownedRelationship 724e4212c01c8e5c 14 14 +RenderingUsage ownedSpecialization 4d2f7a4a994e1fa7 14 14 +RenderingUsage ownedSubsetting a9d0f850683abec9 14 14 +RenderingUsage ownedTypeFeaturing f88374922a60e41e 14 0 +RenderingUsage ownedTyping 4186a7bbb472f14a 14 2 +RenderingUsage ownedUnioning f88374922a60e41e 14 0 +RenderingUsage owner 5ac1eca2fbd38d79 14 14 +RenderingUsage owningDefinition e1dbbb707a9ddb8a 14 3 +RenderingUsage owningFeatureMembership 7701af792b975e2e 14 12 +RenderingUsage owningMembership 307b744d18a1dbf5 14 14 +RenderingUsage owningNamespace 5ac1eca2fbd38d79 14 14 +RenderingUsage owningRelationship 307b744d18a1dbf5 14 14 +RenderingUsage owningType 3fb1328357e3d088 14 12 +RenderingUsage owningUsage 46ea32e0aef02df2 14 9 +RenderingUsage partDefinition 145d1d25068bf40b 14 13 +RenderingUsage portionKind e914bbcdd1aa38f4 14 0 +RenderingUsage qualifiedName faf113a5cd0117e9 14 14 +RenderingUsage renderingDefinition 069f341bccaf04a2 14 13 +RenderingUsage shortName e914bbcdd1aa38f4 14 0 +RenderingUsage textualRepresentation f88374922a60e41e 14 0 +RenderingUsage type c60f15cd1d2e1093 14 13 +RenderingUsage unioningType f88374922a60e41e 14 0 +RenderingUsage usage c20f640416afaa83 14 2 +RenderingUsage variant f88374922a60e41e 14 0 +RenderingUsage variantMembership f88374922a60e41e 14 0 +RequirementConstraintMembership aliasIds f825b3fdd215e998 54 0 +RequirementConstraintMembership declaredName e0fcfa569375a7fa 54 0 +RequirementConstraintMembership declaredShortName e0fcfa569375a7fa 54 0 +RequirementConstraintMembership documentation f825b3fdd215e998 54 0 +RequirementConstraintMembership elementId 58653c1337b2d084 54 54 +RequirementConstraintMembership isImplied 7424ee3b88e2988a 54 0 +RequirementConstraintMembership isImpliedIncluded bca796c06c314cc8 54 54 +RequirementConstraintMembership isLibraryElement 7424ee3b88e2988a 54 0 +RequirementConstraintMembership kind 504cd94854859f90 54 54 +RequirementConstraintMembership memberElement b94ff8f1604ba776 54 54 +RequirementConstraintMembership memberElementId 64b237266b48128c 54 54 +RequirementConstraintMembership memberName a190476b6ab1399a 54 23 +RequirementConstraintMembership memberShortName e0fcfa569375a7fa 54 0 +RequirementConstraintMembership membershipOwningNamespace 4f4dc952cd97d9cb 54 54 +RequirementConstraintMembership name e0fcfa569375a7fa 54 0 +RequirementConstraintMembership ownedAnnotation f825b3fdd215e998 54 0 +RequirementConstraintMembership ownedConstraint b94ff8f1604ba776 54 54 +RequirementConstraintMembership ownedElement f825b3fdd215e998 54 0 +RequirementConstraintMembership ownedMemberElement b94ff8f1604ba776 54 54 +RequirementConstraintMembership ownedMemberElementId 64b237266b48128c 54 54 +RequirementConstraintMembership ownedMemberFeature b94ff8f1604ba776 54 54 +RequirementConstraintMembership ownedMemberName a190476b6ab1399a 54 23 +RequirementConstraintMembership ownedMemberShortName ce6dc98c829c5d31 54 10 +RequirementConstraintMembership ownedRelatedElement 7e7d8d9bc10859d2 54 54 +RequirementConstraintMembership ownedRelationship f825b3fdd215e998 54 0 +RequirementConstraintMembership owner e0fcfa569375a7fa 54 0 +RequirementConstraintMembership owningMembership e0fcfa569375a7fa 54 0 +RequirementConstraintMembership owningNamespace e0fcfa569375a7fa 54 0 +RequirementConstraintMembership owningRelatedElement 4f4dc952cd97d9cb 54 54 +RequirementConstraintMembership owningRelationship e0fcfa569375a7fa 54 0 +RequirementConstraintMembership owningType 4f4dc952cd97d9cb 54 54 +RequirementConstraintMembership qualifiedName e0fcfa569375a7fa 54 0 +RequirementConstraintMembership referencedConstraint d0173992d0013505 54 54 +RequirementConstraintMembership relatedElement 319f7ebce5cff191 54 54 +RequirementConstraintMembership shortName e0fcfa569375a7fa 54 0 +RequirementConstraintMembership source 4680a56348ee9e29 54 54 +RequirementConstraintMembership target 7e7d8d9bc10859d2 54 54 +RequirementConstraintMembership textualRepresentation f825b3fdd215e998 54 0 +RequirementConstraintMembership visibility 41d29c504cd87d52 54 54 +RequirementDefinition actorParameter 1f15ad6d54e9a9b9 32 0 +RequirementDefinition aliasIds 1f15ad6d54e9a9b9 32 0 +RequirementDefinition assumedConstraint ccbe7a0789e225a3 32 2 +RequirementDefinition declaredName 0683a2e7350a0732 32 32 +RequirementDefinition declaredShortName 2179ca968a8bd370 32 7 +RequirementDefinition differencingType 1f15ad6d54e9a9b9 32 0 +RequirementDefinition directedFeature 556ab3b246715286 32 8 +RequirementDefinition directedUsage 556ab3b246715286 32 8 +RequirementDefinition documentation 77d537ca34e94d9b 32 19 +RequirementDefinition elementId fb265a8feb386968 32 32 +RequirementDefinition endFeature 1f15ad6d54e9a9b9 32 0 +RequirementDefinition expression 5b44033d599615f0 32 14 +RequirementDefinition feature 3b2b7e71293bd551 32 22 +RequirementDefinition featureMembership 137e0d849f8342e3 32 22 +RequirementDefinition framedConcern 1f15ad6d54e9a9b9 32 0 +RequirementDefinition importedMembership 1f15ad6d54e9a9b9 32 0 +RequirementDefinition inheritedFeature 1f15ad6d54e9a9b9 32 0 +RequirementDefinition inheritedMembership 1f15ad6d54e9a9b9 32 0 +RequirementDefinition input 556ab3b246715286 32 8 +RequirementDefinition intersectingType 1f15ad6d54e9a9b9 32 0 +RequirementDefinition isAbstract 6b5133b9536bd39d 32 0 +RequirementDefinition isConjugated 6b5133b9536bd39d 32 0 +RequirementDefinition isImpliedIncluded f1fcc79129b16c0d 32 32 +RequirementDefinition isIndividual 7636019f13ee12b7 32 0 +RequirementDefinition isLibraryElement 65774f87d62deaef 32 2 +RequirementDefinition isModelLevelEvaluable 6b5133b9536bd39d 32 0 +RequirementDefinition isSufficient 6b5133b9536bd39d 32 0 +RequirementDefinition isVariation 6b5133b9536bd39d 32 0 +RequirementDefinition member 40dee7ca35f5c5e0 32 25 +RequirementDefinition membership e82aa1919a09f7c2 32 25 +RequirementDefinition multiplicity 7636019f13ee12b7 32 0 +RequirementDefinition name 0683a2e7350a0732 32 32 +RequirementDefinition output 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedAction 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedAllocation 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedAnalysisCase 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedAnnotation 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedAttribute eecd4ad4eeacbb7d 32 14 +RequirementDefinition ownedCalculation 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedCase 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedConcern 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedConjugator 7636019f13ee12b7 32 0 +RequirementDefinition ownedConnection 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedConstraint 5b44033d599615f0 32 14 +RequirementDefinition ownedDifferencing 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedDisjoining 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedElement 40dee7ca35f5c5e0 32 25 +RequirementDefinition ownedEndFeature 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedEnumeration 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedFeature 3b2b7e71293bd551 32 22 +RequirementDefinition ownedFeatureMembership 137e0d849f8342e3 32 22 +RequirementDefinition ownedFlow 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedImport 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedInterface 556ab3b246715286 32 8 +RequirementDefinition ownedIntersecting 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedItem 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedMember 40dee7ca35f5c5e0 32 25 +RequirementDefinition ownedMembership e82aa1919a09f7c2 32 25 +RequirementDefinition ownedMetadata 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedOccurrence 5b44033d599615f0 32 14 +RequirementDefinition ownedPart 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedPort 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedReference 556ab3b246715286 32 8 +RequirementDefinition ownedRelationship ea8c3bedd65724f9 32 32 +RequirementDefinition ownedRendering 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedRequirement e63cb611652540de 32 1 +RequirementDefinition ownedSpecialization fbc9ba09b2b13c96 32 32 +RequirementDefinition ownedState 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedSubclassification fbc9ba09b2b13c96 32 32 +RequirementDefinition ownedTransition 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedUnioning 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedUsage 3b2b7e71293bd551 32 22 +RequirementDefinition ownedUseCase 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedVerificationCase 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedView 1f15ad6d54e9a9b9 32 0 +RequirementDefinition ownedViewpoint 1f15ad6d54e9a9b9 32 0 +RequirementDefinition owner b643fcf739895ad1 32 32 +RequirementDefinition owningMembership 8bf86ef8a325076a 32 32 +RequirementDefinition owningNamespace b643fcf739895ad1 32 32 +RequirementDefinition owningRelationship 8bf86ef8a325076a 32 32 +RequirementDefinition parameter 556ab3b246715286 32 8 +RequirementDefinition qualifiedName e74b6488887bd1c7 32 32 +RequirementDefinition reqId 7636019f13ee12b7 32 0 +RequirementDefinition requiredConstraint d05ed5779dc0fd4b 32 13 +RequirementDefinition result d8d0331b75785e5a 32 0 +RequirementDefinition shortName 2179ca968a8bd370 32 7 +RequirementDefinition stakeholderParameter 1f15ad6d54e9a9b9 32 0 +RequirementDefinition step 5b44033d599615f0 32 14 +RequirementDefinition subjectParameter bb1cdc6e94282f7a 32 8 +RequirementDefinition text 6e091a7366d74893 32 19 +RequirementDefinition textualRepresentation 1f15ad6d54e9a9b9 32 0 +RequirementDefinition unioningType 1f15ad6d54e9a9b9 32 0 +RequirementDefinition usage 3b2b7e71293bd551 32 22 +RequirementDefinition variant 1f15ad6d54e9a9b9 32 0 +RequirementDefinition variantMembership 1f15ad6d54e9a9b9 32 0 +RequirementUsage actorParameter 971b54713097b58b 135 0 +RequirementUsage aliasIds 971b54713097b58b 135 0 +RequirementUsage assumedConstraint fd06ef83cb233a76 135 17 +RequirementUsage behavior 34475cac14dcba05 135 75 +RequirementUsage chainingFeature 971b54713097b58b 135 0 +RequirementUsage constraintDefinition 3a0340253051a04d 135 75 +RequirementUsage crossFeature a89867c0736e855c 135 0 +RequirementUsage declaredName 0b1173beff4e4430 135 106 +RequirementUsage declaredShortName f7fe6460d74c0699 135 26 +RequirementUsage definition 34475cac14dcba05 135 75 +RequirementUsage differencingType 971b54713097b58b 135 0 +RequirementUsage directedFeature 26e47c6d2309c401 135 31 +RequirementUsage directedUsage 26e47c6d2309c401 135 31 +RequirementUsage direction 57b3ab4e7f200d60 135 6 +RequirementUsage documentation 0e7e9736baa4ee1b 135 37 +RequirementUsage elementId 530bf1b45b2c9518 135 135 +RequirementUsage endFeature 971b54713097b58b 135 0 +RequirementUsage endOwningType a89867c0736e855c 135 0 +RequirementUsage feature 442674b62fb6a9b3 135 74 +RequirementUsage featureMembership 05463e958264067d 135 74 +RequirementUsage featureTarget fe200c66cdb841a1 135 0 +RequirementUsage featuringType 971b54713097b58b 135 0 +RequirementUsage framedConcern 971b54713097b58b 135 0 +RequirementUsage function 3a0340253051a04d 135 75 +RequirementUsage importedMembership 971b54713097b58b 135 0 +RequirementUsage individualDefinition a89867c0736e855c 135 0 +RequirementUsage inheritedFeature 971b54713097b58b 135 0 +RequirementUsage inheritedMembership 971b54713097b58b 135 0 +RequirementUsage input 26e47c6d2309c401 135 31 +RequirementUsage intersectingType 971b54713097b58b 135 0 +RequirementUsage isAbstract d310cc2ebdb48b0f 135 3 +RequirementUsage isComposite 91e1df394409e366 135 86 +RequirementUsage isConjugated 2539ffa655aca030 135 0 +RequirementUsage isConstant 2539ffa655aca030 135 0 +RequirementUsage isDerived 2539ffa655aca030 135 0 +RequirementUsage isEnd 2539ffa655aca030 135 0 +RequirementUsage isImpliedIncluded fe8076bb45a257b3 135 135 +RequirementUsage isIndividual a89867c0736e855c 135 0 +RequirementUsage isLibraryElement 52063c1239072675 135 1 +RequirementUsage isModelLevelEvaluable 2539ffa655aca030 135 0 +RequirementUsage isOrdered 2539ffa655aca030 135 0 +RequirementUsage isPortion a89867c0736e855c 135 0 +RequirementUsage isReference 91d897285745147d 135 49 +RequirementUsage isSufficient a89867c0736e855c 135 0 +RequirementUsage isUnique e37b986fddb24f51 135 133 +RequirementUsage isVariable a89867c0736e855c 135 0 +RequirementUsage isVariation a6448fc2da5a04ca 135 2 +RequirementUsage mayTimeVary a89867c0736e855c 135 0 +RequirementUsage member e4564f553bd5525d 135 101 +RequirementUsage membership f67e6ebdf7f127d1 135 101 +RequirementUsage multiplicity 8a6ec3ddc603314f 135 2 +RequirementUsage name ee6e66eb496a6f75 135 132 +RequirementUsage nestedAction 971b54713097b58b 135 0 +RequirementUsage nestedAllocation b5a1a9984a10d152 135 1 +RequirementUsage nestedAnalysisCase 971b54713097b58b 135 0 +RequirementUsage nestedAttribute b4967afc49bc385b 135 14 +RequirementUsage nestedCalculation 971b54713097b58b 135 0 +RequirementUsage nestedCase 971b54713097b58b 135 0 +RequirementUsage nestedConcern 971b54713097b58b 135 0 +RequirementUsage nestedConnection b5a1a9984a10d152 135 1 +RequirementUsage nestedConstraint 4fc8df265930a587 135 44 +RequirementUsage nestedEnumeration 971b54713097b58b 135 0 +RequirementUsage nestedFlow 971b54713097b58b 135 0 +RequirementUsage nestedInterface 1b8ca3b2052b1539 135 43 +RequirementUsage nestedItem b5a1a9984a10d152 135 1 +RequirementUsage nestedMetadata 971b54713097b58b 135 0 +RequirementUsage nestedOccurrence 094d331c266179fd 135 46 +RequirementUsage nestedPart b5a1a9984a10d152 135 1 +RequirementUsage nestedPort c27acb5c36dcf9e2 135 2 +RequirementUsage nestedReference 1b8ca3b2052b1539 135 43 +RequirementUsage nestedRendering 971b54713097b58b 135 0 +RequirementUsage nestedRequirement 43b87cc04a023bb0 135 16 +RequirementUsage nestedState 971b54713097b58b 135 0 +RequirementUsage nestedTransition 971b54713097b58b 135 0 +RequirementUsage nestedUsage 442674b62fb6a9b3 135 74 +RequirementUsage nestedUseCase 971b54713097b58b 135 0 +RequirementUsage nestedVerificationCase 971b54713097b58b 135 0 +RequirementUsage nestedView 971b54713097b58b 135 0 +RequirementUsage nestedViewpoint 971b54713097b58b 135 0 +RequirementUsage occurrenceDefinition 34475cac14dcba05 135 75 +RequirementUsage output 971b54713097b58b 135 0 +RequirementUsage ownedAnnotation 971b54713097b58b 135 0 +RequirementUsage ownedConjugator a89867c0736e855c 135 0 +RequirementUsage ownedCrossSubsetting a89867c0736e855c 135 0 +RequirementUsage ownedDifferencing 971b54713097b58b 135 0 +RequirementUsage ownedDisjoining 971b54713097b58b 135 0 +RequirementUsage ownedElement 04557b1f93cc6796 135 101 +RequirementUsage ownedEndFeature 971b54713097b58b 135 0 +RequirementUsage ownedFeature 442674b62fb6a9b3 135 74 +RequirementUsage ownedFeatureChaining 971b54713097b58b 135 0 +RequirementUsage ownedFeatureInverting 971b54713097b58b 135 0 +RequirementUsage ownedFeatureMembership 05463e958264067d 135 74 +RequirementUsage ownedImport 5d6bf1fde5463629 135 1 +RequirementUsage ownedIntersecting 971b54713097b58b 135 0 +RequirementUsage ownedMember e4564f553bd5525d 135 101 +RequirementUsage ownedMembership f67e6ebdf7f127d1 135 101 +RequirementUsage ownedRedefinition df0bf58481fdb280 135 15 +RequirementUsage ownedReferenceSubsetting 0b7a52a3f738d444 135 5 +RequirementUsage ownedRelationship 5aca40f7b9d7f74b 135 135 +RequirementUsage ownedSpecialization 98b7ed0691284a0b 135 135 +RequirementUsage ownedSubsetting df919be03dd11819 135 135 +RequirementUsage ownedTypeFeaturing 971b54713097b58b 135 0 +RequirementUsage ownedTyping 95323301f40f3a63 135 57 +RequirementUsage ownedUnioning 971b54713097b58b 135 0 +RequirementUsage owner 9814296a323a9188 135 135 +RequirementUsage owningDefinition d938112150b7abf9 135 24 +RequirementUsage owningFeatureMembership 6e5a5674ee210674 135 92 +RequirementUsage owningMembership af6f8c12f86565ab 135 135 +RequirementUsage owningNamespace 9814296a323a9188 135 135 +RequirementUsage owningRelationship af6f8c12f86565ab 135 135 +RequirementUsage owningType 963c81fb42d9476d 135 92 +RequirementUsage owningUsage 659cd89a659020d0 135 68 +RequirementUsage parameter 26e47c6d2309c401 135 31 +RequirementUsage portionKind a89867c0736e855c 135 0 +RequirementUsage predicate 3a0340253051a04d 135 75 +RequirementUsage qualifiedName 6feb4a515cf67d15 135 132 +RequirementUsage reqId a89867c0736e855c 135 0 +RequirementUsage requiredConstraint f20f0992738acc03 135 21 +RequirementUsage requirementDefinition 3a0340253051a04d 135 75 +RequirementUsage result fe200c66cdb841a1 135 0 +RequirementUsage shortName e81cc3cff2d5ce04 135 28 +RequirementUsage stakeholderParameter 971b54713097b58b 135 0 +RequirementUsage subjectParameter 5a6ca1b6fa66131e 135 31 +RequirementUsage text 4c954254e84153a3 135 37 +RequirementUsage textualRepresentation 971b54713097b58b 135 0 +RequirementUsage type 34475cac14dcba05 135 75 +RequirementUsage unioningType 971b54713097b58b 135 0 +RequirementUsage usage 442674b62fb6a9b3 135 74 +RequirementUsage variant 7c974ce8d22bf721 135 2 +RequirementUsage variantMembership 7b93cdd1b7190459 135 2 +RequirementVerificationMembership aliasIds 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership declaredName 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership declaredShortName 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership documentation 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership elementId d543f32591c5fbe0 6 6 +RequirementVerificationMembership isImplied 31a98a6d196c7b74 6 0 +RequirementVerificationMembership isImpliedIncluded 97132b22845a8322 6 6 +RequirementVerificationMembership isLibraryElement 31a98a6d196c7b74 6 0 +RequirementVerificationMembership kind 3f0ae08f29380c58 6 6 +RequirementVerificationMembership memberElement 5dd243c26213f188 6 6 +RequirementVerificationMembership memberElementId 015cf84b022c2672 6 6 +RequirementVerificationMembership memberName d0e9b57755796da1 6 4 +RequirementVerificationMembership memberShortName 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership membershipOwningNamespace e99cb9a8bdd49862 6 6 +RequirementVerificationMembership name 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership ownedAnnotation 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership ownedConstraint 5dd243c26213f188 6 6 +RequirementVerificationMembership ownedElement 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership ownedMemberElement 5dd243c26213f188 6 6 +RequirementVerificationMembership ownedMemberElementId 015cf84b022c2672 6 6 +RequirementVerificationMembership ownedMemberFeature 5dd243c26213f188 6 6 +RequirementVerificationMembership ownedMemberName d0e9b57755796da1 6 4 +RequirementVerificationMembership ownedMemberShortName 075c6041bcfde4be 6 1 +RequirementVerificationMembership ownedRelatedElement 6315ccddd16181d4 6 6 +RequirementVerificationMembership ownedRelationship 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership ownedRequirement 5dd243c26213f188 6 6 +RequirementVerificationMembership owner 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership owningMembership 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership owningNamespace 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership owningRelatedElement e99cb9a8bdd49862 6 6 +RequirementVerificationMembership owningRelationship 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership owningType e99cb9a8bdd49862 6 6 +RequirementVerificationMembership qualifiedName 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership referencedConstraint 29f2b6314ee7b8e3 6 6 +RequirementVerificationMembership relatedElement b9380db3089114e0 6 6 +RequirementVerificationMembership shortName 3430f34ab9ca94ac 6 0 +RequirementVerificationMembership source 176cbc839ef24346 6 6 +RequirementVerificationMembership target 6315ccddd16181d4 6 6 +RequirementVerificationMembership textualRepresentation 4cd0c5a1b6246cba 6 0 +RequirementVerificationMembership verifiedRequirement 29f2b6314ee7b8e3 6 6 +RequirementVerificationMembership visibility b9c9db6a124c0900 6 6 +ResultExpressionMembership aliasIds e5dd4fe59392a009 105 0 +ResultExpressionMembership declaredName 8caa2072cf57d97c 105 0 +ResultExpressionMembership declaredShortName 8caa2072cf57d97c 105 0 +ResultExpressionMembership documentation e5dd4fe59392a009 105 0 +ResultExpressionMembership elementId 8142ce7969eabe68 105 105 +ResultExpressionMembership isImplied 9ec0708892517624 105 0 +ResultExpressionMembership isImpliedIncluded 1c3c7be153a3d771 105 105 +ResultExpressionMembership isLibraryElement 9ec0708892517624 105 0 +ResultExpressionMembership memberElement ce8d1bed0d9ff5f0 105 105 +ResultExpressionMembership memberElementId 891a56462e9610d1 105 105 +ResultExpressionMembership memberName 8caa2072cf57d97c 105 0 +ResultExpressionMembership memberShortName 8caa2072cf57d97c 105 0 +ResultExpressionMembership membershipOwningNamespace 4a61ba3b6131edc5 105 105 +ResultExpressionMembership name 8caa2072cf57d97c 105 0 +ResultExpressionMembership ownedAnnotation e5dd4fe59392a009 105 0 +ResultExpressionMembership ownedElement e5dd4fe59392a009 105 0 +ResultExpressionMembership ownedMemberElement ce8d1bed0d9ff5f0 105 105 +ResultExpressionMembership ownedMemberElementId 891a56462e9610d1 105 105 +ResultExpressionMembership ownedMemberFeature ce8d1bed0d9ff5f0 105 105 +ResultExpressionMembership ownedMemberName 8caa2072cf57d97c 105 0 +ResultExpressionMembership ownedMemberShortName 8caa2072cf57d97c 105 0 +ResultExpressionMembership ownedRelatedElement cc174a68e74d5586 105 105 +ResultExpressionMembership ownedRelationship e5dd4fe59392a009 105 0 +ResultExpressionMembership ownedResultExpression ce8d1bed0d9ff5f0 105 105 +ResultExpressionMembership owner 8caa2072cf57d97c 105 0 +ResultExpressionMembership owningMembership 8caa2072cf57d97c 105 0 +ResultExpressionMembership owningNamespace 8caa2072cf57d97c 105 0 +ResultExpressionMembership owningRelatedElement 4a61ba3b6131edc5 105 105 +ResultExpressionMembership owningRelationship 8caa2072cf57d97c 105 0 +ResultExpressionMembership owningType 4a61ba3b6131edc5 105 105 +ResultExpressionMembership qualifiedName 8caa2072cf57d97c 105 0 +ResultExpressionMembership relatedElement fa6aabd660690750 105 105 +ResultExpressionMembership shortName 8caa2072cf57d97c 105 0 +ResultExpressionMembership source 94de3607180f5c15 105 105 +ResultExpressionMembership target cc174a68e74d5586 105 105 +ResultExpressionMembership textualRepresentation e5dd4fe59392a009 105 0 +ResultExpressionMembership visibility 09fbeb566528ecb2 105 105 +ReturnParameterMembership aliasIds a8f9aecaeff899a7 157 0 +ReturnParameterMembership declaredName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership declaredShortName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership documentation a8f9aecaeff899a7 157 0 +ReturnParameterMembership elementId e9354790f3540934 157 157 +ReturnParameterMembership isImplied 5021ec1757d0395e 157 0 +ReturnParameterMembership isImpliedIncluded 650156ffcf74031f 157 157 +ReturnParameterMembership isLibraryElement 01f162fefd3e9c29 157 23 +ReturnParameterMembership memberElement 2664adae40e05dc8 157 157 +ReturnParameterMembership memberElementId 9efe72127aa3a685 157 157 +ReturnParameterMembership memberName ea88d8b90f583804 157 157 +ReturnParameterMembership memberShortName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership membershipOwningNamespace d91b55cecbfc1a21 157 157 +ReturnParameterMembership name 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership ownedAnnotation a8f9aecaeff899a7 157 0 +ReturnParameterMembership ownedElement a8f9aecaeff899a7 157 0 +ReturnParameterMembership ownedMemberElement 2664adae40e05dc8 157 157 +ReturnParameterMembership ownedMemberElementId 9efe72127aa3a685 157 157 +ReturnParameterMembership ownedMemberFeature 2664adae40e05dc8 157 157 +ReturnParameterMembership ownedMemberName ea88d8b90f583804 157 157 +ReturnParameterMembership ownedMemberParameter 2664adae40e05dc8 157 157 +ReturnParameterMembership ownedMemberShortName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership ownedRelatedElement 9d90063d68ca5f46 157 157 +ReturnParameterMembership ownedRelationship a8f9aecaeff899a7 157 0 +ReturnParameterMembership owner 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership owningMembership 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership owningNamespace 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership owningRelatedElement d91b55cecbfc1a21 157 157 +ReturnParameterMembership owningRelationship 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership owningType d91b55cecbfc1a21 157 157 +ReturnParameterMembership qualifiedName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership relatedElement 6f2f3df55e6e6e32 157 157 +ReturnParameterMembership shortName 9cbfa2d4f5e9517a 157 0 +ReturnParameterMembership source 76faaa603e327061 157 157 +ReturnParameterMembership target 9d90063d68ca5f46 157 157 +ReturnParameterMembership textualRepresentation a8f9aecaeff899a7 157 0 +ReturnParameterMembership visibility 636ccb1079f3a1bc 157 81 +SatisfyRequirementUsage actorParameter 68885785a8e480da 22 0 +SatisfyRequirementUsage aliasIds 68885785a8e480da 22 0 +SatisfyRequirementUsage assertedConstraint b50c142a1f184a64 22 18 +SatisfyRequirementUsage assumedConstraint 68885785a8e480da 22 0 +SatisfyRequirementUsage behavior 39cf6c5d2d3ecab8 22 9 +SatisfyRequirementUsage chainingFeature 68885785a8e480da 22 0 +SatisfyRequirementUsage constraintDefinition 18ec518fed14c1b7 22 9 +SatisfyRequirementUsage crossFeature 15305e32408be798 22 0 +SatisfyRequirementUsage declaredName 56702bd2010e6455 22 4 +SatisfyRequirementUsage declaredShortName 15305e32408be798 22 0 +SatisfyRequirementUsage definition 39cf6c5d2d3ecab8 22 9 +SatisfyRequirementUsage differencingType 68885785a8e480da 22 0 +SatisfyRequirementUsage directedFeature 0bd80be9160b9486 22 19 +SatisfyRequirementUsage directedUsage 0bd80be9160b9486 22 19 +SatisfyRequirementUsage direction 15305e32408be798 22 0 +SatisfyRequirementUsage documentation 68885785a8e480da 22 0 +SatisfyRequirementUsage elementId a73d186aab468088 22 22 +SatisfyRequirementUsage endFeature 68885785a8e480da 22 0 +SatisfyRequirementUsage endOwningType 15305e32408be798 22 0 +SatisfyRequirementUsage feature 00774b00e3ae16b6 22 19 +SatisfyRequirementUsage featureMembership ad3eb17662bdc9be 22 19 +SatisfyRequirementUsage featureTarget f83ed5d41a2fafd2 22 0 +SatisfyRequirementUsage featuringType 68885785a8e480da 22 0 +SatisfyRequirementUsage framedConcern 68885785a8e480da 22 0 +SatisfyRequirementUsage function 18ec518fed14c1b7 22 9 +SatisfyRequirementUsage importedMembership 68885785a8e480da 22 0 +SatisfyRequirementUsage individualDefinition 15305e32408be798 22 0 +SatisfyRequirementUsage inheritedFeature 68885785a8e480da 22 0 +SatisfyRequirementUsage inheritedMembership 68885785a8e480da 22 0 +SatisfyRequirementUsage input 0bd80be9160b9486 22 19 +SatisfyRequirementUsage intersectingType 68885785a8e480da 22 0 +SatisfyRequirementUsage isAbstract b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isComposite 3e7d8027a443615b 22 19 +SatisfyRequirementUsage isConjugated b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isConstant b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isDerived b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isEnd b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isImpliedIncluded 56b1065cf1cb9f2a 22 22 +SatisfyRequirementUsage isIndividual 15305e32408be798 22 0 +SatisfyRequirementUsage isLibraryElement b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isModelLevelEvaluable b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isNegated b966054c5f0c6916 22 2 +SatisfyRequirementUsage isOrdered b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage isPortion 15305e32408be798 22 0 +SatisfyRequirementUsage isReference cdf785f87b5b2cbb 22 3 +SatisfyRequirementUsage isSufficient 15305e32408be798 22 0 +SatisfyRequirementUsage isUnique 56b1065cf1cb9f2a 22 22 +SatisfyRequirementUsage isVariable 15305e32408be798 22 0 +SatisfyRequirementUsage isVariation b5c3ffc32dd2eeec 22 0 +SatisfyRequirementUsage mayTimeVary 15305e32408be798 22 0 +SatisfyRequirementUsage member f06175302d33e2b8 22 19 +SatisfyRequirementUsage membership 9c21c5a2f2556fc0 22 19 +SatisfyRequirementUsage multiplicity 15305e32408be798 22 0 +SatisfyRequirementUsage name b90dece13c3e1501 22 22 +SatisfyRequirementUsage nestedAction 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedAllocation 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedAnalysisCase 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedAttribute 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedCalculation 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedCase 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedConcern 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedConnection 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedConstraint 9e020885911bc758 22 2 +SatisfyRequirementUsage nestedEnumeration 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedFlow 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedInterface 0bd80be9160b9486 22 19 +SatisfyRequirementUsage nestedItem 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedMetadata 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedOccurrence 9e020885911bc758 22 2 +SatisfyRequirementUsage nestedPart 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedPort 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedReference 0bd80be9160b9486 22 19 +SatisfyRequirementUsage nestedRendering 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedRequirement 9e020885911bc758 22 2 +SatisfyRequirementUsage nestedState 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedTransition 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedUsage 00774b00e3ae16b6 22 19 +SatisfyRequirementUsage nestedUseCase 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedVerificationCase 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedView 68885785a8e480da 22 0 +SatisfyRequirementUsage nestedViewpoint 68885785a8e480da 22 0 +SatisfyRequirementUsage occurrenceDefinition 39cf6c5d2d3ecab8 22 9 +SatisfyRequirementUsage output 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedAnnotation 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedConjugator 15305e32408be798 22 0 +SatisfyRequirementUsage ownedCrossSubsetting 15305e32408be798 22 0 +SatisfyRequirementUsage ownedDifferencing 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedDisjoining 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedElement f06175302d33e2b8 22 19 +SatisfyRequirementUsage ownedEndFeature 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedFeature 00774b00e3ae16b6 22 19 +SatisfyRequirementUsage ownedFeatureChaining 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedFeatureInverting 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedFeatureMembership ad3eb17662bdc9be 22 19 +SatisfyRequirementUsage ownedImport 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedIntersecting 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedMember f06175302d33e2b8 22 19 +SatisfyRequirementUsage ownedMembership 9c21c5a2f2556fc0 22 19 +SatisfyRequirementUsage ownedRedefinition 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedReferenceSubsetting 69fba36d6cd0045f 22 18 +SatisfyRequirementUsage ownedRelationship 9cd6fb3ede5a21d9 22 22 +SatisfyRequirementUsage ownedSpecialization 716075834ece7a23 22 22 +SatisfyRequirementUsage ownedSubsetting 9494554511d4b7c2 22 22 +SatisfyRequirementUsage ownedTypeFeaturing 68885785a8e480da 22 0 +SatisfyRequirementUsage ownedTyping fa1b2ce4e192e967 22 4 +SatisfyRequirementUsage ownedUnioning 68885785a8e480da 22 0 +SatisfyRequirementUsage owner 12025e40702e9d92 22 22 +SatisfyRequirementUsage owningDefinition ed8be44b086c9d73 22 1 +SatisfyRequirementUsage owningFeatureMembership 29e6ce459b39c2f7 22 19 +SatisfyRequirementUsage owningMembership 50b47ac962a21435 22 22 +SatisfyRequirementUsage owningNamespace 12025e40702e9d92 22 22 +SatisfyRequirementUsage owningRelationship 50b47ac962a21435 22 22 +SatisfyRequirementUsage owningType d4a2a03b800c6b87 22 19 +SatisfyRequirementUsage owningUsage fc471a22b82bb5ac 22 18 +SatisfyRequirementUsage parameter 0bd80be9160b9486 22 19 +SatisfyRequirementUsage portionKind 15305e32408be798 22 0 +SatisfyRequirementUsage predicate 18ec518fed14c1b7 22 9 +SatisfyRequirementUsage qualifiedName 49e78b2893038473 22 22 +SatisfyRequirementUsage reqId 15305e32408be798 22 0 +SatisfyRequirementUsage requiredConstraint 68885785a8e480da 22 0 +SatisfyRequirementUsage requirementDefinition 18ec518fed14c1b7 22 9 +SatisfyRequirementUsage result f83ed5d41a2fafd2 22 0 +SatisfyRequirementUsage satisfiedRequirement b50c142a1f184a64 22 18 +SatisfyRequirementUsage satisfyingFeature c0390b207469a286 22 19 +SatisfyRequirementUsage shortName 15305e32408be798 22 0 +SatisfyRequirementUsage stakeholderParameter 68885785a8e480da 22 0 +SatisfyRequirementUsage subjectParameter 57d2943ff78266ad 22 19 +SatisfyRequirementUsage text 68885785a8e480da 22 0 +SatisfyRequirementUsage textualRepresentation 68885785a8e480da 22 0 +SatisfyRequirementUsage type 39cf6c5d2d3ecab8 22 9 +SatisfyRequirementUsage unioningType 68885785a8e480da 22 0 +SatisfyRequirementUsage usage 00774b00e3ae16b6 22 19 +SatisfyRequirementUsage variant 68885785a8e480da 22 0 +SatisfyRequirementUsage variantMembership 68885785a8e480da 22 0 +SelectExpression aliasIds 7da4538739bb7b2d 2 0 +SelectExpression argument 4c52f91853f5f472 2 2 +SelectExpression behavior 7da4538739bb7b2d 2 0 +SelectExpression chainingFeature 7da4538739bb7b2d 2 0 +SelectExpression crossFeature f613db5daf2145dd 2 0 +SelectExpression declaredName f613db5daf2145dd 2 0 +SelectExpression declaredShortName f613db5daf2145dd 2 0 +SelectExpression differencingType 7da4538739bb7b2d 2 0 +SelectExpression directedFeature d8166efcda9dd721 2 2 +SelectExpression direction f613db5daf2145dd 2 0 +SelectExpression documentation 7da4538739bb7b2d 2 0 +SelectExpression elementId b06117f2d250d368 2 2 +SelectExpression endFeature 7da4538739bb7b2d 2 0 +SelectExpression endOwningType f613db5daf2145dd 2 0 +SelectExpression feature d8166efcda9dd721 2 2 +SelectExpression featureMembership 077200833aa00eae 2 2 +SelectExpression featureTarget e3fae91dfac1071c 2 0 +SelectExpression featuringType 7da4538739bb7b2d 2 0 +SelectExpression function f613db5daf2145dd 2 0 +SelectExpression importedMembership 7da4538739bb7b2d 2 0 +SelectExpression inheritedFeature 7da4538739bb7b2d 2 0 +SelectExpression inheritedMembership 7da4538739bb7b2d 2 0 +SelectExpression input d8166efcda9dd721 2 2 +SelectExpression instantiatedType 3c327fac034bfc91 2 2 +SelectExpression intersectingType 7da4538739bb7b2d 2 0 +SelectExpression isAbstract f613db5daf2145dd 2 0 +SelectExpression isComposite f613db5daf2145dd 2 0 +SelectExpression isConjugated 50d4e5c4b410aaff 2 0 +SelectExpression isConstant f613db5daf2145dd 2 0 +SelectExpression isDerived f613db5daf2145dd 2 0 +SelectExpression isEnd f613db5daf2145dd 2 0 +SelectExpression isImpliedIncluded f3bc82fd5128f3b9 2 2 +SelectExpression isLibraryElement 50d4e5c4b410aaff 2 0 +SelectExpression isModelLevelEvaluable 50d4e5c4b410aaff 2 0 +SelectExpression isOrdered f613db5daf2145dd 2 0 +SelectExpression isPortion f613db5daf2145dd 2 0 +SelectExpression isSufficient f613db5daf2145dd 2 0 +SelectExpression isUnique f613db5daf2145dd 2 0 +SelectExpression isVariable f613db5daf2145dd 2 0 +SelectExpression member d8166efcda9dd721 2 2 +SelectExpression membership 077200833aa00eae 2 2 +SelectExpression multiplicity f613db5daf2145dd 2 0 +SelectExpression name f613db5daf2145dd 2 0 +SelectExpression operator 4af96b66f2bb3d25 2 2 +SelectExpression output 7da4538739bb7b2d 2 0 +SelectExpression ownedAnnotation 7da4538739bb7b2d 2 0 +SelectExpression ownedConjugator f613db5daf2145dd 2 0 +SelectExpression ownedCrossSubsetting f613db5daf2145dd 2 0 +SelectExpression ownedDifferencing 7da4538739bb7b2d 2 0 +SelectExpression ownedDisjoining 7da4538739bb7b2d 2 0 +SelectExpression ownedElement d8166efcda9dd721 2 2 +SelectExpression ownedEndFeature 7da4538739bb7b2d 2 0 +SelectExpression ownedFeature d8166efcda9dd721 2 2 +SelectExpression ownedFeatureChaining 7da4538739bb7b2d 2 0 +SelectExpression ownedFeatureInverting 7da4538739bb7b2d 2 0 +SelectExpression ownedFeatureMembership 077200833aa00eae 2 2 +SelectExpression ownedImport 7da4538739bb7b2d 2 0 +SelectExpression ownedIntersecting 7da4538739bb7b2d 2 0 +SelectExpression ownedMember d8166efcda9dd721 2 2 +SelectExpression ownedMembership 077200833aa00eae 2 2 +SelectExpression ownedRedefinition 7da4538739bb7b2d 2 0 +SelectExpression ownedReferenceSubsetting f613db5daf2145dd 2 0 +SelectExpression ownedRelationship 077200833aa00eae 2 2 +SelectExpression ownedSpecialization 7da4538739bb7b2d 2 0 +SelectExpression ownedSubsetting 7da4538739bb7b2d 2 0 +SelectExpression ownedTypeFeaturing 7da4538739bb7b2d 2 0 +SelectExpression ownedTyping 7da4538739bb7b2d 2 0 +SelectExpression ownedUnioning 7da4538739bb7b2d 2 0 +SelectExpression owner 55700bc23465687b 2 2 +SelectExpression owningFeatureMembership f613db5daf2145dd 2 0 +SelectExpression owningMembership 5889d7d8f7ad2b58 2 2 +SelectExpression owningNamespace 55700bc23465687b 2 2 +SelectExpression owningRelationship 5889d7d8f7ad2b58 2 2 +SelectExpression owningType f613db5daf2145dd 2 0 +SelectExpression parameter d8166efcda9dd721 2 2 +SelectExpression qualifiedName f613db5daf2145dd 2 0 +SelectExpression result e3fae91dfac1071c 2 0 +SelectExpression shortName f613db5daf2145dd 2 0 +SelectExpression textualRepresentation 7da4538739bb7b2d 2 0 +SelectExpression type 7da4538739bb7b2d 2 0 +SelectExpression unioningType 7da4538739bb7b2d 2 0 +SendActionUsage actionDefinition 0f31877d531b5a83 37 0 +SendActionUsage aliasIds 0f31877d531b5a83 37 0 +SendActionUsage behavior 0f31877d531b5a83 37 0 +SendActionUsage chainingFeature 0f31877d531b5a83 37 0 +SendActionUsage crossFeature 794ee8b26bff4de2 37 0 +SendActionUsage declaredName 26c6c9e62cf7337e 37 11 +SendActionUsage declaredShortName 794ee8b26bff4de2 37 0 +SendActionUsage definition 0f31877d531b5a83 37 0 +SendActionUsage differencingType 0f31877d531b5a83 37 0 +SendActionUsage directedFeature f6db1b8ae9ca8353 37 37 +SendActionUsage directedUsage f6db1b8ae9ca8353 37 37 +SendActionUsage direction 794ee8b26bff4de2 37 0 +SendActionUsage documentation 0f31877d531b5a83 37 0 +SendActionUsage elementId d8e3d1147f4e8ce8 37 37 +SendActionUsage endFeature 0f31877d531b5a83 37 0 +SendActionUsage endOwningType 794ee8b26bff4de2 37 0 +SendActionUsage feature f6db1b8ae9ca8353 37 37 +SendActionUsage featureMembership 26cada3fb8fa495a 37 37 +SendActionUsage featureTarget a54d5b5238367faf 37 0 +SendActionUsage featuringType 0f31877d531b5a83 37 0 +SendActionUsage importedMembership 0f31877d531b5a83 37 0 +SendActionUsage individualDefinition 794ee8b26bff4de2 37 0 +SendActionUsage inheritedFeature 0f31877d531b5a83 37 0 +SendActionUsage inheritedMembership 0f31877d531b5a83 37 0 +SendActionUsage input f6db1b8ae9ca8353 37 37 +SendActionUsage intersectingType 0f31877d531b5a83 37 0 +SendActionUsage isAbstract e364447561063eda 37 0 +SendActionUsage isComposite 0f05fa8dcdeef3f3 37 37 +SendActionUsage isConjugated e364447561063eda 37 0 +SendActionUsage isConstant e364447561063eda 37 0 +SendActionUsage isDerived e364447561063eda 37 0 +SendActionUsage isEnd e364447561063eda 37 0 +SendActionUsage isImpliedIncluded 0f05fa8dcdeef3f3 37 37 +SendActionUsage isIndividual 794ee8b26bff4de2 37 0 +SendActionUsage isLibraryElement e364447561063eda 37 0 +SendActionUsage isOrdered e364447561063eda 37 0 +SendActionUsage isPortion 794ee8b26bff4de2 37 0 +SendActionUsage isReference e364447561063eda 37 0 +SendActionUsage isSufficient 794ee8b26bff4de2 37 0 +SendActionUsage isUnique 0f05fa8dcdeef3f3 37 37 +SendActionUsage isVariable 794ee8b26bff4de2 37 0 +SendActionUsage isVariation e364447561063eda 37 0 +SendActionUsage mayTimeVary 794ee8b26bff4de2 37 0 +SendActionUsage member f6db1b8ae9ca8353 37 37 +SendActionUsage membership 26cada3fb8fa495a 37 37 +SendActionUsage multiplicity 794ee8b26bff4de2 37 0 +SendActionUsage name 26c6c9e62cf7337e 37 11 +SendActionUsage nestedAction 0f31877d531b5a83 37 0 +SendActionUsage nestedAllocation 0f31877d531b5a83 37 0 +SendActionUsage nestedAnalysisCase 0f31877d531b5a83 37 0 +SendActionUsage nestedAttribute 0f31877d531b5a83 37 0 +SendActionUsage nestedCalculation 0f31877d531b5a83 37 0 +SendActionUsage nestedCase 0f31877d531b5a83 37 0 +SendActionUsage nestedConcern 0f31877d531b5a83 37 0 +SendActionUsage nestedConnection 0f31877d531b5a83 37 0 +SendActionUsage nestedConstraint 0f31877d531b5a83 37 0 +SendActionUsage nestedEnumeration 0f31877d531b5a83 37 0 +SendActionUsage nestedFlow 0f31877d531b5a83 37 0 +SendActionUsage nestedInterface f6db1b8ae9ca8353 37 37 +SendActionUsage nestedItem 0f31877d531b5a83 37 0 +SendActionUsage nestedMetadata 0f31877d531b5a83 37 0 +SendActionUsage nestedOccurrence 0f31877d531b5a83 37 0 +SendActionUsage nestedPart 0f31877d531b5a83 37 0 +SendActionUsage nestedPort 0f31877d531b5a83 37 0 +SendActionUsage nestedReference f6db1b8ae9ca8353 37 37 +SendActionUsage nestedRendering 0f31877d531b5a83 37 0 +SendActionUsage nestedRequirement 0f31877d531b5a83 37 0 +SendActionUsage nestedState 0f31877d531b5a83 37 0 +SendActionUsage nestedTransition 0f31877d531b5a83 37 0 +SendActionUsage nestedUsage f6db1b8ae9ca8353 37 37 +SendActionUsage nestedUseCase 0f31877d531b5a83 37 0 +SendActionUsage nestedVerificationCase 0f31877d531b5a83 37 0 +SendActionUsage nestedView 0f31877d531b5a83 37 0 +SendActionUsage nestedViewpoint 0f31877d531b5a83 37 0 +SendActionUsage occurrenceDefinition 0f31877d531b5a83 37 0 +SendActionUsage output 0f31877d531b5a83 37 0 +SendActionUsage ownedAnnotation 0f31877d531b5a83 37 0 +SendActionUsage ownedConjugator 794ee8b26bff4de2 37 0 +SendActionUsage ownedCrossSubsetting 794ee8b26bff4de2 37 0 +SendActionUsage ownedDifferencing 0f31877d531b5a83 37 0 +SendActionUsage ownedDisjoining 0f31877d531b5a83 37 0 +SendActionUsage ownedElement f6db1b8ae9ca8353 37 37 +SendActionUsage ownedEndFeature 0f31877d531b5a83 37 0 +SendActionUsage ownedFeature f6db1b8ae9ca8353 37 37 +SendActionUsage ownedFeatureChaining 0f31877d531b5a83 37 0 +SendActionUsage ownedFeatureInverting 0f31877d531b5a83 37 0 +SendActionUsage ownedFeatureMembership 26cada3fb8fa495a 37 37 +SendActionUsage ownedImport 0f31877d531b5a83 37 0 +SendActionUsage ownedIntersecting 0f31877d531b5a83 37 0 +SendActionUsage ownedMember f6db1b8ae9ca8353 37 37 +SendActionUsage ownedMembership 26cada3fb8fa495a 37 37 +SendActionUsage ownedRedefinition 0f31877d531b5a83 37 0 +SendActionUsage ownedReferenceSubsetting 794ee8b26bff4de2 37 0 +SendActionUsage ownedRelationship 3ca458c7cdb49af8 37 37 +SendActionUsage ownedSpecialization 78664b91d9f0e58d 37 37 +SendActionUsage ownedSubsetting 78664b91d9f0e58d 37 37 +SendActionUsage ownedTypeFeaturing 0f31877d531b5a83 37 0 +SendActionUsage ownedTyping 0f31877d531b5a83 37 0 +SendActionUsage ownedUnioning 0f31877d531b5a83 37 0 +SendActionUsage owner 8988c4cbf4146866 37 37 +SendActionUsage owningDefinition 794ee8b26bff4de2 37 0 +SendActionUsage owningFeatureMembership f2f651e0e7873011 37 37 +SendActionUsage owningMembership f2f651e0e7873011 37 37 +SendActionUsage owningNamespace 8988c4cbf4146866 37 37 +SendActionUsage owningRelationship f2f651e0e7873011 37 37 +SendActionUsage owningType 8988c4cbf4146866 37 37 +SendActionUsage owningUsage 8988c4cbf4146866 37 37 +SendActionUsage parameter f6db1b8ae9ca8353 37 37 +SendActionUsage payloadArgument 7306dc3896f86bf6 37 35 +SendActionUsage portionKind 794ee8b26bff4de2 37 0 +SendActionUsage qualifiedName 70a4f42d4527545f 37 11 +SendActionUsage receiverArgument 09e8e7ad83c78958 37 23 +SendActionUsage senderArgument 0a8788f8d3ba5929 37 14 +SendActionUsage shortName 794ee8b26bff4de2 37 0 +SendActionUsage textualRepresentation 0f31877d531b5a83 37 0 +SendActionUsage type 0f31877d531b5a83 37 0 +SendActionUsage unioningType 0f31877d531b5a83 37 0 +SendActionUsage usage f6db1b8ae9ca8353 37 37 +SendActionUsage variant 0f31877d531b5a83 37 0 +SendActionUsage variantMembership 0f31877d531b5a83 37 0 +StakeholderMembership aliasIds 7971aa5800ae70da 7 0 +StakeholderMembership declaredName d470d1007b113661 7 0 +StakeholderMembership declaredShortName d470d1007b113661 7 0 +StakeholderMembership documentation 7971aa5800ae70da 7 0 +StakeholderMembership elementId 47c9a8d40cc9a404 7 7 +StakeholderMembership isImplied 1a1df35ba0b7acab 7 0 +StakeholderMembership isImpliedIncluded 8ba910ad17ca1076 7 7 +StakeholderMembership isLibraryElement 1a1df35ba0b7acab 7 0 +StakeholderMembership memberElement 5e794912befd2472 7 7 +StakeholderMembership memberElementId 710f4cffea7012af 7 7 +StakeholderMembership memberName 4db9e84ef1d8a727 7 7 +StakeholderMembership memberShortName d470d1007b113661 7 0 +StakeholderMembership membershipOwningNamespace 1efd7b6b01134720 7 7 +StakeholderMembership name d470d1007b113661 7 0 +StakeholderMembership ownedAnnotation 7971aa5800ae70da 7 0 +StakeholderMembership ownedElement 7971aa5800ae70da 7 0 +StakeholderMembership ownedMemberElement 5e794912befd2472 7 7 +StakeholderMembership ownedMemberElementId 710f4cffea7012af 7 7 +StakeholderMembership ownedMemberFeature 5e794912befd2472 7 7 +StakeholderMembership ownedMemberName 4db9e84ef1d8a727 7 7 +StakeholderMembership ownedMemberParameter 5e794912befd2472 7 7 +StakeholderMembership ownedMemberShortName d470d1007b113661 7 0 +StakeholderMembership ownedRelatedElement e05d19cf10753cc2 7 7 +StakeholderMembership ownedRelationship 7971aa5800ae70da 7 0 +StakeholderMembership ownedStakeholderParameter 5e794912befd2472 7 7 +StakeholderMembership owner d470d1007b113661 7 0 +StakeholderMembership owningMembership d470d1007b113661 7 0 +StakeholderMembership owningNamespace d470d1007b113661 7 0 +StakeholderMembership owningRelatedElement 1efd7b6b01134720 7 7 +StakeholderMembership owningRelationship d470d1007b113661 7 0 +StakeholderMembership owningType 1efd7b6b01134720 7 7 +StakeholderMembership qualifiedName d470d1007b113661 7 0 +StakeholderMembership relatedElement ecd4f50e9729e184 7 7 +StakeholderMembership shortName d470d1007b113661 7 0 +StakeholderMembership source 484c02d4451a5624 7 7 +StakeholderMembership target e05d19cf10753cc2 7 7 +StakeholderMembership textualRepresentation 7971aa5800ae70da 7 0 +StakeholderMembership visibility 1711f500877c174b 7 7 +StateDefinition action 3a0133fc7a343ab5 17 4 +StateDefinition aliasIds b54b27bfaaefbbed 17 0 +StateDefinition declaredName e321fac6550d376c 17 17 +StateDefinition declaredShortName 36b99177e665b758 17 0 +StateDefinition differencingType b54b27bfaaefbbed 17 0 +StateDefinition directedFeature 5a296b3106b3e579 17 1 +StateDefinition directedUsage 5a296b3106b3e579 17 1 +StateDefinition doAction b54fea08567c1d9e 17 1 +StateDefinition documentation b54b27bfaaefbbed 17 0 +StateDefinition elementId 802a0282e22a30a0 17 17 +StateDefinition endFeature b54b27bfaaefbbed 17 0 +StateDefinition entryAction 5147cd227c9a332f 17 2 +StateDefinition exitAction f4e876cc1decd517 17 1 +StateDefinition feature cb8b769c22a0fa64 17 5 +StateDefinition featureMembership 30ff3ad55c55aa40 17 5 +StateDefinition importedMembership b54b27bfaaefbbed 17 0 +StateDefinition inheritedFeature b54b27bfaaefbbed 17 0 +StateDefinition inheritedMembership b54b27bfaaefbbed 17 0 +StateDefinition input 5a296b3106b3e579 17 1 +StateDefinition intersectingType b54b27bfaaefbbed 17 0 +StateDefinition isAbstract 12e739ded7d68520 17 0 +StateDefinition isConjugated 12e739ded7d68520 17 0 +StateDefinition isImpliedIncluded 882454254121474d 17 17 +StateDefinition isIndividual 36b99177e665b758 17 0 +StateDefinition isLibraryElement 12e739ded7d68520 17 0 +StateDefinition isParallel 12e739ded7d68520 17 0 +StateDefinition isSufficient 12e739ded7d68520 17 0 +StateDefinition isVariation 12e739ded7d68520 17 0 +StateDefinition member cb8b769c22a0fa64 17 5 +StateDefinition membership 30ff3ad55c55aa40 17 5 +StateDefinition multiplicity 36b99177e665b758 17 0 +StateDefinition name e321fac6550d376c 17 17 +StateDefinition output b54b27bfaaefbbed 17 0 +StateDefinition ownedAction 3a0133fc7a343ab5 17 4 +StateDefinition ownedAllocation b54b27bfaaefbbed 17 0 +StateDefinition ownedAnalysisCase b54b27bfaaefbbed 17 0 +StateDefinition ownedAnnotation b54b27bfaaefbbed 17 0 +StateDefinition ownedAttribute b54b27bfaaefbbed 17 0 +StateDefinition ownedCalculation b54b27bfaaefbbed 17 0 +StateDefinition ownedCase b54b27bfaaefbbed 17 0 +StateDefinition ownedConcern b54b27bfaaefbbed 17 0 +StateDefinition ownedConjugator 36b99177e665b758 17 0 +StateDefinition ownedConnection 0e2e50bde5e7ff38 17 4 +StateDefinition ownedConstraint b54b27bfaaefbbed 17 0 +StateDefinition ownedDifferencing b54b27bfaaefbbed 17 0 +StateDefinition ownedDisjoining b54b27bfaaefbbed 17 0 +StateDefinition ownedElement cb8b769c22a0fa64 17 5 +StateDefinition ownedEndFeature b54b27bfaaefbbed 17 0 +StateDefinition ownedEnumeration b54b27bfaaefbbed 17 0 +StateDefinition ownedFeature cb8b769c22a0fa64 17 5 +StateDefinition ownedFeatureMembership 30ff3ad55c55aa40 17 5 +StateDefinition ownedFlow b54b27bfaaefbbed 17 0 +StateDefinition ownedImport b54b27bfaaefbbed 17 0 +StateDefinition ownedInterface 5a296b3106b3e579 17 1 +StateDefinition ownedIntersecting b54b27bfaaefbbed 17 0 +StateDefinition ownedItem 2ffea806ddff9cdf 17 1 +StateDefinition ownedMember cb8b769c22a0fa64 17 5 +StateDefinition ownedMembership 30ff3ad55c55aa40 17 5 +StateDefinition ownedMetadata b54b27bfaaefbbed 17 0 +StateDefinition ownedOccurrence e34641a0777e18a7 17 4 +StateDefinition ownedPart 2ffea806ddff9cdf 17 1 +StateDefinition ownedPort b54b27bfaaefbbed 17 0 +StateDefinition ownedReference 5a296b3106b3e579 17 1 +StateDefinition ownedRelationship 3d4d68b5b1bd3d5e 17 17 +StateDefinition ownedRendering b54b27bfaaefbbed 17 0 +StateDefinition ownedRequirement b54b27bfaaefbbed 17 0 +StateDefinition ownedSpecialization 6c5d727fe63517b3 17 17 +StateDefinition ownedState 434cc7ab1e69ed4b 17 4 +StateDefinition ownedSubclassification 6c5d727fe63517b3 17 17 +StateDefinition ownedTransition 77229bf3e842eead 17 4 +StateDefinition ownedUnioning b54b27bfaaefbbed 17 0 +StateDefinition ownedUsage cb8b769c22a0fa64 17 5 +StateDefinition ownedUseCase b54b27bfaaefbbed 17 0 +StateDefinition ownedVerificationCase b54b27bfaaefbbed 17 0 +StateDefinition ownedView b54b27bfaaefbbed 17 0 +StateDefinition ownedViewpoint b54b27bfaaefbbed 17 0 +StateDefinition owner 84d09fbaffdf70f0 17 17 +StateDefinition owningMembership 69cda2e490d7a63a 17 17 +StateDefinition owningNamespace 84d09fbaffdf70f0 17 17 +StateDefinition owningRelationship 69cda2e490d7a63a 17 17 +StateDefinition parameter 5a296b3106b3e579 17 1 +StateDefinition qualifiedName a2df02b8d93e4895 17 17 +StateDefinition shortName 36b99177e665b758 17 0 +StateDefinition state 434cc7ab1e69ed4b 17 4 +StateDefinition step 3a0133fc7a343ab5 17 4 +StateDefinition textualRepresentation b54b27bfaaefbbed 17 0 +StateDefinition unioningType b54b27bfaaefbbed 17 0 +StateDefinition usage cb8b769c22a0fa64 17 5 +StateDefinition variant b54b27bfaaefbbed 17 0 +StateDefinition variantMembership b54b27bfaaefbbed 17 0 +StateSubactionMembership action e0172ee4d2023052 56 56 +StateSubactionMembership aliasIds 1cba7f34cf2b9996 56 0 +StateSubactionMembership declaredName ffe60030f0ceb29a 56 0 +StateSubactionMembership declaredShortName ffe60030f0ceb29a 56 0 +StateSubactionMembership documentation 1cba7f34cf2b9996 56 0 +StateSubactionMembership elementId 10bc52c778fec7dc 56 56 +StateSubactionMembership isImplied f4cec0714aca08ae 56 0 +StateSubactionMembership isImpliedIncluded e7e796ad713ac00e 56 56 +StateSubactionMembership isLibraryElement f4cec0714aca08ae 56 0 +StateSubactionMembership kind 9153a955c4c98662 56 56 +StateSubactionMembership memberElement e0172ee4d2023052 56 56 +StateSubactionMembership memberElementId 7486f4d0441b3d32 56 56 +StateSubactionMembership memberName 64c196c15246e80e 56 37 +StateSubactionMembership memberShortName ffe60030f0ceb29a 56 0 +StateSubactionMembership membershipOwningNamespace 5d8b868501c90a4c 56 56 +StateSubactionMembership name ffe60030f0ceb29a 56 0 +StateSubactionMembership ownedAnnotation 1cba7f34cf2b9996 56 0 +StateSubactionMembership ownedElement 1cba7f34cf2b9996 56 0 +StateSubactionMembership ownedMemberElement e0172ee4d2023052 56 56 +StateSubactionMembership ownedMemberElementId 7486f4d0441b3d32 56 56 +StateSubactionMembership ownedMemberFeature e0172ee4d2023052 56 56 +StateSubactionMembership ownedMemberName 64c196c15246e80e 56 37 +StateSubactionMembership ownedMemberShortName ffe60030f0ceb29a 56 0 +StateSubactionMembership ownedRelatedElement 9c91c09d181bd802 56 56 +StateSubactionMembership ownedRelationship 1cba7f34cf2b9996 56 0 +StateSubactionMembership owner ffe60030f0ceb29a 56 0 +StateSubactionMembership owningMembership ffe60030f0ceb29a 56 0 +StateSubactionMembership owningNamespace ffe60030f0ceb29a 56 0 +StateSubactionMembership owningRelatedElement 5d8b868501c90a4c 56 56 +StateSubactionMembership owningRelationship ffe60030f0ceb29a 56 0 +StateSubactionMembership owningType 5d8b868501c90a4c 56 56 +StateSubactionMembership qualifiedName ffe60030f0ceb29a 56 0 +StateSubactionMembership relatedElement ef0dc36056002d44 56 56 +StateSubactionMembership shortName ffe60030f0ceb29a 56 0 +StateSubactionMembership source 85c1ca99c83c3508 56 56 +StateSubactionMembership target 9c91c09d181bd802 56 56 +StateSubactionMembership textualRepresentation 1cba7f34cf2b9996 56 0 +StateSubactionMembership visibility 1394064d236286d2 56 56 +StateUsage actionDefinition 758d5d82f479d6c1 131 11 +StateUsage aliasIds a920af2ca7526091 131 0 +StateUsage behavior 758d5d82f479d6c1 131 11 +StateUsage chainingFeature a920af2ca7526091 131 0 +StateUsage crossFeature d0fc20f6ef15294e 131 0 +StateUsage declaredName 4b32be2d22f0c624 131 131 +StateUsage declaredShortName d0fc20f6ef15294e 131 0 +StateUsage definition 758d5d82f479d6c1 131 11 +StateUsage differencingType a920af2ca7526091 131 0 +StateUsage directedFeature 09dde6b498bf51e7 131 4 +StateUsage directedUsage 09dde6b498bf51e7 131 4 +StateUsage direction d0fc20f6ef15294e 131 0 +StateUsage doAction 8b3ebbe3b69cfaed 131 17 +StateUsage documentation 3197b5f5c680bf3b 131 2 +StateUsage elementId aed47d2aa0255dd4 131 131 +StateUsage endFeature a920af2ca7526091 131 0 +StateUsage endOwningType d0fc20f6ef15294e 131 0 +StateUsage entryAction a8421c9a616ae59d 131 25 +StateUsage exitAction f29146fad05e7d73 131 6 +StateUsage feature 95e2dfb83096022d 131 49 +StateUsage featureMembership a74117b83aad8fce 131 49 +StateUsage featureTarget 3c201fcd6d6ee9f1 131 0 +StateUsage featuringType a920af2ca7526091 131 0 +StateUsage importedMembership a920af2ca7526091 131 0 +StateUsage individualDefinition d0fc20f6ef15294e 131 0 +StateUsage inheritedFeature a920af2ca7526091 131 0 +StateUsage inheritedMembership a920af2ca7526091 131 0 +StateUsage input 09dde6b498bf51e7 131 4 +StateUsage intersectingType a920af2ca7526091 131 0 +StateUsage isAbstract f72fb195fb17de6a 131 0 +StateUsage isComposite dbcd814b6b042a64 131 114 +StateUsage isConjugated f72fb195fb17de6a 131 0 +StateUsage isConstant f72fb195fb17de6a 131 0 +StateUsage isDerived f72fb195fb17de6a 131 0 +StateUsage isEnd f72fb195fb17de6a 131 0 +StateUsage isImpliedIncluded bff5fbc326def531 131 131 +StateUsage isIndividual d0fc20f6ef15294e 131 0 +StateUsage isLibraryElement f72fb195fb17de6a 131 0 +StateUsage isOrdered f72fb195fb17de6a 131 0 +StateUsage isParallel f452c03d920a8b52 131 8 +StateUsage isPortion d0fc20f6ef15294e 131 0 +StateUsage isReference db582c0db6f2a937 131 17 +StateUsage isSufficient d0fc20f6ef15294e 131 0 +StateUsage isUnique 784b6847fcab1e74 131 130 +StateUsage isVariable d0fc20f6ef15294e 131 0 +StateUsage isVariation f72fb195fb17de6a 131 0 +StateUsage mayTimeVary d0fc20f6ef15294e 131 0 +StateUsage member fd12fa3e9019bd98 131 51 +StateUsage membership 689df57dfa7cbb60 131 51 +StateUsage multiplicity ceaa2f688dd97d68 131 1 +StateUsage name 4b32be2d22f0c624 131 131 +StateUsage nestedAction 9a19853daca1500e 131 49 +StateUsage nestedAllocation a920af2ca7526091 131 0 +StateUsage nestedAnalysisCase a920af2ca7526091 131 0 +StateUsage nestedAttribute a920af2ca7526091 131 0 +StateUsage nestedCalculation a920af2ca7526091 131 0 +StateUsage nestedCase a920af2ca7526091 131 0 +StateUsage nestedConcern a920af2ca7526091 131 0 +StateUsage nestedConnection bcbcb0140157754d 131 14 +StateUsage nestedConstraint 883afceb430a7102 131 3 +StateUsage nestedEnumeration a920af2ca7526091 131 0 +StateUsage nestedFlow a920af2ca7526091 131 0 +StateUsage nestedInterface ecc89223ce9ee131 131 5 +StateUsage nestedItem a920af2ca7526091 131 0 +StateUsage nestedMetadata a920af2ca7526091 131 0 +StateUsage nestedOccurrence c91c0e30a0c6778f 131 49 +StateUsage nestedPart a920af2ca7526091 131 0 +StateUsage nestedPort a920af2ca7526091 131 0 +StateUsage nestedReference ecc89223ce9ee131 131 5 +StateUsage nestedRendering a920af2ca7526091 131 0 +StateUsage nestedRequirement a920af2ca7526091 131 0 +StateUsage nestedState 56c0868c9889b46e 131 36 +StateUsage nestedTransition 068c6c7b972c15b2 131 24 +StateUsage nestedUsage 95e2dfb83096022d 131 49 +StateUsage nestedUseCase a920af2ca7526091 131 0 +StateUsage nestedVerificationCase a920af2ca7526091 131 0 +StateUsage nestedView a920af2ca7526091 131 0 +StateUsage nestedViewpoint a920af2ca7526091 131 0 +StateUsage occurrenceDefinition 758d5d82f479d6c1 131 11 +StateUsage output a920af2ca7526091 131 0 +StateUsage ownedAnnotation a920af2ca7526091 131 0 +StateUsage ownedConjugator d0fc20f6ef15294e 131 0 +StateUsage ownedCrossSubsetting d0fc20f6ef15294e 131 0 +StateUsage ownedDifferencing a920af2ca7526091 131 0 +StateUsage ownedDisjoining a920af2ca7526091 131 0 +StateUsage ownedElement fd12fa3e9019bd98 131 51 +StateUsage ownedEndFeature a920af2ca7526091 131 0 +StateUsage ownedFeature 95e2dfb83096022d 131 49 +StateUsage ownedFeatureChaining a920af2ca7526091 131 0 +StateUsage ownedFeatureInverting a920af2ca7526091 131 0 +StateUsage ownedFeatureMembership a74117b83aad8fce 131 49 +StateUsage ownedImport a920af2ca7526091 131 0 +StateUsage ownedIntersecting a920af2ca7526091 131 0 +StateUsage ownedMember fd12fa3e9019bd98 131 51 +StateUsage ownedMembership 689df57dfa7cbb60 131 51 +StateUsage ownedRedefinition a920af2ca7526091 131 0 +StateUsage ownedReferenceSubsetting d0fc20f6ef15294e 131 0 +StateUsage ownedRelationship 9945282fc2292d7a 131 131 +StateUsage ownedSpecialization a402c21118bb2235 131 131 +StateUsage ownedSubsetting 570ce413940316b9 131 131 +StateUsage ownedTypeFeaturing a920af2ca7526091 131 0 +StateUsage ownedTyping f2b61fb1d025230f 131 11 +StateUsage ownedUnioning a920af2ca7526091 131 0 +StateUsage owner 708418263299a31e 131 131 +StateUsage owningDefinition 1bbb091ae2c11c8a 131 14 +StateUsage owningFeatureMembership 4a05caff3979e654 131 114 +StateUsage owningMembership ed99844d5eee6522 131 131 +StateUsage owningNamespace 708418263299a31e 131 131 +StateUsage owningRelationship ed99844d5eee6522 131 131 +StateUsage owningType 36486c8bcae4c475 131 114 +StateUsage owningUsage eb898467d738d139 131 100 +StateUsage parameter 09dde6b498bf51e7 131 4 +StateUsage portionKind d0fc20f6ef15294e 131 0 +StateUsage qualifiedName eb925fa30ee60fdd 131 131 +StateUsage shortName d0fc20f6ef15294e 131 0 +StateUsage stateDefinition 758d5d82f479d6c1 131 11 +StateUsage textualRepresentation a920af2ca7526091 131 0 +StateUsage type 758d5d82f479d6c1 131 11 +StateUsage unioningType a920af2ca7526091 131 0 +StateUsage usage 95e2dfb83096022d 131 49 +StateUsage variant a920af2ca7526091 131 0 +StateUsage variantMembership a920af2ca7526091 131 0 +Subclassification aliasIds 462ecda113f17213 1151 0 +Subclassification declaredName 52a7a144febaf5a4 1151 0 +Subclassification declaredShortName 52a7a144febaf5a4 1151 0 +Subclassification documentation 462ecda113f17213 1151 0 +Subclassification elementId 0ac6c92666fefcc0 1151 1151 +Subclassification general a3c86d894e5d6915 1151 1151 +Subclassification isImplied 1fea74f056634ad2 1151 898 +Subclassification isImpliedIncluded 3b51657e29b1edc3 1151 1151 +Subclassification isLibraryElement 710e381d67c05b9a 1151 58 +Subclassification name 52a7a144febaf5a4 1151 0 +Subclassification ownedAnnotation 462ecda113f17213 1151 0 +Subclassification ownedElement 462ecda113f17213 1151 0 +Subclassification ownedRelatedElement 462ecda113f17213 1151 0 +Subclassification ownedRelationship 462ecda113f17213 1151 0 +Subclassification owner 52a7a144febaf5a4 1151 0 +Subclassification owningClassifier 82cb232410ebc59b 1151 1151 +Subclassification owningMembership 52a7a144febaf5a4 1151 0 +Subclassification owningNamespace 52a7a144febaf5a4 1151 0 +Subclassification owningRelatedElement 82cb232410ebc59b 1151 1151 +Subclassification owningRelationship 52a7a144febaf5a4 1151 0 +Subclassification owningType 82cb232410ebc59b 1151 1151 +Subclassification qualifiedName 52a7a144febaf5a4 1151 0 +Subclassification relatedElement dcddd7a1ec8c4749 1151 1151 +Subclassification shortName 52a7a144febaf5a4 1151 0 +Subclassification source a207debe43f54c67 1151 1151 +Subclassification specific 82cb232410ebc59b 1151 1151 +Subclassification subclassifier 82cb232410ebc59b 1151 1151 +Subclassification superclassifier a3c86d894e5d6915 1151 1151 +Subclassification target a465d718b3b7de31 1151 1151 +Subclassification textualRepresentation 462ecda113f17213 1151 0 +SubjectMembership aliasIds 13ef2b698bc8406b 122 0 +SubjectMembership declaredName ab175383ef2eb23b 122 0 +SubjectMembership declaredShortName ab175383ef2eb23b 122 0 +SubjectMembership documentation 13ef2b698bc8406b 122 0 +SubjectMembership elementId cd4fd3dc715fb25c 122 122 +SubjectMembership isImplied 4a7d2d486e35d885 122 0 +SubjectMembership isImpliedIncluded 041a072ac80a146f 122 122 +SubjectMembership isLibraryElement 4a7d2d486e35d885 122 0 +SubjectMembership memberElement 6a62627be86e27ef 122 122 +SubjectMembership memberElementId 4a18cda493cd881b 122 122 +SubjectMembership memberName d3b62ff4afae6427 122 122 +SubjectMembership memberShortName ab175383ef2eb23b 122 0 +SubjectMembership membershipOwningNamespace 2213b287f7598a80 122 122 +SubjectMembership name ab175383ef2eb23b 122 0 +SubjectMembership ownedAnnotation 13ef2b698bc8406b 122 0 +SubjectMembership ownedElement 13ef2b698bc8406b 122 0 +SubjectMembership ownedMemberElement 6a62627be86e27ef 122 122 +SubjectMembership ownedMemberElementId 4a18cda493cd881b 122 122 +SubjectMembership ownedMemberFeature 6a62627be86e27ef 122 122 +SubjectMembership ownedMemberName d3b62ff4afae6427 122 122 +SubjectMembership ownedMemberParameter 6a62627be86e27ef 122 122 +SubjectMembership ownedMemberShortName ab175383ef2eb23b 122 0 +SubjectMembership ownedRelatedElement 2df48626c8fdde57 122 122 +SubjectMembership ownedRelationship 13ef2b698bc8406b 122 0 +SubjectMembership ownedSubjectParameter 6a62627be86e27ef 122 122 +SubjectMembership owner ab175383ef2eb23b 122 0 +SubjectMembership owningMembership ab175383ef2eb23b 122 0 +SubjectMembership owningNamespace ab175383ef2eb23b 122 0 +SubjectMembership owningRelatedElement 2213b287f7598a80 122 122 +SubjectMembership owningRelationship ab175383ef2eb23b 122 0 +SubjectMembership owningType 2213b287f7598a80 122 122 +SubjectMembership qualifiedName ab175383ef2eb23b 122 0 +SubjectMembership relatedElement 5b865f37658ad3be 122 122 +SubjectMembership shortName ab175383ef2eb23b 122 0 +SubjectMembership source 865660f3bc6f5abe 122 122 +SubjectMembership target 2df48626c8fdde57 122 122 +SubjectMembership textualRepresentation 13ef2b698bc8406b 122 0 +SubjectMembership visibility 75a79b2d6684c37d 122 103 +Subsetting aliasIds cdd7bc01dd3a2b36 3167 0 +Subsetting declaredName d802aee440a539ad 3167 0 +Subsetting declaredShortName d802aee440a539ad 3167 0 +Subsetting documentation cdd7bc01dd3a2b36 3167 0 +Subsetting elementId 02f40e17d77d17ac 3167 3167 +Subsetting general 43a56166e5d279a6 3167 3167 +Subsetting isImplied 0678e514d4e8007c 3167 2761 +Subsetting isImpliedIncluded a31107e00ccc6f7a 3167 3167 +Subsetting isLibraryElement f6650ca5b043772b 3167 52 +Subsetting name d802aee440a539ad 3167 0 +Subsetting ownedAnnotation cdd7bc01dd3a2b36 3167 0 +Subsetting ownedElement 0bce73257f3dea59 3167 6 +Subsetting ownedRelatedElement dbe54c3fc5d47f8d 3167 8 +Subsetting ownedRelationship 650a174e260c1271 3167 6 +Subsetting owner d802aee440a539ad 3167 0 +Subsetting owningFeature 2bed2cba045fca8c 3167 3167 +Subsetting owningMembership d802aee440a539ad 3167 0 +Subsetting owningNamespace d802aee440a539ad 3167 0 +Subsetting owningRelatedElement 2bed2cba045fca8c 3167 3167 +Subsetting owningRelationship d802aee440a539ad 3167 0 +Subsetting owningType 2bed2cba045fca8c 3167 3167 +Subsetting qualifiedName d802aee440a539ad 3167 0 +Subsetting relatedElement e0b2473f8f8f47d2 3167 3167 +Subsetting shortName d802aee440a539ad 3167 0 +Subsetting source c9c01831a7a5fc34 3167 3167 +Subsetting specific 2bed2cba045fca8c 3167 3167 +Subsetting subsettedFeature 43a56166e5d279a6 3167 3167 +Subsetting subsettingFeature 2bed2cba045fca8c 3167 3167 +Subsetting target c156476cd4745d0a 3167 3167 +Subsetting textualRepresentation 0bce73257f3dea59 3167 6 +SuccessionAsUsage aliasIds d5400e2f88ea9a92 356 0 +SuccessionAsUsage association c4376bd39c895bd4 356 2 +SuccessionAsUsage chainingFeature d5400e2f88ea9a92 356 0 +SuccessionAsUsage connectorEnd 8c7030b92a19e9a7 356 356 +SuccessionAsUsage crossFeature 012077da79fc58ca 356 0 +SuccessionAsUsage declaredName 36ab6ad4428a518d 356 2 +SuccessionAsUsage declaredShortName 012077da79fc58ca 356 0 +SuccessionAsUsage defaultFeaturingType cfdd98a2201c4f1c 356 218 +SuccessionAsUsage definition c4376bd39c895bd4 356 2 +SuccessionAsUsage differencingType d5400e2f88ea9a92 356 0 +SuccessionAsUsage directedFeature d5400e2f88ea9a92 356 0 +SuccessionAsUsage directedUsage d5400e2f88ea9a92 356 0 +SuccessionAsUsage direction 012077da79fc58ca 356 0 +SuccessionAsUsage documentation d5400e2f88ea9a92 356 0 +SuccessionAsUsage elementId 18073f9191bf59bc 356 356 +SuccessionAsUsage endFeature 8c7030b92a19e9a7 356 356 +SuccessionAsUsage endOwningType 012077da79fc58ca 356 0 +SuccessionAsUsage feature 8c7030b92a19e9a7 356 356 +SuccessionAsUsage featureMembership 4f1b60c56d0b6e88 356 356 +SuccessionAsUsage featureTarget 548c0d773478aa44 356 0 +SuccessionAsUsage featuringType d5400e2f88ea9a92 356 0 +SuccessionAsUsage importedMembership d5400e2f88ea9a92 356 0 +SuccessionAsUsage inheritedFeature d5400e2f88ea9a92 356 0 +SuccessionAsUsage inheritedMembership d5400e2f88ea9a92 356 0 +SuccessionAsUsage input d5400e2f88ea9a92 356 0 +SuccessionAsUsage intersectingType d5400e2f88ea9a92 356 0 +SuccessionAsUsage isAbstract 9e7dbb2f8a89d02a 356 0 +SuccessionAsUsage isComposite b6a2658f4713cabe 356 0 +SuccessionAsUsage isConjugated b6a2658f4713cabe 356 0 +SuccessionAsUsage isConstant 9e7dbb2f8a89d02a 356 0 +SuccessionAsUsage isDerived 9e7dbb2f8a89d02a 356 0 +SuccessionAsUsage isEnd 9e7dbb2f8a89d02a 356 0 +SuccessionAsUsage isImplied 012077da79fc58ca 356 0 +SuccessionAsUsage isImpliedIncluded 42d1c513cb61a322 356 356 +SuccessionAsUsage isLibraryElement b6a2658f4713cabe 356 0 +SuccessionAsUsage isOrdered 9e7dbb2f8a89d02a 356 0 +SuccessionAsUsage isPortion 012077da79fc58ca 356 0 +SuccessionAsUsage isReference 42d1c513cb61a322 356 356 +SuccessionAsUsage isSufficient 012077da79fc58ca 356 0 +SuccessionAsUsage isUnique 07eca5a3f5660a21 356 107 +SuccessionAsUsage isVariable 012077da79fc58ca 356 0 +SuccessionAsUsage isVariation b6a2658f4713cabe 356 0 +SuccessionAsUsage mayTimeVary 012077da79fc58ca 356 0 +SuccessionAsUsage member 909f5a4cb644dc2d 356 356 +SuccessionAsUsage membership 877e06218e4285ba 356 356 +SuccessionAsUsage multiplicity 012077da79fc58ca 356 0 +SuccessionAsUsage name 36ab6ad4428a518d 356 2 +SuccessionAsUsage nestedAction d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedAllocation d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedAnalysisCase d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedAttribute d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedCalculation d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedCase d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedConcern d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedConnection d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedConstraint d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedEnumeration d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedFlow d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedInterface 8c7030b92a19e9a7 356 356 +SuccessionAsUsage nestedItem d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedMetadata d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedOccurrence d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedPart d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedPort d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedReference 8c7030b92a19e9a7 356 356 +SuccessionAsUsage nestedRendering d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedRequirement d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedState d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedTransition d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedUsage 8c7030b92a19e9a7 356 356 +SuccessionAsUsage nestedUseCase d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedVerificationCase d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedView d5400e2f88ea9a92 356 0 +SuccessionAsUsage nestedViewpoint d5400e2f88ea9a92 356 0 +SuccessionAsUsage output d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedAnnotation d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedConjugator 012077da79fc58ca 356 0 +SuccessionAsUsage ownedCrossSubsetting 012077da79fc58ca 356 0 +SuccessionAsUsage ownedDifferencing d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedDisjoining d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedElement 909f5a4cb644dc2d 356 356 +SuccessionAsUsage ownedEndFeature 8c7030b92a19e9a7 356 356 +SuccessionAsUsage ownedFeature 8c7030b92a19e9a7 356 356 +SuccessionAsUsage ownedFeatureChaining d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedFeatureInverting d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedFeatureMembership 4f1b60c56d0b6e88 356 356 +SuccessionAsUsage ownedImport d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedIntersecting d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedMember 909f5a4cb644dc2d 356 356 +SuccessionAsUsage ownedMembership 877e06218e4285ba 356 356 +SuccessionAsUsage ownedRedefinition d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedReferenceSubsetting 012077da79fc58ca 356 0 +SuccessionAsUsage ownedRelatedElement d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedRelationship 7812a74b6c3aa4aa 356 356 +SuccessionAsUsage ownedSpecialization c60973f7965c7e66 356 2 +SuccessionAsUsage ownedSubsetting d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedTypeFeaturing d5400e2f88ea9a92 356 0 +SuccessionAsUsage ownedTyping c60973f7965c7e66 356 2 +SuccessionAsUsage ownedUnioning d5400e2f88ea9a92 356 0 +SuccessionAsUsage owner 1678c4e7be770a11 356 356 +SuccessionAsUsage owningDefinition 8c0145577a58c25d 356 50 +SuccessionAsUsage owningFeatureMembership 5d4a0b72cb281e8c 356 245 +SuccessionAsUsage owningMembership 40a4315b27313067 356 356 +SuccessionAsUsage owningNamespace 1678c4e7be770a11 356 356 +SuccessionAsUsage owningRelatedElement 012077da79fc58ca 356 0 +SuccessionAsUsage owningRelationship 40a4315b27313067 356 356 +SuccessionAsUsage owningType 638d27ea01b3830a 356 245 +SuccessionAsUsage owningUsage d8ac5a6d01571977 356 195 +SuccessionAsUsage qualifiedName a10c5b10da92029f 356 2 +SuccessionAsUsage relatedElement d5400e2f88ea9a92 356 0 +SuccessionAsUsage relatedFeature 2c4fce7aa318d8e6 356 218 +SuccessionAsUsage shortName 012077da79fc58ca 356 0 +SuccessionAsUsage source d5400e2f88ea9a92 356 0 +SuccessionAsUsage sourceFeature f724583f95bacdc4 356 218 +SuccessionAsUsage target d5400e2f88ea9a92 356 0 +SuccessionAsUsage targetFeature afb235c93d6ab67a 356 55 +SuccessionAsUsage textualRepresentation d5400e2f88ea9a92 356 0 +SuccessionAsUsage type c4376bd39c895bd4 356 2 +SuccessionAsUsage unioningType d5400e2f88ea9a92 356 0 +SuccessionAsUsage usage 8c7030b92a19e9a7 356 356 +SuccessionAsUsage variant d5400e2f88ea9a92 356 0 +SuccessionAsUsage variantMembership d5400e2f88ea9a92 356 0 +SuccessionFlowUsage actionDefinition 1a16647131364873 4 0 +SuccessionFlowUsage aliasIds 1a16647131364873 4 0 +SuccessionFlowUsage association 1a16647131364873 4 0 +SuccessionFlowUsage behavior 1a16647131364873 4 0 +SuccessionFlowUsage chainingFeature 1a16647131364873 4 0 +SuccessionFlowUsage connectorEnd 79866851bc43f5cb 4 4 +SuccessionFlowUsage crossFeature 92150e0a7bf2a241 4 0 +SuccessionFlowUsage declaredName f1d04f23da686403 4 2 +SuccessionFlowUsage declaredShortName 92150e0a7bf2a241 4 0 +SuccessionFlowUsage defaultFeaturingType 745e5f756b1bf617 4 4 +SuccessionFlowUsage definition 1a16647131364873 4 0 +SuccessionFlowUsage differencingType 1a16647131364873 4 0 +SuccessionFlowUsage directedFeature 1a16647131364873 4 0 +SuccessionFlowUsage directedUsage 1a16647131364873 4 0 +SuccessionFlowUsage direction 92150e0a7bf2a241 4 0 +SuccessionFlowUsage documentation 1a16647131364873 4 0 +SuccessionFlowUsage elementId e818b1dd4491d918 4 4 +SuccessionFlowUsage endFeature 79866851bc43f5cb 4 4 +SuccessionFlowUsage endOwningType 92150e0a7bf2a241 4 0 +SuccessionFlowUsage feature 79866851bc43f5cb 4 4 +SuccessionFlowUsage featureMembership 8798b973d8c0f0bd 4 4 +SuccessionFlowUsage featureTarget 1db9f3d1405136e6 4 0 +SuccessionFlowUsage featuringType 1a16647131364873 4 0 +SuccessionFlowUsage flowDefinition 1a16647131364873 4 0 +SuccessionFlowUsage flowEnd 79866851bc43f5cb 4 4 +SuccessionFlowUsage importedMembership 1a16647131364873 4 0 +SuccessionFlowUsage individualDefinition 92150e0a7bf2a241 4 0 +SuccessionFlowUsage inheritedFeature 1a16647131364873 4 0 +SuccessionFlowUsage inheritedMembership 1a16647131364873 4 0 +SuccessionFlowUsage input 1a16647131364873 4 0 +SuccessionFlowUsage interaction 1a16647131364873 4 0 +SuccessionFlowUsage intersectingType 1a16647131364873 4 0 +SuccessionFlowUsage isAbstract cb289e8ed617283b 4 0 +SuccessionFlowUsage isComposite 2e66253feab21bbf 4 4 +SuccessionFlowUsage isConjugated cb289e8ed617283b 4 0 +SuccessionFlowUsage isConstant cb289e8ed617283b 4 0 +SuccessionFlowUsage isDerived cb289e8ed617283b 4 0 +SuccessionFlowUsage isEnd cb289e8ed617283b 4 0 +SuccessionFlowUsage isImplied 92150e0a7bf2a241 4 0 +SuccessionFlowUsage isImpliedIncluded 2e66253feab21bbf 4 4 +SuccessionFlowUsage isIndividual 92150e0a7bf2a241 4 0 +SuccessionFlowUsage isLibraryElement cb289e8ed617283b 4 0 +SuccessionFlowUsage isOrdered cb289e8ed617283b 4 0 +SuccessionFlowUsage isPortion 92150e0a7bf2a241 4 0 +SuccessionFlowUsage isReference cb289e8ed617283b 4 0 +SuccessionFlowUsage isSufficient 92150e0a7bf2a241 4 0 +SuccessionFlowUsage isUnique 2e66253feab21bbf 4 4 +SuccessionFlowUsage isVariable 92150e0a7bf2a241 4 0 +SuccessionFlowUsage isVariation cb289e8ed617283b 4 0 +SuccessionFlowUsage mayTimeVary 92150e0a7bf2a241 4 0 +SuccessionFlowUsage member 79866851bc43f5cb 4 4 +SuccessionFlowUsage membership 8798b973d8c0f0bd 4 4 +SuccessionFlowUsage multiplicity 92150e0a7bf2a241 4 0 +SuccessionFlowUsage name f1d04f23da686403 4 2 +SuccessionFlowUsage nestedAction 1a16647131364873 4 0 +SuccessionFlowUsage nestedAllocation 1a16647131364873 4 0 +SuccessionFlowUsage nestedAnalysisCase 1a16647131364873 4 0 +SuccessionFlowUsage nestedAttribute 1a16647131364873 4 0 +SuccessionFlowUsage nestedCalculation 1a16647131364873 4 0 +SuccessionFlowUsage nestedCase 1a16647131364873 4 0 +SuccessionFlowUsage nestedConcern 1a16647131364873 4 0 +SuccessionFlowUsage nestedConnection 1a16647131364873 4 0 +SuccessionFlowUsage nestedConstraint 1a16647131364873 4 0 +SuccessionFlowUsage nestedEnumeration 1a16647131364873 4 0 +SuccessionFlowUsage nestedFlow 1a16647131364873 4 0 +SuccessionFlowUsage nestedInterface 1a16647131364873 4 0 +SuccessionFlowUsage nestedItem 1a16647131364873 4 0 +SuccessionFlowUsage nestedMetadata 1a16647131364873 4 0 +SuccessionFlowUsage nestedOccurrence 1a16647131364873 4 0 +SuccessionFlowUsage nestedPart 1a16647131364873 4 0 +SuccessionFlowUsage nestedPort 1a16647131364873 4 0 +SuccessionFlowUsage nestedReference 1a16647131364873 4 0 +SuccessionFlowUsage nestedRendering 1a16647131364873 4 0 +SuccessionFlowUsage nestedRequirement 1a16647131364873 4 0 +SuccessionFlowUsage nestedState 1a16647131364873 4 0 +SuccessionFlowUsage nestedTransition 1a16647131364873 4 0 +SuccessionFlowUsage nestedUsage 1a16647131364873 4 0 +SuccessionFlowUsage nestedUseCase 1a16647131364873 4 0 +SuccessionFlowUsage nestedVerificationCase 1a16647131364873 4 0 +SuccessionFlowUsage nestedView 1a16647131364873 4 0 +SuccessionFlowUsage nestedViewpoint 1a16647131364873 4 0 +SuccessionFlowUsage occurrenceDefinition 1a16647131364873 4 0 +SuccessionFlowUsage output 1a16647131364873 4 0 +SuccessionFlowUsage ownedAnnotation 1a16647131364873 4 0 +SuccessionFlowUsage ownedConjugator 92150e0a7bf2a241 4 0 +SuccessionFlowUsage ownedCrossSubsetting 92150e0a7bf2a241 4 0 +SuccessionFlowUsage ownedDifferencing 1a16647131364873 4 0 +SuccessionFlowUsage ownedDisjoining 1a16647131364873 4 0 +SuccessionFlowUsage ownedElement 79866851bc43f5cb 4 4 +SuccessionFlowUsage ownedEndFeature 79866851bc43f5cb 4 4 +SuccessionFlowUsage ownedFeature 79866851bc43f5cb 4 4 +SuccessionFlowUsage ownedFeatureChaining 1a16647131364873 4 0 +SuccessionFlowUsage ownedFeatureInverting 1a16647131364873 4 0 +SuccessionFlowUsage ownedFeatureMembership 8798b973d8c0f0bd 4 4 +SuccessionFlowUsage ownedImport 1a16647131364873 4 0 +SuccessionFlowUsage ownedIntersecting 1a16647131364873 4 0 +SuccessionFlowUsage ownedMember 79866851bc43f5cb 4 4 +SuccessionFlowUsage ownedMembership 8798b973d8c0f0bd 4 4 +SuccessionFlowUsage ownedRedefinition 1a16647131364873 4 0 +SuccessionFlowUsage ownedReferenceSubsetting 92150e0a7bf2a241 4 0 +SuccessionFlowUsage ownedRelatedElement 1a16647131364873 4 0 +SuccessionFlowUsage ownedRelationship 6675855455139686 4 4 +SuccessionFlowUsage ownedSpecialization 0e80f570bb0530a0 4 4 +SuccessionFlowUsage ownedSubsetting 0e80f570bb0530a0 4 4 +SuccessionFlowUsage ownedTypeFeaturing 1a16647131364873 4 0 +SuccessionFlowUsage ownedTyping 1a16647131364873 4 0 +SuccessionFlowUsage ownedUnioning 1a16647131364873 4 0 +SuccessionFlowUsage owner 745e5f756b1bf617 4 4 +SuccessionFlowUsage owningDefinition 0be0b264707658ab 4 2 +SuccessionFlowUsage owningFeatureMembership fd8633edb2cd8aea 4 4 +SuccessionFlowUsage owningMembership fd8633edb2cd8aea 4 4 +SuccessionFlowUsage owningNamespace 745e5f756b1bf617 4 4 +SuccessionFlowUsage owningRelatedElement 92150e0a7bf2a241 4 0 +SuccessionFlowUsage owningRelationship fd8633edb2cd8aea 4 4 +SuccessionFlowUsage owningType 745e5f756b1bf617 4 4 +SuccessionFlowUsage owningUsage fa92bb1b76983fad 4 2 +SuccessionFlowUsage parameter 1a16647131364873 4 0 +SuccessionFlowUsage payloadFeature 92150e0a7bf2a241 4 0 +SuccessionFlowUsage payloadType 1a16647131364873 4 0 +SuccessionFlowUsage portionKind 92150e0a7bf2a241 4 0 +SuccessionFlowUsage qualifiedName d50748fde18fd1cf 4 2 +SuccessionFlowUsage relatedElement 1a16647131364873 4 0 +SuccessionFlowUsage relatedFeature eff36c57baf34f35 4 4 +SuccessionFlowUsage shortName 92150e0a7bf2a241 4 0 +SuccessionFlowUsage source 1a16647131364873 4 0 +SuccessionFlowUsage sourceFeature 98515f5218d1c97c 4 4 +SuccessionFlowUsage sourceOutputFeature 609d29cb4c2fa7ab 4 4 +SuccessionFlowUsage target 1a16647131364873 4 0 +SuccessionFlowUsage targetFeature 38bf899553dc5542 4 4 +SuccessionFlowUsage targetInputFeature 16ff0a5a0926d172 4 4 +SuccessionFlowUsage textualRepresentation 1a16647131364873 4 0 +SuccessionFlowUsage type 1a16647131364873 4 0 +SuccessionFlowUsage unioningType 1a16647131364873 4 0 +SuccessionFlowUsage usage 1a16647131364873 4 0 +SuccessionFlowUsage variant 1a16647131364873 4 0 +SuccessionFlowUsage variantMembership 1a16647131364873 4 0 +TerminateActionUsage actionDefinition bc05246ed5a395d7 6 0 +TerminateActionUsage aliasIds bc05246ed5a395d7 6 0 +TerminateActionUsage behavior bc05246ed5a395d7 6 0 +TerminateActionUsage chainingFeature bc05246ed5a395d7 6 0 +TerminateActionUsage crossFeature b67e248bc2758a97 6 0 +TerminateActionUsage declaredName a07dd6d08fa65cde 6 1 +TerminateActionUsage declaredShortName b67e248bc2758a97 6 0 +TerminateActionUsage definition bc05246ed5a395d7 6 0 +TerminateActionUsage differencingType bc05246ed5a395d7 6 0 +TerminateActionUsage directedFeature 25e8566260dd7c43 6 3 +TerminateActionUsage directedUsage 25e8566260dd7c43 6 3 +TerminateActionUsage direction b67e248bc2758a97 6 0 +TerminateActionUsage documentation bc05246ed5a395d7 6 0 +TerminateActionUsage elementId 6f6a5f94f2bd644c 6 6 +TerminateActionUsage endFeature bc05246ed5a395d7 6 0 +TerminateActionUsage endOwningType b67e248bc2758a97 6 0 +TerminateActionUsage feature 25e8566260dd7c43 6 3 +TerminateActionUsage featureMembership a6cd665df81d6cf4 6 3 +TerminateActionUsage featureTarget f39e4048f7d88f2c 6 0 +TerminateActionUsage featuringType bc05246ed5a395d7 6 0 +TerminateActionUsage importedMembership bc05246ed5a395d7 6 0 +TerminateActionUsage individualDefinition b67e248bc2758a97 6 0 +TerminateActionUsage inheritedFeature bc05246ed5a395d7 6 0 +TerminateActionUsage inheritedMembership bc05246ed5a395d7 6 0 +TerminateActionUsage input 25e8566260dd7c43 6 3 +TerminateActionUsage intersectingType bc05246ed5a395d7 6 0 +TerminateActionUsage isAbstract bb69398771b07dad 6 0 +TerminateActionUsage isComposite 60428e81319bc42b 6 6 +TerminateActionUsage isConjugated bb69398771b07dad 6 0 +TerminateActionUsage isConstant bb69398771b07dad 6 0 +TerminateActionUsage isDerived bb69398771b07dad 6 0 +TerminateActionUsage isEnd bb69398771b07dad 6 0 +TerminateActionUsage isImpliedIncluded 60428e81319bc42b 6 6 +TerminateActionUsage isIndividual b67e248bc2758a97 6 0 +TerminateActionUsage isLibraryElement bb69398771b07dad 6 0 +TerminateActionUsage isOrdered bb69398771b07dad 6 0 +TerminateActionUsage isPortion b67e248bc2758a97 6 0 +TerminateActionUsage isReference bb69398771b07dad 6 0 +TerminateActionUsage isSufficient b67e248bc2758a97 6 0 +TerminateActionUsage isUnique 60428e81319bc42b 6 6 +TerminateActionUsage isVariable b67e248bc2758a97 6 0 +TerminateActionUsage isVariation bb69398771b07dad 6 0 +TerminateActionUsage mayTimeVary b67e248bc2758a97 6 0 +TerminateActionUsage member 25e8566260dd7c43 6 3 +TerminateActionUsage membership a6cd665df81d6cf4 6 3 +TerminateActionUsage multiplicity b67e248bc2758a97 6 0 +TerminateActionUsage name a07dd6d08fa65cde 6 1 +TerminateActionUsage nestedAction bc05246ed5a395d7 6 0 +TerminateActionUsage nestedAllocation bc05246ed5a395d7 6 0 +TerminateActionUsage nestedAnalysisCase bc05246ed5a395d7 6 0 +TerminateActionUsage nestedAttribute bc05246ed5a395d7 6 0 +TerminateActionUsage nestedCalculation bc05246ed5a395d7 6 0 +TerminateActionUsage nestedCase bc05246ed5a395d7 6 0 +TerminateActionUsage nestedConcern bc05246ed5a395d7 6 0 +TerminateActionUsage nestedConnection bc05246ed5a395d7 6 0 +TerminateActionUsage nestedConstraint bc05246ed5a395d7 6 0 +TerminateActionUsage nestedEnumeration bc05246ed5a395d7 6 0 +TerminateActionUsage nestedFlow bc05246ed5a395d7 6 0 +TerminateActionUsage nestedInterface 25e8566260dd7c43 6 3 +TerminateActionUsage nestedItem bc05246ed5a395d7 6 0 +TerminateActionUsage nestedMetadata bc05246ed5a395d7 6 0 +TerminateActionUsage nestedOccurrence bc05246ed5a395d7 6 0 +TerminateActionUsage nestedPart bc05246ed5a395d7 6 0 +TerminateActionUsage nestedPort bc05246ed5a395d7 6 0 +TerminateActionUsage nestedReference 25e8566260dd7c43 6 3 +TerminateActionUsage nestedRendering bc05246ed5a395d7 6 0 +TerminateActionUsage nestedRequirement bc05246ed5a395d7 6 0 +TerminateActionUsage nestedState bc05246ed5a395d7 6 0 +TerminateActionUsage nestedTransition bc05246ed5a395d7 6 0 +TerminateActionUsage nestedUsage 25e8566260dd7c43 6 3 +TerminateActionUsage nestedUseCase bc05246ed5a395d7 6 0 +TerminateActionUsage nestedVerificationCase bc05246ed5a395d7 6 0 +TerminateActionUsage nestedView bc05246ed5a395d7 6 0 +TerminateActionUsage nestedViewpoint bc05246ed5a395d7 6 0 +TerminateActionUsage occurrenceDefinition bc05246ed5a395d7 6 0 +TerminateActionUsage output bc05246ed5a395d7 6 0 +TerminateActionUsage ownedAnnotation bc05246ed5a395d7 6 0 +TerminateActionUsage ownedConjugator b67e248bc2758a97 6 0 +TerminateActionUsage ownedCrossSubsetting b67e248bc2758a97 6 0 +TerminateActionUsage ownedDifferencing bc05246ed5a395d7 6 0 +TerminateActionUsage ownedDisjoining bc05246ed5a395d7 6 0 +TerminateActionUsage ownedElement 25e8566260dd7c43 6 3 +TerminateActionUsage ownedEndFeature bc05246ed5a395d7 6 0 +TerminateActionUsage ownedFeature 25e8566260dd7c43 6 3 +TerminateActionUsage ownedFeatureChaining bc05246ed5a395d7 6 0 +TerminateActionUsage ownedFeatureInverting bc05246ed5a395d7 6 0 +TerminateActionUsage ownedFeatureMembership a6cd665df81d6cf4 6 3 +TerminateActionUsage ownedImport bc05246ed5a395d7 6 0 +TerminateActionUsage ownedIntersecting bc05246ed5a395d7 6 0 +TerminateActionUsage ownedMember 25e8566260dd7c43 6 3 +TerminateActionUsage ownedMembership a6cd665df81d6cf4 6 3 +TerminateActionUsage ownedRedefinition bc05246ed5a395d7 6 0 +TerminateActionUsage ownedReferenceSubsetting b67e248bc2758a97 6 0 +TerminateActionUsage ownedRelationship 3cdf99018ac80a3a 6 6 +TerminateActionUsage ownedSpecialization 51b971a59b9988ed 6 6 +TerminateActionUsage ownedSubsetting 51b971a59b9988ed 6 6 +TerminateActionUsage ownedTypeFeaturing bc05246ed5a395d7 6 0 +TerminateActionUsage ownedTyping bc05246ed5a395d7 6 0 +TerminateActionUsage ownedUnioning bc05246ed5a395d7 6 0 +TerminateActionUsage owner 8f492f34cc3f0fc7 6 6 +TerminateActionUsage owningDefinition a32de7ba51c96d50 6 2 +TerminateActionUsage owningFeatureMembership f2d64bea8fb6cf5e 6 6 +TerminateActionUsage owningMembership f2d64bea8fb6cf5e 6 6 +TerminateActionUsage owningNamespace 8f492f34cc3f0fc7 6 6 +TerminateActionUsage owningRelationship f2d64bea8fb6cf5e 6 6 +TerminateActionUsage owningType 8f492f34cc3f0fc7 6 6 +TerminateActionUsage owningUsage a2996c063ceb2d0e 6 4 +TerminateActionUsage parameter 25e8566260dd7c43 6 3 +TerminateActionUsage portionKind b67e248bc2758a97 6 0 +TerminateActionUsage qualifiedName ddc672d7dbecd53c 6 1 +TerminateActionUsage shortName b67e248bc2758a97 6 0 +TerminateActionUsage terminatedOccurrenceArgument 1900f909f5ade708 6 3 +TerminateActionUsage textualRepresentation bc05246ed5a395d7 6 0 +TerminateActionUsage type bc05246ed5a395d7 6 0 +TerminateActionUsage unioningType bc05246ed5a395d7 6 0 +TerminateActionUsage usage 25e8566260dd7c43 6 3 +TerminateActionUsage variant bc05246ed5a395d7 6 0 +TerminateActionUsage variantMembership bc05246ed5a395d7 6 0 +TextualRepresentation aliasIds cc7f384e80bcf2a4 91 0 +TextualRepresentation annotatedElement 5045116fd5e43490 91 91 +TextualRepresentation annotation cc7f384e80bcf2a4 91 0 +TextualRepresentation body 7558077c3f99ea49 91 91 +TextualRepresentation declaredName 888dbabc419e7589 91 1 +TextualRepresentation declaredShortName 7cc2e7bcfc261c2f 91 0 +TextualRepresentation documentation cc7f384e80bcf2a4 91 0 +TextualRepresentation elementId 8f62583c8c589568 91 91 +TextualRepresentation isImpliedIncluded eb1697f69c479fe8 91 91 +TextualRepresentation isLibraryElement 89c6220491d34211 91 0 +TextualRepresentation language f4677481bc3f7cc6 91 91 +TextualRepresentation name 888dbabc419e7589 91 1 +TextualRepresentation ownedAnnotatingRelationship cc7f384e80bcf2a4 91 0 +TextualRepresentation ownedAnnotation cc7f384e80bcf2a4 91 0 +TextualRepresentation ownedElement cc7f384e80bcf2a4 91 0 +TextualRepresentation ownedRelationship cc7f384e80bcf2a4 91 0 +TextualRepresentation owner 141a00a481a50e58 91 91 +TextualRepresentation owningAnnotatingRelationship 7cc2e7bcfc261c2f 91 0 +TextualRepresentation owningMembership 6c70ef80928dc075 91 91 +TextualRepresentation owningNamespace 141a00a481a50e58 91 91 +TextualRepresentation owningRelationship 6c70ef80928dc075 91 91 +TextualRepresentation qualifiedName 3d5c736455001fb6 91 1 +TextualRepresentation representedElement 141a00a481a50e58 91 91 +TextualRepresentation shortName 7cc2e7bcfc261c2f 91 0 +TextualRepresentation textualRepresentation cc7f384e80bcf2a4 91 0 +TransitionFeatureMembership aliasIds 0b64d66525dd20d3 121 0 +TransitionFeatureMembership declaredName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership declaredShortName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership documentation 0b64d66525dd20d3 121 0 +TransitionFeatureMembership elementId 0dfc4247ad483f28 121 121 +TransitionFeatureMembership isImplied f1f45a069d6ddace 121 0 +TransitionFeatureMembership isImpliedIncluded 5757d8079b769e4b 121 121 +TransitionFeatureMembership isLibraryElement f1f45a069d6ddace 121 0 +TransitionFeatureMembership kind 121cc9f4fb48e83a 121 121 +TransitionFeatureMembership memberElement 68baa2b1caec201c 121 121 +TransitionFeatureMembership memberElementId bd57c5ac0e716515 121 121 +TransitionFeatureMembership memberName f50f5b4cb7c90118 121 82 +TransitionFeatureMembership memberShortName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership membershipOwningNamespace 34b971d9b244eb21 121 121 +TransitionFeatureMembership name d8a8a69e000efbf2 121 0 +TransitionFeatureMembership ownedAnnotation 0b64d66525dd20d3 121 0 +TransitionFeatureMembership ownedElement 0b64d66525dd20d3 121 0 +TransitionFeatureMembership ownedMemberElement 68baa2b1caec201c 121 121 +TransitionFeatureMembership ownedMemberElementId bd57c5ac0e716515 121 121 +TransitionFeatureMembership ownedMemberFeature 68baa2b1caec201c 121 121 +TransitionFeatureMembership ownedMemberName f50f5b4cb7c90118 121 82 +TransitionFeatureMembership ownedMemberShortName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership ownedRelatedElement 2238239f6a686d86 121 121 +TransitionFeatureMembership ownedRelationship 0b64d66525dd20d3 121 0 +TransitionFeatureMembership owner d8a8a69e000efbf2 121 0 +TransitionFeatureMembership owningMembership d8a8a69e000efbf2 121 0 +TransitionFeatureMembership owningNamespace d8a8a69e000efbf2 121 0 +TransitionFeatureMembership owningRelatedElement 34b971d9b244eb21 121 121 +TransitionFeatureMembership owningRelationship d8a8a69e000efbf2 121 0 +TransitionFeatureMembership owningType 34b971d9b244eb21 121 121 +TransitionFeatureMembership qualifiedName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership relatedElement 763472c90be5f90a 121 121 +TransitionFeatureMembership shortName d8a8a69e000efbf2 121 0 +TransitionFeatureMembership source 0d843b6838aecefd 121 121 +TransitionFeatureMembership target 2238239f6a686d86 121 121 +TransitionFeatureMembership textualRepresentation 0b64d66525dd20d3 121 0 +TransitionFeatureMembership transitionFeature 68baa2b1caec201c 121 121 +TransitionFeatureMembership visibility d8a8a69e000efbf2 121 0 +TransitionUsage actionDefinition f9a7ca87f242d57f 111 0 +TransitionUsage aliasIds f9a7ca87f242d57f 111 0 +TransitionUsage behavior f9a7ca87f242d57f 111 0 +TransitionUsage chainingFeature f9a7ca87f242d57f 111 0 +TransitionUsage crossFeature e8a1c0f7bb6230a0 111 0 +TransitionUsage declaredName c0a1ca458ff2d306 111 39 +TransitionUsage declaredShortName e8a1c0f7bb6230a0 111 0 +TransitionUsage definition f9a7ca87f242d57f 111 0 +TransitionUsage differencingType f9a7ca87f242d57f 111 0 +TransitionUsage directedFeature f10d5764ec8b754e 111 80 +TransitionUsage directedUsage f10d5764ec8b754e 111 80 +TransitionUsage direction e8a1c0f7bb6230a0 111 0 +TransitionUsage documentation f9a7ca87f242d57f 111 0 +TransitionUsage effectAction 330274732890f030 111 20 +TransitionUsage elementId ff9b05ef9cc6d608 111 111 +TransitionUsage endFeature f9a7ca87f242d57f 111 0 +TransitionUsage endOwningType e8a1c0f7bb6230a0 111 0 +TransitionUsage feature d322c2017768e66b 111 95 +TransitionUsage featureMembership 659a7216ce62a44c 111 95 +TransitionUsage featureTarget f430ce286c696e35 111 0 +TransitionUsage featuringType f9a7ca87f242d57f 111 0 +TransitionUsage guardExpression d698024a2463450f 111 21 +TransitionUsage importedMembership f9a7ca87f242d57f 111 0 +TransitionUsage individualDefinition e8a1c0f7bb6230a0 111 0 +TransitionUsage inheritedFeature f9a7ca87f242d57f 111 0 +TransitionUsage inheritedMembership f9a7ca87f242d57f 111 0 +TransitionUsage input f10d5764ec8b754e 111 80 +TransitionUsage intersectingType f9a7ca87f242d57f 111 0 +TransitionUsage isAbstract e407cb80643287b4 111 0 +TransitionUsage isComposite 5b47a9ebd492ed37 111 111 +TransitionUsage isConjugated e407cb80643287b4 111 0 +TransitionUsage isConstant e407cb80643287b4 111 0 +TransitionUsage isDerived e407cb80643287b4 111 0 +TransitionUsage isEnd e407cb80643287b4 111 0 +TransitionUsage isImpliedIncluded 5b47a9ebd492ed37 111 111 +TransitionUsage isIndividual e8a1c0f7bb6230a0 111 0 +TransitionUsage isLibraryElement e407cb80643287b4 111 0 +TransitionUsage isOrdered e407cb80643287b4 111 0 +TransitionUsage isPortion e8a1c0f7bb6230a0 111 0 +TransitionUsage isReference e407cb80643287b4 111 0 +TransitionUsage isSufficient e8a1c0f7bb6230a0 111 0 +TransitionUsage isUnique 5b47a9ebd492ed37 111 111 +TransitionUsage isVariable e8a1c0f7bb6230a0 111 0 +TransitionUsage isVariation e407cb80643287b4 111 0 +TransitionUsage mayTimeVary e8a1c0f7bb6230a0 111 0 +TransitionUsage member ca11e290c07ea56f 111 111 +TransitionUsage membership 12ee05b52c3ff7f5 111 111 +TransitionUsage multiplicity e8a1c0f7bb6230a0 111 0 +TransitionUsage name c0a1ca458ff2d306 111 39 +TransitionUsage nestedAction 9d8ade2413b53cb0 111 82 +TransitionUsage nestedAllocation f9a7ca87f242d57f 111 0 +TransitionUsage nestedAnalysisCase f9a7ca87f242d57f 111 0 +TransitionUsage nestedAttribute f9a7ca87f242d57f 111 0 +TransitionUsage nestedCalculation f9a7ca87f242d57f 111 0 +TransitionUsage nestedCase f9a7ca87f242d57f 111 0 +TransitionUsage nestedConcern f9a7ca87f242d57f 111 0 +TransitionUsage nestedConnection f9a7ca87f242d57f 111 0 +TransitionUsage nestedConstraint f9a7ca87f242d57f 111 0 +TransitionUsage nestedEnumeration f9a7ca87f242d57f 111 0 +TransitionUsage nestedFlow f9a7ca87f242d57f 111 0 +TransitionUsage nestedInterface f10d5764ec8b754e 111 80 +TransitionUsage nestedItem f9a7ca87f242d57f 111 0 +TransitionUsage nestedMetadata f9a7ca87f242d57f 111 0 +TransitionUsage nestedOccurrence 9d8ade2413b53cb0 111 82 +TransitionUsage nestedPart f9a7ca87f242d57f 111 0 +TransitionUsage nestedPort f9a7ca87f242d57f 111 0 +TransitionUsage nestedReference f10d5764ec8b754e 111 80 +TransitionUsage nestedRendering f9a7ca87f242d57f 111 0 +TransitionUsage nestedRequirement f9a7ca87f242d57f 111 0 +TransitionUsage nestedState f9a7ca87f242d57f 111 0 +TransitionUsage nestedTransition f9a7ca87f242d57f 111 0 +TransitionUsage nestedUsage b4a61f48f6527f17 111 82 +TransitionUsage nestedUseCase f9a7ca87f242d57f 111 0 +TransitionUsage nestedVerificationCase f9a7ca87f242d57f 111 0 +TransitionUsage nestedView f9a7ca87f242d57f 111 0 +TransitionUsage nestedViewpoint f9a7ca87f242d57f 111 0 +TransitionUsage occurrenceDefinition f9a7ca87f242d57f 111 0 +TransitionUsage output f9a7ca87f242d57f 111 0 +TransitionUsage ownedAnnotation f9a7ca87f242d57f 111 0 +TransitionUsage ownedConjugator e8a1c0f7bb6230a0 111 0 +TransitionUsage ownedCrossSubsetting e8a1c0f7bb6230a0 111 0 +TransitionUsage ownedDifferencing f9a7ca87f242d57f 111 0 +TransitionUsage ownedDisjoining f9a7ca87f242d57f 111 0 +TransitionUsage ownedElement 036a4515c624b5c5 111 111 +TransitionUsage ownedEndFeature f9a7ca87f242d57f 111 0 +TransitionUsage ownedFeature d322c2017768e66b 111 95 +TransitionUsage ownedFeatureChaining f9a7ca87f242d57f 111 0 +TransitionUsage ownedFeatureInverting f9a7ca87f242d57f 111 0 +TransitionUsage ownedFeatureMembership 659a7216ce62a44c 111 95 +TransitionUsage ownedImport f9a7ca87f242d57f 111 0 +TransitionUsage ownedIntersecting f9a7ca87f242d57f 111 0 +TransitionUsage ownedMember 036a4515c624b5c5 111 111 +TransitionUsage ownedMembership 12ee05b52c3ff7f5 111 111 +TransitionUsage ownedRedefinition f9a7ca87f242d57f 111 0 +TransitionUsage ownedReferenceSubsetting e8a1c0f7bb6230a0 111 0 +TransitionUsage ownedRelationship bfa9da36024a971a 111 111 +TransitionUsage ownedSpecialization 5a9190ecea28a79c 111 111 +TransitionUsage ownedSubsetting 5a9190ecea28a79c 111 111 +TransitionUsage ownedTypeFeaturing f9a7ca87f242d57f 111 0 +TransitionUsage ownedTyping f9a7ca87f242d57f 111 0 +TransitionUsage ownedUnioning f9a7ca87f242d57f 111 0 +TransitionUsage owner 7bf249d1f7178a13 111 111 +TransitionUsage owningDefinition 18a7f3a809a77d2b 111 22 +TransitionUsage owningFeatureMembership 1c3f85726deb3074 111 111 +TransitionUsage owningMembership 1c3f85726deb3074 111 111 +TransitionUsage owningNamespace 7bf249d1f7178a13 111 111 +TransitionUsage owningRelationship 1c3f85726deb3074 111 111 +TransitionUsage owningType 7bf249d1f7178a13 111 111 +TransitionUsage owningUsage 4bec1721a8d23d88 111 89 +TransitionUsage parameter f10d5764ec8b754e 111 80 +TransitionUsage portionKind e8a1c0f7bb6230a0 111 0 +TransitionUsage qualifiedName 008e9610b35a69ae 111 39 +TransitionUsage shortName e8a1c0f7bb6230a0 111 0 +TransitionUsage source 6a1f9db32fb79243 111 52 +TransitionUsage succession b35e4e432316ba80 111 111 +TransitionUsage target 0f9fcb5507f851ea 111 111 +TransitionUsage textualRepresentation f9a7ca87f242d57f 111 0 +TransitionUsage triggerAction 933cc09bb11f6289 111 80 +TransitionUsage type f9a7ca87f242d57f 111 0 +TransitionUsage unioningType f9a7ca87f242d57f 111 0 +TransitionUsage usage b4a61f48f6527f17 111 82 +TransitionUsage variant f9a7ca87f242d57f 111 0 +TransitionUsage variantMembership f9a7ca87f242d57f 111 0 +TriggerInvocationExpression aliasIds 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression argument 6a6a643b887551b5 18 18 +TriggerInvocationExpression behavior 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression chainingFeature 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression crossFeature 124868eb6a7f3283 18 0 +TriggerInvocationExpression declaredName 124868eb6a7f3283 18 0 +TriggerInvocationExpression declaredShortName 124868eb6a7f3283 18 0 +TriggerInvocationExpression differencingType 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression directedFeature 6a6a643b887551b5 18 18 +TriggerInvocationExpression direction 124868eb6a7f3283 18 0 +TriggerInvocationExpression documentation 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression elementId 4f04ce36a8b3af54 18 18 +TriggerInvocationExpression endFeature 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression endOwningType 124868eb6a7f3283 18 0 +TriggerInvocationExpression feature 6a6a643b887551b5 18 18 +TriggerInvocationExpression featureMembership 6305f23c2da9f348 18 18 +TriggerInvocationExpression featureTarget 94f742df6ac72c1c 18 0 +TriggerInvocationExpression featuringType 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression function 124868eb6a7f3283 18 0 +TriggerInvocationExpression importedMembership 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression inheritedFeature 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression inheritedMembership 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression input 6a6a643b887551b5 18 18 +TriggerInvocationExpression instantiatedType a6d53a07e32d69bc 18 18 +TriggerInvocationExpression intersectingType 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression isAbstract 124868eb6a7f3283 18 0 +TriggerInvocationExpression isComposite 124868eb6a7f3283 18 0 +TriggerInvocationExpression isConjugated 1d938dca5b647ae1 18 0 +TriggerInvocationExpression isConstant 124868eb6a7f3283 18 0 +TriggerInvocationExpression isDerived 124868eb6a7f3283 18 0 +TriggerInvocationExpression isEnd 124868eb6a7f3283 18 0 +TriggerInvocationExpression isImpliedIncluded b6f1e2589d392cd3 18 18 +TriggerInvocationExpression isLibraryElement 1d938dca5b647ae1 18 0 +TriggerInvocationExpression isModelLevelEvaluable 1d938dca5b647ae1 18 0 +TriggerInvocationExpression isOrdered 124868eb6a7f3283 18 0 +TriggerInvocationExpression isPortion 124868eb6a7f3283 18 0 +TriggerInvocationExpression isSufficient 124868eb6a7f3283 18 0 +TriggerInvocationExpression isUnique 124868eb6a7f3283 18 0 +TriggerInvocationExpression isVariable 124868eb6a7f3283 18 0 +TriggerInvocationExpression kind f79b4cb85fca6653 18 18 +TriggerInvocationExpression member 6a6a643b887551b5 18 18 +TriggerInvocationExpression membership 6305f23c2da9f348 18 18 +TriggerInvocationExpression multiplicity 124868eb6a7f3283 18 0 +TriggerInvocationExpression name 124868eb6a7f3283 18 0 +TriggerInvocationExpression output 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedAnnotation 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedConjugator 124868eb6a7f3283 18 0 +TriggerInvocationExpression ownedCrossSubsetting 124868eb6a7f3283 18 0 +TriggerInvocationExpression ownedDifferencing 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedDisjoining 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedElement 6a6a643b887551b5 18 18 +TriggerInvocationExpression ownedEndFeature 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedFeature 6a6a643b887551b5 18 18 +TriggerInvocationExpression ownedFeatureChaining 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedFeatureInverting 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedFeatureMembership 6305f23c2da9f348 18 18 +TriggerInvocationExpression ownedImport 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedIntersecting 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedMember 6a6a643b887551b5 18 18 +TriggerInvocationExpression ownedMembership 6305f23c2da9f348 18 18 +TriggerInvocationExpression ownedRedefinition 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedReferenceSubsetting 124868eb6a7f3283 18 0 +TriggerInvocationExpression ownedRelationship 6305f23c2da9f348 18 18 +TriggerInvocationExpression ownedSpecialization 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedSubsetting 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedTypeFeaturing 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedTyping 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression ownedUnioning 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression owner 3c051dfded0b6ae5 18 18 +TriggerInvocationExpression owningFeatureMembership fea93f1c4061ea90 18 18 +TriggerInvocationExpression owningMembership fea93f1c4061ea90 18 18 +TriggerInvocationExpression owningNamespace 3c051dfded0b6ae5 18 18 +TriggerInvocationExpression owningRelationship fea93f1c4061ea90 18 18 +TriggerInvocationExpression owningType 3c051dfded0b6ae5 18 18 +TriggerInvocationExpression parameter 6a6a643b887551b5 18 18 +TriggerInvocationExpression qualifiedName 124868eb6a7f3283 18 0 +TriggerInvocationExpression result 94f742df6ac72c1c 18 0 +TriggerInvocationExpression shortName 124868eb6a7f3283 18 0 +TriggerInvocationExpression textualRepresentation 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression type 50fbaf39e2c234ef 18 0 +TriggerInvocationExpression unioningType 50fbaf39e2c234ef 18 0 +Usage aliasIds 7124f405e7fc7804 55 0 +Usage chainingFeature 7124f405e7fc7804 55 0 +Usage crossFeature b358be3d3f6eea5b 55 0 +Usage declaredName d85ad9850c953230 55 41 +Usage declaredShortName b358be3d3f6eea5b 55 0 +Usage definition 6d543dd888c78af8 55 23 +Usage differencingType 7124f405e7fc7804 55 0 +Usage directedFeature 7124f405e7fc7804 55 0 +Usage directedUsage 7124f405e7fc7804 55 0 +Usage direction b358be3d3f6eea5b 55 0 +Usage documentation 7124f405e7fc7804 55 0 +Usage elementId 86b6d698614eba60 55 55 +Usage endFeature 7124f405e7fc7804 55 0 +Usage endOwningType f4914700c854ad40 55 21 +Usage feature 8aafea61cccc88b8 55 14 +Usage featureMembership 8fbd6ecde2153b7f 55 14 +Usage featureTarget 85197e7cfa9cb303 55 0 +Usage featuringType 7124f405e7fc7804 55 0 +Usage importedMembership 7124f405e7fc7804 55 0 +Usage inheritedFeature 7124f405e7fc7804 55 0 +Usage inheritedMembership 7124f405e7fc7804 55 0 +Usage input 7124f405e7fc7804 55 0 +Usage intersectingType 7124f405e7fc7804 55 0 +Usage isAbstract 88e3c2ce12c24122 55 1 +Usage isComposite 47d404b52045a9a7 55 26 +Usage isConjugated 10cb1016c62d6a95 55 0 +Usage isConstant a3f0e11651bf3eee 55 21 +Usage isDerived 10cb1016c62d6a95 55 0 +Usage isEnd a3f0e11651bf3eee 55 21 +Usage isImpliedIncluded 12d554d43f67eb48 55 55 +Usage isLibraryElement 2b88e0366a5360fb 55 14 +Usage isOrdered 10cb1016c62d6a95 55 0 +Usage isPortion b358be3d3f6eea5b 55 0 +Usage isReference dbcc6035e54fac36 55 29 +Usage isSufficient b358be3d3f6eea5b 55 0 +Usage isUnique 12d554d43f67eb48 55 55 +Usage isVariable e53d23f47d3f10ea 55 21 +Usage isVariation 10cb1016c62d6a95 55 0 +Usage mayTimeVary e53d23f47d3f10ea 55 21 +Usage member 961196f4e342c6b3 55 55 +Usage membership b9331f0bcb354240 55 55 +Usage multiplicity b358be3d3f6eea5b 55 0 +Usage name 2773712493333c76 55 55 +Usage nestedAction a104f706cb113789 55 4 +Usage nestedAllocation 7124f405e7fc7804 55 0 +Usage nestedAnalysisCase 7124f405e7fc7804 55 0 +Usage nestedAttribute 1dbe5c4dc382bcee 55 3 +Usage nestedCalculation 7124f405e7fc7804 55 0 +Usage nestedCase 7124f405e7fc7804 55 0 +Usage nestedConcern 7124f405e7fc7804 55 0 +Usage nestedConnection 71788698e95b3e21 55 1 +Usage nestedConstraint f62736f3c6c191b6 55 1 +Usage nestedEnumeration 7124f405e7fc7804 55 0 +Usage nestedFlow 7124f405e7fc7804 55 0 +Usage nestedInterface 7800df4719793ff5 55 4 +Usage nestedItem 4333decdb3c8f62c 55 1 +Usage nestedMetadata 7124f405e7fc7804 55 0 +Usage nestedOccurrence f81624bc75a2cf63 55 6 +Usage nestedPart 4333decdb3c8f62c 55 1 +Usage nestedPort 7124f405e7fc7804 55 0 +Usage nestedReference 7800df4719793ff5 55 4 +Usage nestedRendering 7124f405e7fc7804 55 0 +Usage nestedRequirement 7124f405e7fc7804 55 0 +Usage nestedState 4b1ad14c120a23e7 55 3 +Usage nestedTransition 7124f405e7fc7804 55 0 +Usage nestedUsage 8aafea61cccc88b8 55 14 +Usage nestedUseCase 7124f405e7fc7804 55 0 +Usage nestedVerificationCase 7124f405e7fc7804 55 0 +Usage nestedView 7124f405e7fc7804 55 0 +Usage nestedViewpoint 7124f405e7fc7804 55 0 +Usage output 7124f405e7fc7804 55 0 +Usage ownedAnnotation 7124f405e7fc7804 55 0 +Usage ownedConjugator b358be3d3f6eea5b 55 0 +Usage ownedCrossSubsetting b358be3d3f6eea5b 55 0 +Usage ownedDifferencing 7124f405e7fc7804 55 0 +Usage ownedDisjoining 7124f405e7fc7804 55 0 +Usage ownedElement 638454dcdc7ea1eb 55 55 +Usage ownedEndFeature 7124f405e7fc7804 55 0 +Usage ownedFeature 8aafea61cccc88b8 55 14 +Usage ownedFeatureChaining 7124f405e7fc7804 55 0 +Usage ownedFeatureInverting 7124f405e7fc7804 55 0 +Usage ownedFeatureMembership 8fbd6ecde2153b7f 55 14 +Usage ownedImport 7124f405e7fc7804 55 0 +Usage ownedIntersecting 7124f405e7fc7804 55 0 +Usage ownedMember 961196f4e342c6b3 55 55 +Usage ownedMembership b9331f0bcb354240 55 55 +Usage ownedRedefinition 80a03df7257185ff 55 2 +Usage ownedReferenceSubsetting 001a19ff15471ac1 55 16 +Usage ownedRelationship 086ed0cb8efbe199 55 55 +Usage ownedSpecialization e337b5786b96e097 55 37 +Usage ownedSubsetting 0869e6e290631d71 55 21 +Usage ownedTypeFeaturing 7124f405e7fc7804 55 0 +Usage ownedTyping a689d0dfaf2dd0a6 55 17 +Usage ownedUnioning 7124f405e7fc7804 55 0 +Usage owner 02407d486cb59db3 55 55 +Usage owningDefinition e6a37e652ee225b3 55 12 +Usage owningFeatureMembership d570d4a3c5e31962 55 47 +Usage owningMembership c0db88bb2660f8ae 55 55 +Usage owningNamespace 02407d486cb59db3 55 55 +Usage owningRelationship c0db88bb2660f8ae 55 55 +Usage owningType c32fa2a60c4c60f3 55 47 +Usage owningUsage 8fe4e27e1cd9259b 55 35 +Usage qualifiedName 026929a5e9624b84 55 43 +Usage shortName b358be3d3f6eea5b 55 0 +Usage textualRepresentation 7124f405e7fc7804 55 0 +Usage type 6d543dd888c78af8 55 23 +Usage unioningType 7124f405e7fc7804 55 0 +Usage usage 8aafea61cccc88b8 55 14 +Usage variant 7124f405e7fc7804 55 0 +Usage variantMembership 7124f405e7fc7804 55 0 +UseCaseDefinition action e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition actorParameter dec7caf3cabd3889 8 7 +UseCaseDefinition aliasIds 8bd937d1bf3987c4 8 0 +UseCaseDefinition calculation e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition declaredName e9ccfe2e6eed7f61 8 8 +UseCaseDefinition declaredShortName 59061534173d1b48 8 0 +UseCaseDefinition differencingType 8bd937d1bf3987c4 8 0 +UseCaseDefinition directedFeature 07d7bd0ae08cc746 8 7 +UseCaseDefinition directedUsage 07d7bd0ae08cc746 8 7 +UseCaseDefinition documentation 8bd937d1bf3987c4 8 0 +UseCaseDefinition elementId dc0d990f53a77ca8 8 8 +UseCaseDefinition endFeature 8bd937d1bf3987c4 8 0 +UseCaseDefinition expression d661531e0f03e2ee 8 5 +UseCaseDefinition feature 82a6e617abb4c6ac 8 7 +UseCaseDefinition featureMembership bfd1abcfcc0c84a5 8 7 +UseCaseDefinition importedMembership 8bd937d1bf3987c4 8 0 +UseCaseDefinition includedUseCase e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition inheritedFeature 8bd937d1bf3987c4 8 0 +UseCaseDefinition inheritedMembership 8bd937d1bf3987c4 8 0 +UseCaseDefinition input 07d7bd0ae08cc746 8 7 +UseCaseDefinition intersectingType 8bd937d1bf3987c4 8 0 +UseCaseDefinition isAbstract 5573c45512a99a74 8 0 +UseCaseDefinition isConjugated 5573c45512a99a74 8 0 +UseCaseDefinition isImpliedIncluded 79e0d9990e6215cc 8 8 +UseCaseDefinition isIndividual 59061534173d1b48 8 0 +UseCaseDefinition isLibraryElement 5573c45512a99a74 8 0 +UseCaseDefinition isModelLevelEvaluable 5573c45512a99a74 8 0 +UseCaseDefinition isSufficient 5573c45512a99a74 8 0 +UseCaseDefinition isVariation 5573c45512a99a74 8 0 +UseCaseDefinition member 82a6e617abb4c6ac 8 7 +UseCaseDefinition membership bfd1abcfcc0c84a5 8 7 +UseCaseDefinition multiplicity 59061534173d1b48 8 0 +UseCaseDefinition name e9ccfe2e6eed7f61 8 8 +UseCaseDefinition objectiveRequirement 7b1a89b6258a91a3 8 3 +UseCaseDefinition output 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedAction e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition ownedAllocation 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedAnalysisCase 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedAnnotation 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedAttribute 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedCalculation e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition ownedCase e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition ownedConcern 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedConjugator 59061534173d1b48 8 0 +UseCaseDefinition ownedConnection 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedConstraint ce8fd260a25ac293 8 5 +UseCaseDefinition ownedDifferencing 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedDisjoining 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedElement 82a6e617abb4c6ac 8 7 +UseCaseDefinition ownedEndFeature 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedEnumeration 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedFeature 82a6e617abb4c6ac 8 7 +UseCaseDefinition ownedFeatureMembership bfd1abcfcc0c84a5 8 7 +UseCaseDefinition ownedFlow 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedImport 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedInterface 961b34a38733eaf1 8 7 +UseCaseDefinition ownedIntersecting 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedItem dec7caf3cabd3889 8 7 +UseCaseDefinition ownedMember 82a6e617abb4c6ac 8 7 +UseCaseDefinition ownedMembership bfd1abcfcc0c84a5 8 7 +UseCaseDefinition ownedMetadata 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedOccurrence 39d60f26e50d235f 8 7 +UseCaseDefinition ownedPart dec7caf3cabd3889 8 7 +UseCaseDefinition ownedPort 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedReference 961b34a38733eaf1 8 7 +UseCaseDefinition ownedRelationship 0982f68a1f0de059 8 8 +UseCaseDefinition ownedRendering 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedRequirement 87c2e18bbe7f943e 8 3 +UseCaseDefinition ownedSpecialization 0a7db295034615ba 8 8 +UseCaseDefinition ownedState 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedSubclassification 0a7db295034615ba 8 8 +UseCaseDefinition ownedTransition 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedUnioning 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedUsage 82a6e617abb4c6ac 8 7 +UseCaseDefinition ownedUseCase e00c5f4b5e6ac4c5 8 2 +UseCaseDefinition ownedVerificationCase 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedView 8bd937d1bf3987c4 8 0 +UseCaseDefinition ownedViewpoint 8bd937d1bf3987c4 8 0 +UseCaseDefinition owner 4dc0cad030c775fd 8 8 +UseCaseDefinition owningMembership a838a010917b8627 8 8 +UseCaseDefinition owningNamespace 4dc0cad030c775fd 8 8 +UseCaseDefinition owningRelationship a838a010917b8627 8 8 +UseCaseDefinition parameter 07d7bd0ae08cc746 8 7 +UseCaseDefinition qualifiedName 7565f57b871d9806 8 8 +UseCaseDefinition result 9f7e0cd129688cac 8 0 +UseCaseDefinition shortName 59061534173d1b48 8 0 +UseCaseDefinition step d661531e0f03e2ee 8 5 +UseCaseDefinition subjectParameter 77272fe53f8fa12b 8 7 +UseCaseDefinition textualRepresentation 8bd937d1bf3987c4 8 0 +UseCaseDefinition unioningType 8bd937d1bf3987c4 8 0 +UseCaseDefinition usage 82a6e617abb4c6ac 8 7 +UseCaseDefinition variant 8bd937d1bf3987c4 8 0 +UseCaseDefinition variantMembership 8bd937d1bf3987c4 8 0 +UseCaseUsage actionDefinition 35190a62f15e8870 19 7 +UseCaseUsage actorParameter 3d76f3e6aca22f63 19 7 +UseCaseUsage aliasIds a285ee2a5d843e24 19 0 +UseCaseUsage behavior 35190a62f15e8870 19 7 +UseCaseUsage calculationDefinition a03488b329e7b51e 19 7 +UseCaseUsage caseDefinition a03488b329e7b51e 19 7 +UseCaseUsage chainingFeature a285ee2a5d843e24 19 0 +UseCaseUsage crossFeature a9dc2ad030387ca3 19 0 +UseCaseUsage declaredName 667d9584b56cba49 19 19 +UseCaseUsage declaredShortName a9dc2ad030387ca3 19 0 +UseCaseUsage definition 35190a62f15e8870 19 7 +UseCaseUsage differencingType a285ee2a5d843e24 19 0 +UseCaseUsage directedFeature f86f511477c581da 19 8 +UseCaseUsage directedUsage f86f511477c581da 19 8 +UseCaseUsage direction a9dc2ad030387ca3 19 0 +UseCaseUsage documentation a285ee2a5d843e24 19 0 +UseCaseUsage elementId 396524a0e5f04fd8 19 19 +UseCaseUsage endFeature a285ee2a5d843e24 19 0 +UseCaseUsage endOwningType a9dc2ad030387ca3 19 0 +UseCaseUsage feature 847130c857bf9586 19 14 +UseCaseUsage featureMembership 44cf9dc754fc873f 19 14 +UseCaseUsage featureTarget 6059a2601e140b63 19 0 +UseCaseUsage featuringType a285ee2a5d843e24 19 0 +UseCaseUsage function a03488b329e7b51e 19 7 +UseCaseUsage importedMembership a285ee2a5d843e24 19 0 +UseCaseUsage includedUseCase 78c8cc63da361c10 19 5 +UseCaseUsage individualDefinition a9dc2ad030387ca3 19 0 +UseCaseUsage inheritedFeature a285ee2a5d843e24 19 0 +UseCaseUsage inheritedMembership a285ee2a5d843e24 19 0 +UseCaseUsage input f86f511477c581da 19 8 +UseCaseUsage intersectingType a285ee2a5d843e24 19 0 +UseCaseUsage isAbstract 178809e01a399c5e 19 1 +UseCaseUsage isComposite 622b303875239918 19 3 +UseCaseUsage isConjugated dbc1da3fb3a85961 19 0 +UseCaseUsage isConstant dbc1da3fb3a85961 19 0 +UseCaseUsage isDerived dbc1da3fb3a85961 19 0 +UseCaseUsage isEnd dbc1da3fb3a85961 19 0 +UseCaseUsage isImpliedIncluded 8b4a028b0d2e5240 19 19 +UseCaseUsage isIndividual a9dc2ad030387ca3 19 0 +UseCaseUsage isLibraryElement dbc1da3fb3a85961 19 0 +UseCaseUsage isModelLevelEvaluable dbc1da3fb3a85961 19 0 +UseCaseUsage isOrdered dbc1da3fb3a85961 19 0 +UseCaseUsage isPortion a9dc2ad030387ca3 19 0 +UseCaseUsage isReference 04e0ac924bb31289 19 16 +UseCaseUsage isSufficient a9dc2ad030387ca3 19 0 +UseCaseUsage isUnique 8b4a028b0d2e5240 19 19 +UseCaseUsage isVariable a9dc2ad030387ca3 19 0 +UseCaseUsage isVariation 178809e01a399c5e 19 1 +UseCaseUsage mayTimeVary a9dc2ad030387ca3 19 0 +UseCaseUsage member 43dd5f1120221f37 19 15 +UseCaseUsage membership 1c0113dd5d7c3feb 19 15 +UseCaseUsage multiplicity a9dc2ad030387ca3 19 0 +UseCaseUsage name 667d9584b56cba49 19 19 +UseCaseUsage nestedAction b24b71e29d1caf70 19 9 +UseCaseUsage nestedAllocation a285ee2a5d843e24 19 0 +UseCaseUsage nestedAnalysisCase a285ee2a5d843e24 19 0 +UseCaseUsage nestedAttribute a285ee2a5d843e24 19 0 +UseCaseUsage nestedCalculation d98ec61b66cdff4a 19 5 +UseCaseUsage nestedCase d98ec61b66cdff4a 19 5 +UseCaseUsage nestedConcern a285ee2a5d843e24 19 0 +UseCaseUsage nestedConnection 55396b46eb7b49b8 19 6 +UseCaseUsage nestedConstraint d6eb9d37a8e4ba76 19 1 +UseCaseUsage nestedEnumeration a285ee2a5d843e24 19 0 +UseCaseUsage nestedFlow a285ee2a5d843e24 19 0 +UseCaseUsage nestedInterface 4fee5f77da3b335d 19 8 +UseCaseUsage nestedItem 3d76f3e6aca22f63 19 7 +UseCaseUsage nestedMetadata a285ee2a5d843e24 19 0 +UseCaseUsage nestedOccurrence 1c2049fe4c0e2cf7 19 14 +UseCaseUsage nestedPart 3d76f3e6aca22f63 19 7 +UseCaseUsage nestedPort a285ee2a5d843e24 19 0 +UseCaseUsage nestedReference 4fee5f77da3b335d 19 8 +UseCaseUsage nestedRendering a285ee2a5d843e24 19 0 +UseCaseUsage nestedRequirement d6eb9d37a8e4ba76 19 1 +UseCaseUsage nestedState a285ee2a5d843e24 19 0 +UseCaseUsage nestedTransition a285ee2a5d843e24 19 0 +UseCaseUsage nestedUsage 847130c857bf9586 19 14 +UseCaseUsage nestedUseCase d98ec61b66cdff4a 19 5 +UseCaseUsage nestedVerificationCase a285ee2a5d843e24 19 0 +UseCaseUsage nestedView a285ee2a5d843e24 19 0 +UseCaseUsage nestedViewpoint a285ee2a5d843e24 19 0 +UseCaseUsage objectiveRequirement 61da660d6faa2330 19 1 +UseCaseUsage occurrenceDefinition 35190a62f15e8870 19 7 +UseCaseUsage output a285ee2a5d843e24 19 0 +UseCaseUsage ownedAnnotation a285ee2a5d843e24 19 0 +UseCaseUsage ownedConjugator a9dc2ad030387ca3 19 0 +UseCaseUsage ownedCrossSubsetting a9dc2ad030387ca3 19 0 +UseCaseUsage ownedDifferencing a285ee2a5d843e24 19 0 +UseCaseUsage ownedDisjoining a285ee2a5d843e24 19 0 +UseCaseUsage ownedElement 5dcf2dcba0806532 19 15 +UseCaseUsage ownedEndFeature a285ee2a5d843e24 19 0 +UseCaseUsage ownedFeature 847130c857bf9586 19 14 +UseCaseUsage ownedFeatureChaining a285ee2a5d843e24 19 0 +UseCaseUsage ownedFeatureInverting a285ee2a5d843e24 19 0 +UseCaseUsage ownedFeatureMembership 44cf9dc754fc873f 19 14 +UseCaseUsage ownedImport a285ee2a5d843e24 19 0 +UseCaseUsage ownedIntersecting a285ee2a5d843e24 19 0 +UseCaseUsage ownedMember 5dcf2dcba0806532 19 15 +UseCaseUsage ownedMembership 1c0113dd5d7c3feb 19 15 +UseCaseUsage ownedRedefinition a285ee2a5d843e24 19 0 +UseCaseUsage ownedReferenceSubsetting a9dc2ad030387ca3 19 0 +UseCaseUsage ownedRelationship 8ca4dde86e65c320 19 19 +UseCaseUsage ownedSpecialization 0321a3b408631937 19 19 +UseCaseUsage ownedSubsetting 78a2d12c4a3fec69 19 19 +UseCaseUsage ownedTypeFeaturing a285ee2a5d843e24 19 0 +UseCaseUsage ownedTyping 6d0e035b323165d0 19 7 +UseCaseUsage ownedUnioning a285ee2a5d843e24 19 0 +UseCaseUsage owner 5deb033bd178b9fc 19 19 +UseCaseUsage owningDefinition a9dc2ad030387ca3 19 0 +UseCaseUsage owningFeatureMembership 54916a4581969c30 19 3 +UseCaseUsage owningMembership 4767c8062fa33a73 19 19 +UseCaseUsage owningNamespace 5deb033bd178b9fc 19 19 +UseCaseUsage owningRelationship 4767c8062fa33a73 19 19 +UseCaseUsage owningType 595576c8faab3770 19 3 +UseCaseUsage owningUsage 595576c8faab3770 19 3 +UseCaseUsage parameter f86f511477c581da 19 8 +UseCaseUsage portionKind a9dc2ad030387ca3 19 0 +UseCaseUsage qualifiedName 74c9e975eaacd365 19 19 +UseCaseUsage result 6059a2601e140b63 19 0 +UseCaseUsage shortName a9dc2ad030387ca3 19 0 +UseCaseUsage subjectParameter 10e47a82428db30f 19 8 +UseCaseUsage textualRepresentation a285ee2a5d843e24 19 0 +UseCaseUsage type 35190a62f15e8870 19 7 +UseCaseUsage unioningType a285ee2a5d843e24 19 0 +UseCaseUsage usage 847130c857bf9586 19 14 +UseCaseUsage useCaseDefinition a03488b329e7b51e 19 7 +UseCaseUsage variant 3621a53d41c54081 19 1 +UseCaseUsage variantMembership 45f5cc7d19849c39 19 1 +VariantMembership aliasIds b537a5c8e4532cbd 107 0 +VariantMembership declaredName 0353983341a8c1e2 107 0 +VariantMembership declaredShortName 0353983341a8c1e2 107 0 +VariantMembership documentation b537a5c8e4532cbd 107 0 +VariantMembership elementId 67aa29443aeed3f4 107 107 +VariantMembership isImplied 46d71125b8c476b6 107 0 +VariantMembership isImpliedIncluded 46aae84ea50cd3f5 107 107 +VariantMembership isLibraryElement b21fa829f07efb56 107 8 +VariantMembership memberElement 0676ed2bdc47728d 107 107 +VariantMembership memberElementId 04ac34d1d5faabd0 107 107 +VariantMembership memberName 8e2b8330c1298042 107 101 +VariantMembership memberShortName 0353983341a8c1e2 107 0 +VariantMembership membershipOwningNamespace 02ea3522c55a0488 107 107 +VariantMembership name 0353983341a8c1e2 107 0 +VariantMembership ownedAnnotation b537a5c8e4532cbd 107 0 +VariantMembership ownedElement b537a5c8e4532cbd 107 0 +VariantMembership ownedMemberElement 0676ed2bdc47728d 107 107 +VariantMembership ownedMemberElementId 04ac34d1d5faabd0 107 107 +VariantMembership ownedMemberName 8e2b8330c1298042 107 101 +VariantMembership ownedMemberShortName 0353983341a8c1e2 107 0 +VariantMembership ownedRelatedElement 9bf89b04e775e15d 107 107 +VariantMembership ownedRelationship b537a5c8e4532cbd 107 0 +VariantMembership ownedVariantUsage 0676ed2bdc47728d 107 107 +VariantMembership owner 0353983341a8c1e2 107 0 +VariantMembership owningMembership 0353983341a8c1e2 107 0 +VariantMembership owningNamespace 0353983341a8c1e2 107 0 +VariantMembership owningRelatedElement 02ea3522c55a0488 107 107 +VariantMembership owningRelationship 0353983341a8c1e2 107 0 +VariantMembership qualifiedName 0353983341a8c1e2 107 0 +VariantMembership relatedElement b6a1e52a49d14a78 107 107 +VariantMembership shortName 0353983341a8c1e2 107 0 +VariantMembership source 6b2a5bad550a895e 107 107 +VariantMembership target 9bf89b04e775e15d 107 107 +VariantMembership textualRepresentation b537a5c8e4532cbd 107 0 +VariantMembership visibility 7062d1d72794050c 107 107 +VerificationCaseDefinition action b026ddc35909a3ce 8 2 +VerificationCaseDefinition actorParameter c5e1b725371404b2 8 0 +VerificationCaseDefinition aliasIds c5e1b725371404b2 8 0 +VerificationCaseDefinition calculation e8a36115091a77d7 8 1 +VerificationCaseDefinition declaredName 65480c1333aae069 8 8 +VerificationCaseDefinition declaredShortName d7e0f288d05a3302 8 0 +VerificationCaseDefinition differencingType c5e1b725371404b2 8 0 +VerificationCaseDefinition directedFeature 1ada936cb2db025d 8 3 +VerificationCaseDefinition directedUsage 1ada936cb2db025d 8 3 +VerificationCaseDefinition documentation c5e1b725371404b2 8 0 +VerificationCaseDefinition elementId cf2fa6a0b8c06af0 8 8 +VerificationCaseDefinition endFeature c5e1b725371404b2 8 0 +VerificationCaseDefinition expression bf2ec33ac0fdeb56 8 4 +VerificationCaseDefinition feature bf8be791fb8157d8 8 4 +VerificationCaseDefinition featureMembership 6caa258e3c288bd3 8 4 +VerificationCaseDefinition importedMembership c5e1b725371404b2 8 0 +VerificationCaseDefinition inheritedFeature c5e1b725371404b2 8 0 +VerificationCaseDefinition inheritedMembership c5e1b725371404b2 8 0 +VerificationCaseDefinition input cf59547c418d9d96 8 3 +VerificationCaseDefinition intersectingType c5e1b725371404b2 8 0 +VerificationCaseDefinition isAbstract a67d779d22394b1a 8 0 +VerificationCaseDefinition isConjugated a67d779d22394b1a 8 0 +VerificationCaseDefinition isImpliedIncluded 9e43ab194033b6fa 8 8 +VerificationCaseDefinition isIndividual d7e0f288d05a3302 8 0 +VerificationCaseDefinition isLibraryElement a67d779d22394b1a 8 0 +VerificationCaseDefinition isModelLevelEvaluable a67d779d22394b1a 8 0 +VerificationCaseDefinition isSufficient a67d779d22394b1a 8 0 +VerificationCaseDefinition isVariation a67d779d22394b1a 8 0 +VerificationCaseDefinition member bf8be791fb8157d8 8 4 +VerificationCaseDefinition membership 6caa258e3c288bd3 8 4 +VerificationCaseDefinition multiplicity d7e0f288d05a3302 8 0 +VerificationCaseDefinition name 65480c1333aae069 8 8 +VerificationCaseDefinition objectiveRequirement 283b9ba31e4cae92 8 4 +VerificationCaseDefinition output 2c4702d3fc7d02cd 8 1 +VerificationCaseDefinition ownedAction b026ddc35909a3ce 8 2 +VerificationCaseDefinition ownedAllocation c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedAnalysisCase c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedAnnotation c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedAttribute c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedCalculation e8a36115091a77d7 8 1 +VerificationCaseDefinition ownedCase e8a36115091a77d7 8 1 +VerificationCaseDefinition ownedConcern c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedConjugator d7e0f288d05a3302 8 0 +VerificationCaseDefinition ownedConnection c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedConstraint fd46ba941e83c5f6 8 4 +VerificationCaseDefinition ownedDifferencing c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedDisjoining c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedElement bf8be791fb8157d8 8 4 +VerificationCaseDefinition ownedEndFeature c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedEnumeration c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedFeature bf8be791fb8157d8 8 4 +VerificationCaseDefinition ownedFeatureMembership 6caa258e3c288bd3 8 4 +VerificationCaseDefinition ownedFlow c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedImport 5ab819eadd40e064 8 1 +VerificationCaseDefinition ownedInterface 1ada936cb2db025d 8 3 +VerificationCaseDefinition ownedIntersecting c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedItem c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedMember bf8be791fb8157d8 8 4 +VerificationCaseDefinition ownedMembership 6caa258e3c288bd3 8 4 +VerificationCaseDefinition ownedMetadata c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedOccurrence 50dced05783175f8 8 4 +VerificationCaseDefinition ownedPart c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedPort c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedReference 1ada936cb2db025d 8 3 +VerificationCaseDefinition ownedRelationship 4f2a7319ad114671 8 8 +VerificationCaseDefinition ownedRendering c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedRequirement fd46ba941e83c5f6 8 4 +VerificationCaseDefinition ownedSpecialization 130ac9824753e602 8 8 +VerificationCaseDefinition ownedState c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedSubclassification 130ac9824753e602 8 8 +VerificationCaseDefinition ownedTransition c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedUnioning c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedUsage 25d492e733516717 8 4 +VerificationCaseDefinition ownedUseCase c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedVerificationCase e8a36115091a77d7 8 1 +VerificationCaseDefinition ownedView c5e1b725371404b2 8 0 +VerificationCaseDefinition ownedViewpoint c5e1b725371404b2 8 0 +VerificationCaseDefinition owner 2cfa39e1101f5829 8 8 +VerificationCaseDefinition owningMembership d0556178fda9462d 8 8 +VerificationCaseDefinition owningNamespace 2cfa39e1101f5829 8 8 +VerificationCaseDefinition owningRelationship d0556178fda9462d 8 8 +VerificationCaseDefinition parameter 1ada936cb2db025d 8 3 +VerificationCaseDefinition qualifiedName 63037d474873502e 8 8 +VerificationCaseDefinition result 592ade2ed6e78c19 8 1 +VerificationCaseDefinition shortName d7e0f288d05a3302 8 0 +VerificationCaseDefinition step c3c315badc5e0f49 8 4 +VerificationCaseDefinition subjectParameter 973a29a9befa3110 8 3 +VerificationCaseDefinition textualRepresentation c5e1b725371404b2 8 0 +VerificationCaseDefinition unioningType c5e1b725371404b2 8 0 +VerificationCaseDefinition usage 25d492e733516717 8 4 +VerificationCaseDefinition variant c5e1b725371404b2 8 0 +VerificationCaseDefinition variantMembership c5e1b725371404b2 8 0 +VerificationCaseDefinition verifiedRequirement 3a0230f6146d4ecd 8 4 +VerificationCaseUsage actionDefinition 65dea69ce5eeb749 7 6 +VerificationCaseUsage actorParameter e891dee753a59e6e 7 1 +VerificationCaseUsage aliasIds 02b68886545128ef 7 0 +VerificationCaseUsage behavior 65dea69ce5eeb749 7 6 +VerificationCaseUsage calculationDefinition 38ff9586a9e6f8c4 7 6 +VerificationCaseUsage caseDefinition 38ff9586a9e6f8c4 7 6 +VerificationCaseUsage chainingFeature 02b68886545128ef 7 0 +VerificationCaseUsage crossFeature 4f2c344fdb1aef78 7 0 +VerificationCaseUsage declaredName c47f146509c830e7 7 7 +VerificationCaseUsage declaredShortName 4f2c344fdb1aef78 7 0 +VerificationCaseUsage definition 65dea69ce5eeb749 7 6 +VerificationCaseUsage differencingType 02b68886545128ef 7 0 +VerificationCaseUsage directedFeature 69de77d4d5555ca8 7 4 +VerificationCaseUsage directedUsage 69de77d4d5555ca8 7 4 +VerificationCaseUsage direction 4f2c344fdb1aef78 7 0 +VerificationCaseUsage documentation 02b68886545128ef 7 0 +VerificationCaseUsage elementId 4e5f363e39e867c0 7 7 +VerificationCaseUsage endFeature 02b68886545128ef 7 0 +VerificationCaseUsage endOwningType 4f2c344fdb1aef78 7 0 +VerificationCaseUsage feature 3cf6669ba04574a0 7 5 +VerificationCaseUsage featureMembership c6e925c0e5e33e06 7 5 +VerificationCaseUsage featureTarget 9c827391eea3d431 7 0 +VerificationCaseUsage featuringType 02b68886545128ef 7 0 +VerificationCaseUsage function 38ff9586a9e6f8c4 7 6 +VerificationCaseUsage importedMembership 02b68886545128ef 7 0 +VerificationCaseUsage individualDefinition 4f2c344fdb1aef78 7 0 +VerificationCaseUsage inheritedFeature 02b68886545128ef 7 0 +VerificationCaseUsage inheritedMembership 02b68886545128ef 7 0 +VerificationCaseUsage input 05b01b219953247b 7 4 +VerificationCaseUsage intersectingType 02b68886545128ef 7 0 +VerificationCaseUsage isAbstract d1691d40d1979ae1 7 1 +VerificationCaseUsage isComposite 0ec9cfd0a76fc4ce 7 2 +VerificationCaseUsage isConjugated ce22b7215500567c 7 0 +VerificationCaseUsage isConstant ce22b7215500567c 7 0 +VerificationCaseUsage isDerived ce22b7215500567c 7 0 +VerificationCaseUsage isEnd ce22b7215500567c 7 0 +VerificationCaseUsage isImpliedIncluded 2e605d4757f4e0ff 7 7 +VerificationCaseUsage isIndividual 4f2c344fdb1aef78 7 0 +VerificationCaseUsage isLibraryElement ce22b7215500567c 7 0 +VerificationCaseUsage isModelLevelEvaluable ce22b7215500567c 7 0 +VerificationCaseUsage isOrdered ce22b7215500567c 7 0 +VerificationCaseUsage isPortion 4f2c344fdb1aef78 7 0 +VerificationCaseUsage isReference edb94498058572ad 7 5 +VerificationCaseUsage isSufficient 4f2c344fdb1aef78 7 0 +VerificationCaseUsage isUnique 2e605d4757f4e0ff 7 7 +VerificationCaseUsage isVariable 4f2c344fdb1aef78 7 0 +VerificationCaseUsage isVariation d1691d40d1979ae1 7 1 +VerificationCaseUsage mayTimeVary 4f2c344fdb1aef78 7 0 +VerificationCaseUsage member 886a091542b0f255 7 5 +VerificationCaseUsage membership bb7a81cfe16a3bf7 7 5 +VerificationCaseUsage multiplicity 4f2c344fdb1aef78 7 0 +VerificationCaseUsage name c47f146509c830e7 7 7 +VerificationCaseUsage nestedAction 9ec560dd24414f67 7 3 +VerificationCaseUsage nestedAllocation 02b68886545128ef 7 0 +VerificationCaseUsage nestedAnalysisCase 02b68886545128ef 7 0 +VerificationCaseUsage nestedAttribute 02b68886545128ef 7 0 +VerificationCaseUsage nestedCalculation 02b68886545128ef 7 0 +VerificationCaseUsage nestedCase 02b68886545128ef 7 0 +VerificationCaseUsage nestedConcern 02b68886545128ef 7 0 +VerificationCaseUsage nestedConnection 3d3177d653609b7c 7 1 +VerificationCaseUsage nestedConstraint 652d187178af0d44 7 3 +VerificationCaseUsage nestedEnumeration 02b68886545128ef 7 0 +VerificationCaseUsage nestedFlow 02b68886545128ef 7 0 +VerificationCaseUsage nestedInterface bb78f69beb70e941 7 4 +VerificationCaseUsage nestedItem e891dee753a59e6e 7 1 +VerificationCaseUsage nestedMetadata 02b68886545128ef 7 0 +VerificationCaseUsage nestedOccurrence 394ef5480a5408c3 7 3 +VerificationCaseUsage nestedPart e891dee753a59e6e 7 1 +VerificationCaseUsage nestedPort 02b68886545128ef 7 0 +VerificationCaseUsage nestedReference bb78f69beb70e941 7 4 +VerificationCaseUsage nestedRendering 02b68886545128ef 7 0 +VerificationCaseUsage nestedRequirement 652d187178af0d44 7 3 +VerificationCaseUsage nestedState 02b68886545128ef 7 0 +VerificationCaseUsage nestedTransition 02b68886545128ef 7 0 +VerificationCaseUsage nestedUsage 3cf6669ba04574a0 7 5 +VerificationCaseUsage nestedUseCase 02b68886545128ef 7 0 +VerificationCaseUsage nestedVerificationCase 02b68886545128ef 7 0 +VerificationCaseUsage nestedView 02b68886545128ef 7 0 +VerificationCaseUsage nestedViewpoint 02b68886545128ef 7 0 +VerificationCaseUsage objectiveRequirement 4c316abd8b282dbe 7 3 +VerificationCaseUsage occurrenceDefinition 65dea69ce5eeb749 7 6 +VerificationCaseUsage output 2fa001de92a535de 7 2 +VerificationCaseUsage ownedAnnotation 02b68886545128ef 7 0 +VerificationCaseUsage ownedConjugator 4f2c344fdb1aef78 7 0 +VerificationCaseUsage ownedCrossSubsetting 4f2c344fdb1aef78 7 0 +VerificationCaseUsage ownedDifferencing 02b68886545128ef 7 0 +VerificationCaseUsage ownedDisjoining 02b68886545128ef 7 0 +VerificationCaseUsage ownedElement 886a091542b0f255 7 5 +VerificationCaseUsage ownedEndFeature 02b68886545128ef 7 0 +VerificationCaseUsage ownedFeature 3cf6669ba04574a0 7 5 +VerificationCaseUsage ownedFeatureChaining 02b68886545128ef 7 0 +VerificationCaseUsage ownedFeatureInverting 02b68886545128ef 7 0 +VerificationCaseUsage ownedFeatureMembership c6e925c0e5e33e06 7 5 +VerificationCaseUsage ownedImport 02b68886545128ef 7 0 +VerificationCaseUsage ownedIntersecting 02b68886545128ef 7 0 +VerificationCaseUsage ownedMember 886a091542b0f255 7 5 +VerificationCaseUsage ownedMembership bb7a81cfe16a3bf7 7 5 +VerificationCaseUsage ownedRedefinition 02b68886545128ef 7 0 +VerificationCaseUsage ownedReferenceSubsetting 4f2c344fdb1aef78 7 0 +VerificationCaseUsage ownedRelationship bf063f1fb6b9aa87 7 7 +VerificationCaseUsage ownedSpecialization 53c4f05df5dd3b0f 7 7 +VerificationCaseUsage ownedSubsetting a314727b26ffe2b1 7 7 +VerificationCaseUsage ownedTypeFeaturing 02b68886545128ef 7 0 +VerificationCaseUsage ownedTyping 8dcc690cd2fe0fb3 7 6 +VerificationCaseUsage ownedUnioning 02b68886545128ef 7 0 +VerificationCaseUsage owner 5e5196ca44de3cf0 7 7 +VerificationCaseUsage owningDefinition 4237967c0529f34e 7 1 +VerificationCaseUsage owningFeatureMembership 354116cca9b8bd6e 7 2 +VerificationCaseUsage owningMembership 93fa8c13c4007628 7 7 +VerificationCaseUsage owningNamespace 5e5196ca44de3cf0 7 7 +VerificationCaseUsage owningRelationship 93fa8c13c4007628 7 7 +VerificationCaseUsage owningType c9235fd6cf6399f2 7 2 +VerificationCaseUsage owningUsage d617fdaaa554961c 7 1 +VerificationCaseUsage parameter 69de77d4d5555ca8 7 4 +VerificationCaseUsage portionKind 4f2c344fdb1aef78 7 0 +VerificationCaseUsage qualifiedName 07db03b99acf9fce 7 7 +VerificationCaseUsage result 927a829d9909ecaa 7 2 +VerificationCaseUsage shortName 4f2c344fdb1aef78 7 0 +VerificationCaseUsage subjectParameter 6e582ad2f3c7dfe3 7 4 +VerificationCaseUsage textualRepresentation 02b68886545128ef 7 0 +VerificationCaseUsage type 65dea69ce5eeb749 7 6 +VerificationCaseUsage unioningType 02b68886545128ef 7 0 +VerificationCaseUsage usage 3cf6669ba04574a0 7 5 +VerificationCaseUsage variant 02b68886545128ef 7 0 +VerificationCaseUsage variantMembership 02b68886545128ef 7 0 +VerificationCaseUsage verificationCaseDefinition 38ff9586a9e6f8c4 7 6 +VerificationCaseUsage verifiedRequirement cf7fca608bd4e735 7 2 +ViewDefinition aliasIds 86c52aa119d18c10 10 0 +ViewDefinition declaredName b93ad6908fe682a6 10 10 +ViewDefinition declaredShortName d9eb4dca7215301a 10 0 +ViewDefinition differencingType 86c52aa119d18c10 10 0 +ViewDefinition directedFeature 86c52aa119d18c10 10 0 +ViewDefinition directedUsage 86c52aa119d18c10 10 0 +ViewDefinition documentation 86c52aa119d18c10 10 0 +ViewDefinition elementId 0ea8ea7836be3bf8 10 10 +ViewDefinition endFeature 86c52aa119d18c10 10 0 +ViewDefinition feature 6bba54cb169214f6 10 4 +ViewDefinition featureMembership 5e1e446403abf249 10 4 +ViewDefinition importedMembership 86c52aa119d18c10 10 0 +ViewDefinition inheritedFeature 86c52aa119d18c10 10 0 +ViewDefinition inheritedMembership 86c52aa119d18c10 10 0 +ViewDefinition input 86c52aa119d18c10 10 0 +ViewDefinition intersectingType 86c52aa119d18c10 10 0 +ViewDefinition isAbstract e5e0f84d9d95ac96 10 0 +ViewDefinition isConjugated e5e0f84d9d95ac96 10 0 +ViewDefinition isImpliedIncluded 609bc5ac833245b8 10 10 +ViewDefinition isIndividual d9eb4dca7215301a 10 0 +ViewDefinition isLibraryElement e5e0f84d9d95ac96 10 0 +ViewDefinition isSufficient e5e0f84d9d95ac96 10 0 +ViewDefinition isVariation e5e0f84d9d95ac96 10 0 +ViewDefinition member 1ac4eac732877a8d 10 6 +ViewDefinition membership b127a58e4001d032 10 6 +ViewDefinition multiplicity d9eb4dca7215301a 10 0 +ViewDefinition name b93ad6908fe682a6 10 10 +ViewDefinition output 86c52aa119d18c10 10 0 +ViewDefinition ownedAction 86c52aa119d18c10 10 0 +ViewDefinition ownedAllocation 86c52aa119d18c10 10 0 +ViewDefinition ownedAnalysisCase 86c52aa119d18c10 10 0 +ViewDefinition ownedAnnotation 86c52aa119d18c10 10 0 +ViewDefinition ownedAttribute 86c52aa119d18c10 10 0 +ViewDefinition ownedCalculation 86c52aa119d18c10 10 0 +ViewDefinition ownedCase 86c52aa119d18c10 10 0 +ViewDefinition ownedConcern 86c52aa119d18c10 10 0 +ViewDefinition ownedConjugator d9eb4dca7215301a 10 0 +ViewDefinition ownedConnection 86c52aa119d18c10 10 0 +ViewDefinition ownedConstraint b67b71907591cc26 10 2 +ViewDefinition ownedDifferencing 86c52aa119d18c10 10 0 +ViewDefinition ownedDisjoining 86c52aa119d18c10 10 0 +ViewDefinition ownedElement 1ac4eac732877a8d 10 6 +ViewDefinition ownedEndFeature 86c52aa119d18c10 10 0 +ViewDefinition ownedEnumeration 86c52aa119d18c10 10 0 +ViewDefinition ownedFeature 6bba54cb169214f6 10 4 +ViewDefinition ownedFeatureMembership 5e1e446403abf249 10 4 +ViewDefinition ownedFlow 86c52aa119d18c10 10 0 +ViewDefinition ownedImport 86c52aa119d18c10 10 0 +ViewDefinition ownedInterface 86c52aa119d18c10 10 0 +ViewDefinition ownedIntersecting 86c52aa119d18c10 10 0 +ViewDefinition ownedItem 06d58e3e5e255c3c 10 3 +ViewDefinition ownedMember 1ac4eac732877a8d 10 6 +ViewDefinition ownedMembership b127a58e4001d032 10 6 +ViewDefinition ownedMetadata 86c52aa119d18c10 10 0 +ViewDefinition ownedOccurrence 6bba54cb169214f6 10 4 +ViewDefinition ownedPart 06d58e3e5e255c3c 10 3 +ViewDefinition ownedPort 86c52aa119d18c10 10 0 +ViewDefinition ownedReference 86c52aa119d18c10 10 0 +ViewDefinition ownedRelationship 3a0cf9c4725b0687 10 10 +ViewDefinition ownedRendering 437d0b964b3dbe41 10 3 +ViewDefinition ownedRequirement b67b71907591cc26 10 2 +ViewDefinition ownedSpecialization 8f54fc6866369def 10 10 +ViewDefinition ownedState 86c52aa119d18c10 10 0 +ViewDefinition ownedSubclassification 8f54fc6866369def 10 10 +ViewDefinition ownedTransition 86c52aa119d18c10 10 0 +ViewDefinition ownedUnioning 86c52aa119d18c10 10 0 +ViewDefinition ownedUsage 6bba54cb169214f6 10 4 +ViewDefinition ownedUseCase 86c52aa119d18c10 10 0 +ViewDefinition ownedVerificationCase 86c52aa119d18c10 10 0 +ViewDefinition ownedView e687f2682852995b 10 1 +ViewDefinition ownedViewpoint 4a2d1bf858ead0e1 10 1 +ViewDefinition owner a96a8dbad16cdc7f 10 10 +ViewDefinition owningMembership 0286253c9cae429b 10 10 +ViewDefinition owningNamespace a96a8dbad16cdc7f 10 10 +ViewDefinition owningRelationship 0286253c9cae429b 10 10 +ViewDefinition qualifiedName 23dde0c34fa0fe1f 10 10 +ViewDefinition satisfiedViewpoint 4a2d1bf858ead0e1 10 1 +ViewDefinition shortName d9eb4dca7215301a 10 0 +ViewDefinition textualRepresentation 86c52aa119d18c10 10 0 +ViewDefinition unioningType 86c52aa119d18c10 10 0 +ViewDefinition usage 6bba54cb169214f6 10 4 +ViewDefinition variant 86c52aa119d18c10 10 0 +ViewDefinition variantMembership 86c52aa119d18c10 10 0 +ViewDefinition view e687f2682852995b 10 1 +ViewDefinition viewCondition 4acd2e994cf1bf88 10 4 +ViewDefinition viewRendering b568fcc4551a03fe 10 3 +ViewRenderingMembership aliasIds 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership declaredName 0365f84e69262855 11 0 +ViewRenderingMembership declaredShortName 0365f84e69262855 11 0 +ViewRenderingMembership documentation 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership elementId b2d52233cacb5680 11 11 +ViewRenderingMembership isImplied d7ccb446a7ac8c53 11 0 +ViewRenderingMembership isImpliedIncluded 53a9a0f9d4c4dad2 11 11 +ViewRenderingMembership isLibraryElement d7ccb446a7ac8c53 11 0 +ViewRenderingMembership memberElement 87468ed5516cdead 11 11 +ViewRenderingMembership memberElementId 8d852443ae8ef132 11 11 +ViewRenderingMembership memberName 09f36c72fc3ff2a5 11 11 +ViewRenderingMembership memberShortName 0365f84e69262855 11 0 +ViewRenderingMembership membershipOwningNamespace 9c81f26ab7905105 11 11 +ViewRenderingMembership name 0365f84e69262855 11 0 +ViewRenderingMembership ownedAnnotation 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership ownedElement 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership ownedMemberElement 87468ed5516cdead 11 11 +ViewRenderingMembership ownedMemberElementId 8d852443ae8ef132 11 11 +ViewRenderingMembership ownedMemberFeature 87468ed5516cdead 11 11 +ViewRenderingMembership ownedMemberName 09f36c72fc3ff2a5 11 11 +ViewRenderingMembership ownedMemberShortName 0365f84e69262855 11 0 +ViewRenderingMembership ownedRelatedElement 19a22f3a67e77bd7 11 11 +ViewRenderingMembership ownedRelationship 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership ownedRendering 87468ed5516cdead 11 11 +ViewRenderingMembership owner 0365f84e69262855 11 0 +ViewRenderingMembership owningMembership 0365f84e69262855 11 0 +ViewRenderingMembership owningNamespace 0365f84e69262855 11 0 +ViewRenderingMembership owningRelatedElement 9c81f26ab7905105 11 11 +ViewRenderingMembership owningRelationship 0365f84e69262855 11 0 +ViewRenderingMembership owningType 9c81f26ab7905105 11 11 +ViewRenderingMembership qualifiedName 0365f84e69262855 11 0 +ViewRenderingMembership referencedRendering 2d1e6cab1d268ca6 11 11 +ViewRenderingMembership relatedElement bb17228bebd2f6fc 11 11 +ViewRenderingMembership shortName 0365f84e69262855 11 0 +ViewRenderingMembership source f11964459647d5d3 11 11 +ViewRenderingMembership target 19a22f3a67e77bd7 11 11 +ViewRenderingMembership textualRepresentation 04c2b62e7ca8a6c6 11 0 +ViewRenderingMembership visibility 8c00029d5fe4e93b 11 11 +ViewUsage aliasIds 4789f8737172dea1 12 0 +ViewUsage chainingFeature 4789f8737172dea1 12 0 +ViewUsage crossFeature c23e8ae6760020e3 12 0 +ViewUsage declaredName 26d9344fab470ccd 12 10 +ViewUsage declaredShortName c23e8ae6760020e3 12 0 +ViewUsage definition 677fee971a7c577c 12 7 +ViewUsage differencingType 4789f8737172dea1 12 0 +ViewUsage directedFeature 4789f8737172dea1 12 0 +ViewUsage directedUsage 4789f8737172dea1 12 0 +ViewUsage direction c23e8ae6760020e3 12 0 +ViewUsage documentation 4789f8737172dea1 12 0 +ViewUsage elementId e5d679ca1f676f90 12 12 +ViewUsage endFeature 4789f8737172dea1 12 0 +ViewUsage endOwningType c23e8ae6760020e3 12 0 +ViewUsage exposedElement 9e6ca563d86b791e 12 5 +ViewUsage feature 15475ca54b215094 12 10 +ViewUsage featureMembership 6702e120b0532c5e 12 10 +ViewUsage featureTarget f57e1995ecd98326 12 0 +ViewUsage featuringType 4789f8737172dea1 12 0 +ViewUsage importedMembership 4789f8737172dea1 12 0 +ViewUsage individualDefinition c23e8ae6760020e3 12 0 +ViewUsage inheritedFeature 4789f8737172dea1 12 0 +ViewUsage inheritedMembership 4789f8737172dea1 12 0 +ViewUsage input 4789f8737172dea1 12 0 +ViewUsage intersectingType 4789f8737172dea1 12 0 +ViewUsage isAbstract f8f067f2de2253a1 12 0 +ViewUsage isComposite 071ff71976dd384a 12 5 +ViewUsage isConjugated f8f067f2de2253a1 12 0 +ViewUsage isConstant f8f067f2de2253a1 12 0 +ViewUsage isDerived f8f067f2de2253a1 12 0 +ViewUsage isEnd f8f067f2de2253a1 12 0 +ViewUsage isImpliedIncluded 9e820901655ae95d 12 12 +ViewUsage isIndividual c23e8ae6760020e3 12 0 +ViewUsage isLibraryElement f8f067f2de2253a1 12 0 +ViewUsage isOrdered f8f067f2de2253a1 12 0 +ViewUsage isPortion c23e8ae6760020e3 12 0 +ViewUsage isReference 905279dacca004b4 12 7 +ViewUsage isSufficient c23e8ae6760020e3 12 0 +ViewUsage isUnique 9e820901655ae95d 12 12 +ViewUsage isVariable c23e8ae6760020e3 12 0 +ViewUsage isVariation f8f067f2de2253a1 12 0 +ViewUsage itemDefinition 677fee971a7c577c 12 7 +ViewUsage mayTimeVary c23e8ae6760020e3 12 0 +ViewUsage member 5af166e978e5ea0a 12 11 +ViewUsage membership 7361b9c21295bca0 12 11 +ViewUsage multiplicity fe9ddf5641c608fa 12 3 +ViewUsage name 63f74b7c3d809ff1 12 12 +ViewUsage nestedAction 4789f8737172dea1 12 0 +ViewUsage nestedAllocation 4789f8737172dea1 12 0 +ViewUsage nestedAnalysisCase 4789f8737172dea1 12 0 +ViewUsage nestedAttribute 4789f8737172dea1 12 0 +ViewUsage nestedCalculation 4789f8737172dea1 12 0 +ViewUsage nestedCase 4789f8737172dea1 12 0 +ViewUsage nestedConcern 4789f8737172dea1 12 0 +ViewUsage nestedConnection 4789f8737172dea1 12 0 +ViewUsage nestedConstraint aba7619845339ef3 12 2 +ViewUsage nestedEnumeration 4789f8737172dea1 12 0 +ViewUsage nestedFlow 4789f8737172dea1 12 0 +ViewUsage nestedInterface 4789f8737172dea1 12 0 +ViewUsage nestedItem 242328a27e778d08 12 9 +ViewUsage nestedMetadata 4789f8737172dea1 12 0 +ViewUsage nestedOccurrence 15475ca54b215094 12 10 +ViewUsage nestedPart 242328a27e778d08 12 9 +ViewUsage nestedPort 4789f8737172dea1 12 0 +ViewUsage nestedReference 4789f8737172dea1 12 0 +ViewUsage nestedRendering a86e6f32b2fa7cc6 12 8 +ViewUsage nestedRequirement aba7619845339ef3 12 2 +ViewUsage nestedState 4789f8737172dea1 12 0 +ViewUsage nestedTransition 4789f8737172dea1 12 0 +ViewUsage nestedUsage 15475ca54b215094 12 10 +ViewUsage nestedUseCase 4789f8737172dea1 12 0 +ViewUsage nestedVerificationCase 4789f8737172dea1 12 0 +ViewUsage nestedView c33eb1e33cefeee3 12 1 +ViewUsage nestedViewpoint 4789f8737172dea1 12 0 +ViewUsage occurrenceDefinition 677fee971a7c577c 12 7 +ViewUsage output 4789f8737172dea1 12 0 +ViewUsage ownedAnnotation 4789f8737172dea1 12 0 +ViewUsage ownedConjugator c23e8ae6760020e3 12 0 +ViewUsage ownedCrossSubsetting c23e8ae6760020e3 12 0 +ViewUsage ownedDifferencing 4789f8737172dea1 12 0 +ViewUsage ownedDisjoining 4789f8737172dea1 12 0 +ViewUsage ownedElement 8ffce707af33540a 12 11 +ViewUsage ownedEndFeature 4789f8737172dea1 12 0 +ViewUsage ownedFeature 15475ca54b215094 12 10 +ViewUsage ownedFeatureChaining 4789f8737172dea1 12 0 +ViewUsage ownedFeatureInverting 4789f8737172dea1 12 0 +ViewUsage ownedFeatureMembership 6702e120b0532c5e 12 10 +ViewUsage ownedImport b1a908093ed5b3a9 12 9 +ViewUsage ownedIntersecting 4789f8737172dea1 12 0 +ViewUsage ownedMember 407a255d1698670b 12 11 +ViewUsage ownedMembership 7361b9c21295bca0 12 11 +ViewUsage ownedRedefinition 9370e5156198ff00 12 2 +ViewUsage ownedReferenceSubsetting c23e8ae6760020e3 12 0 +ViewUsage ownedRelationship b6dcd336406be7d7 12 12 +ViewUsage ownedSpecialization 9ec29dab40ac168c 12 12 +ViewUsage ownedSubsetting e0838fccb4bfe51e 12 12 +ViewUsage ownedTypeFeaturing 4789f8737172dea1 12 0 +ViewUsage ownedTyping ad108efc322a39af 12 6 +ViewUsage ownedUnioning 4789f8737172dea1 12 0 +ViewUsage owner e4e35156d64aa18a 12 12 +ViewUsage owningDefinition b3f8d82dcc92e46e 12 1 +ViewUsage owningFeatureMembership 0604af312e2ff1f4 12 5 +ViewUsage owningMembership 7f544c1c7431efa5 12 12 +ViewUsage owningNamespace e4e35156d64aa18a 12 12 +ViewUsage owningRelationship 7f544c1c7431efa5 12 12 +ViewUsage owningType a7511e1632960920 12 5 +ViewUsage owningUsage b596d0cedc034595 12 4 +ViewUsage partDefinition 677fee971a7c577c 12 7 +ViewUsage portionKind c23e8ae6760020e3 12 0 +ViewUsage qualifiedName 8d3cb9f8e5acfd08 12 12 +ViewUsage satisfiedViewpoint 4789f8737172dea1 12 0 +ViewUsage shortName c23e8ae6760020e3 12 0 +ViewUsage textualRepresentation 4789f8737172dea1 12 0 +ViewUsage type 677fee971a7c577c 12 7 +ViewUsage unioningType 4789f8737172dea1 12 0 +ViewUsage usage 15475ca54b215094 12 10 +ViewUsage variant 4789f8737172dea1 12 0 +ViewUsage variantMembership 4789f8737172dea1 12 0 +ViewUsage viewCondition f90562ed29b9c7d6 12 2 +ViewUsage viewDefinition 7c5d70de9b656bdd 12 7 +ViewUsage viewRendering 1dc2f2f16cbf7dac 12 8 +ViewpointDefinition actorParameter e7140edd4730e611 3 0 +ViewpointDefinition aliasIds e7140edd4730e611 3 0 +ViewpointDefinition assumedConstraint e7140edd4730e611 3 0 +ViewpointDefinition declaredName 683bc6c38da63305 3 3 +ViewpointDefinition declaredShortName 03658292af8df35a 3 0 +ViewpointDefinition differencingType e7140edd4730e611 3 0 +ViewpointDefinition directedFeature e7140edd4730e611 3 0 +ViewpointDefinition directedUsage e7140edd4730e611 3 0 +ViewpointDefinition documentation e7140edd4730e611 3 0 +ViewpointDefinition elementId 4568b7d7233e7608 3 3 +ViewpointDefinition endFeature e7140edd4730e611 3 0 +ViewpointDefinition expression 3383629e067da7b8 3 2 +ViewpointDefinition feature 3383629e067da7b8 3 2 +ViewpointDefinition featureMembership 3291b3faa4deeb72 3 2 +ViewpointDefinition framedConcern 3383629e067da7b8 3 2 +ViewpointDefinition importedMembership e7140edd4730e611 3 0 +ViewpointDefinition inheritedFeature e7140edd4730e611 3 0 +ViewpointDefinition inheritedMembership e7140edd4730e611 3 0 +ViewpointDefinition input e7140edd4730e611 3 0 +ViewpointDefinition intersectingType e7140edd4730e611 3 0 +ViewpointDefinition isAbstract 97e223e37ced5052 3 0 +ViewpointDefinition isConjugated 97e223e37ced5052 3 0 +ViewpointDefinition isImpliedIncluded e690276988f49a41 3 3 +ViewpointDefinition isIndividual 03658292af8df35a 3 0 +ViewpointDefinition isLibraryElement 97e223e37ced5052 3 0 +ViewpointDefinition isModelLevelEvaluable 97e223e37ced5052 3 0 +ViewpointDefinition isSufficient 97e223e37ced5052 3 0 +ViewpointDefinition isVariation 97e223e37ced5052 3 0 +ViewpointDefinition member 3383629e067da7b8 3 2 +ViewpointDefinition membership 3291b3faa4deeb72 3 2 +ViewpointDefinition multiplicity 03658292af8df35a 3 0 +ViewpointDefinition name 683bc6c38da63305 3 3 +ViewpointDefinition output e7140edd4730e611 3 0 +ViewpointDefinition ownedAction e7140edd4730e611 3 0 +ViewpointDefinition ownedAllocation e7140edd4730e611 3 0 +ViewpointDefinition ownedAnalysisCase e7140edd4730e611 3 0 +ViewpointDefinition ownedAnnotation e7140edd4730e611 3 0 +ViewpointDefinition ownedAttribute e7140edd4730e611 3 0 +ViewpointDefinition ownedCalculation e7140edd4730e611 3 0 +ViewpointDefinition ownedCase e7140edd4730e611 3 0 +ViewpointDefinition ownedConcern 3383629e067da7b8 3 2 +ViewpointDefinition ownedConjugator 03658292af8df35a 3 0 +ViewpointDefinition ownedConnection e7140edd4730e611 3 0 +ViewpointDefinition ownedConstraint 3383629e067da7b8 3 2 +ViewpointDefinition ownedDifferencing e7140edd4730e611 3 0 +ViewpointDefinition ownedDisjoining e7140edd4730e611 3 0 +ViewpointDefinition ownedElement 3383629e067da7b8 3 2 +ViewpointDefinition ownedEndFeature e7140edd4730e611 3 0 +ViewpointDefinition ownedEnumeration e7140edd4730e611 3 0 +ViewpointDefinition ownedFeature 3383629e067da7b8 3 2 +ViewpointDefinition ownedFeatureMembership 3291b3faa4deeb72 3 2 +ViewpointDefinition ownedFlow e7140edd4730e611 3 0 +ViewpointDefinition ownedImport e7140edd4730e611 3 0 +ViewpointDefinition ownedInterface e7140edd4730e611 3 0 +ViewpointDefinition ownedIntersecting e7140edd4730e611 3 0 +ViewpointDefinition ownedItem e7140edd4730e611 3 0 +ViewpointDefinition ownedMember 3383629e067da7b8 3 2 +ViewpointDefinition ownedMembership 3291b3faa4deeb72 3 2 +ViewpointDefinition ownedMetadata e7140edd4730e611 3 0 +ViewpointDefinition ownedOccurrence 3383629e067da7b8 3 2 +ViewpointDefinition ownedPart e7140edd4730e611 3 0 +ViewpointDefinition ownedPort e7140edd4730e611 3 0 +ViewpointDefinition ownedReference e7140edd4730e611 3 0 +ViewpointDefinition ownedRelationship 9f37ec2cce29b6aa 3 3 +ViewpointDefinition ownedRendering e7140edd4730e611 3 0 +ViewpointDefinition ownedRequirement 3383629e067da7b8 3 2 +ViewpointDefinition ownedSpecialization 10e8fcdb4d4f573d 3 3 +ViewpointDefinition ownedState e7140edd4730e611 3 0 +ViewpointDefinition ownedSubclassification 10e8fcdb4d4f573d 3 3 +ViewpointDefinition ownedTransition e7140edd4730e611 3 0 +ViewpointDefinition ownedUnioning e7140edd4730e611 3 0 +ViewpointDefinition ownedUsage 3383629e067da7b8 3 2 +ViewpointDefinition ownedUseCase e7140edd4730e611 3 0 +ViewpointDefinition ownedVerificationCase e7140edd4730e611 3 0 +ViewpointDefinition ownedView e7140edd4730e611 3 0 +ViewpointDefinition ownedViewpoint e7140edd4730e611 3 0 +ViewpointDefinition owner 74de923777d39528 3 3 +ViewpointDefinition owningMembership 1f9216ce336f9e0e 3 3 +ViewpointDefinition owningNamespace 74de923777d39528 3 3 +ViewpointDefinition owningRelationship 1f9216ce336f9e0e 3 3 +ViewpointDefinition parameter e7140edd4730e611 3 0 +ViewpointDefinition qualifiedName 4c6741f151fd3a88 3 3 +ViewpointDefinition reqId 03658292af8df35a 3 0 +ViewpointDefinition requiredConstraint 3383629e067da7b8 3 2 +ViewpointDefinition result 7ed41bd52112e16d 3 0 +ViewpointDefinition shortName 03658292af8df35a 3 0 +ViewpointDefinition stakeholderParameter e7140edd4730e611 3 0 +ViewpointDefinition step 3383629e067da7b8 3 2 +ViewpointDefinition subjectParameter 7ed41bd52112e16d 3 0 +ViewpointDefinition text e7140edd4730e611 3 0 +ViewpointDefinition textualRepresentation e7140edd4730e611 3 0 +ViewpointDefinition unioningType e7140edd4730e611 3 0 +ViewpointDefinition usage 3383629e067da7b8 3 2 +ViewpointDefinition variant e7140edd4730e611 3 0 +ViewpointDefinition variantMembership e7140edd4730e611 3 0 +ViewpointDefinition viewpointStakeholder e7140edd4730e611 3 0 +ViewpointUsage actorParameter 255edb3661d089f1 3 0 +ViewpointUsage aliasIds 255edb3661d089f1 3 0 +ViewpointUsage assumedConstraint 255edb3661d089f1 3 0 +ViewpointUsage behavior 2919ff4bc1dccae4 3 1 +ViewpointUsage chainingFeature 255edb3661d089f1 3 0 +ViewpointUsage constraintDefinition 1c87eec8d0eaae0a 3 1 +ViewpointUsage crossFeature 581ee364b0a1115a 3 0 +ViewpointUsage declaredName d0c42d1252cb0967 3 3 +ViewpointUsage declaredShortName 581ee364b0a1115a 3 0 +ViewpointUsage definition 2919ff4bc1dccae4 3 1 +ViewpointUsage differencingType 255edb3661d089f1 3 0 +ViewpointUsage directedFeature 255edb3661d089f1 3 0 +ViewpointUsage directedUsage 255edb3661d089f1 3 0 +ViewpointUsage direction 581ee364b0a1115a 3 0 +ViewpointUsage documentation 255edb3661d089f1 3 0 +ViewpointUsage elementId 6ad1ee357b677a98 3 3 +ViewpointUsage endFeature 255edb3661d089f1 3 0 +ViewpointUsage endOwningType 581ee364b0a1115a 3 0 +ViewpointUsage feature ceaba62886d56995 3 3 +ViewpointUsage featureMembership 2db63f4c9c54e15d 3 3 +ViewpointUsage featureTarget 44e5393cd9875bc5 3 0 +ViewpointUsage featuringType 255edb3661d089f1 3 0 +ViewpointUsage framedConcern 69d31b192b5e71d5 3 3 +ViewpointUsage function 1c87eec8d0eaae0a 3 1 +ViewpointUsage importedMembership 255edb3661d089f1 3 0 +ViewpointUsage individualDefinition 581ee364b0a1115a 3 0 +ViewpointUsage inheritedFeature 255edb3661d089f1 3 0 +ViewpointUsage inheritedMembership 255edb3661d089f1 3 0 +ViewpointUsage input 255edb3661d089f1 3 0 +ViewpointUsage intersectingType 255edb3661d089f1 3 0 +ViewpointUsage isAbstract ba5a91332de4822a 3 0 +ViewpointUsage isComposite 757ef380f585818f 3 1 +ViewpointUsage isConjugated ba5a91332de4822a 3 0 +ViewpointUsage isConstant ba5a91332de4822a 3 0 +ViewpointUsage isDerived ba5a91332de4822a 3 0 +ViewpointUsage isEnd ba5a91332de4822a 3 0 +ViewpointUsage isImpliedIncluded 8188466a89f7f4c9 3 3 +ViewpointUsage isIndividual 581ee364b0a1115a 3 0 +ViewpointUsage isLibraryElement ba5a91332de4822a 3 0 +ViewpointUsage isModelLevelEvaluable ba5a91332de4822a 3 0 +ViewpointUsage isOrdered ba5a91332de4822a 3 0 +ViewpointUsage isPortion 581ee364b0a1115a 3 0 +ViewpointUsage isReference c663e41cc256f564 3 2 +ViewpointUsage isSufficient 581ee364b0a1115a 3 0 +ViewpointUsage isUnique 8188466a89f7f4c9 3 3 +ViewpointUsage isVariable 581ee364b0a1115a 3 0 +ViewpointUsage isVariation ba5a91332de4822a 3 0 +ViewpointUsage mayTimeVary 581ee364b0a1115a 3 0 +ViewpointUsage member ceaba62886d56995 3 3 +ViewpointUsage membership 2db63f4c9c54e15d 3 3 +ViewpointUsage multiplicity 581ee364b0a1115a 3 0 +ViewpointUsage name d0c42d1252cb0967 3 3 +ViewpointUsage nestedAction 255edb3661d089f1 3 0 +ViewpointUsage nestedAllocation 255edb3661d089f1 3 0 +ViewpointUsage nestedAnalysisCase 255edb3661d089f1 3 0 +ViewpointUsage nestedAttribute 255edb3661d089f1 3 0 +ViewpointUsage nestedCalculation 255edb3661d089f1 3 0 +ViewpointUsage nestedCase 255edb3661d089f1 3 0 +ViewpointUsage nestedConcern fc29e90fffbaa8e0 3 3 +ViewpointUsage nestedConnection 255edb3661d089f1 3 0 +ViewpointUsage nestedConstraint ceaba62886d56995 3 3 +ViewpointUsage nestedEnumeration 255edb3661d089f1 3 0 +ViewpointUsage nestedFlow 255edb3661d089f1 3 0 +ViewpointUsage nestedInterface 255edb3661d089f1 3 0 +ViewpointUsage nestedItem 255edb3661d089f1 3 0 +ViewpointUsage nestedMetadata 255edb3661d089f1 3 0 +ViewpointUsage nestedOccurrence ceaba62886d56995 3 3 +ViewpointUsage nestedPart 255edb3661d089f1 3 0 +ViewpointUsage nestedPort 255edb3661d089f1 3 0 +ViewpointUsage nestedReference 255edb3661d089f1 3 0 +ViewpointUsage nestedRendering 255edb3661d089f1 3 0 +ViewpointUsage nestedRequirement fc29e90fffbaa8e0 3 3 +ViewpointUsage nestedState 255edb3661d089f1 3 0 +ViewpointUsage nestedTransition 255edb3661d089f1 3 0 +ViewpointUsage nestedUsage ceaba62886d56995 3 3 +ViewpointUsage nestedUseCase 255edb3661d089f1 3 0 +ViewpointUsage nestedVerificationCase 255edb3661d089f1 3 0 +ViewpointUsage nestedView 255edb3661d089f1 3 0 +ViewpointUsage nestedViewpoint 255edb3661d089f1 3 0 +ViewpointUsage occurrenceDefinition 2919ff4bc1dccae4 3 1 +ViewpointUsage output 255edb3661d089f1 3 0 +ViewpointUsage ownedAnnotation 255edb3661d089f1 3 0 +ViewpointUsage ownedConjugator 581ee364b0a1115a 3 0 +ViewpointUsage ownedCrossSubsetting 581ee364b0a1115a 3 0 +ViewpointUsage ownedDifferencing 255edb3661d089f1 3 0 +ViewpointUsage ownedDisjoining 255edb3661d089f1 3 0 +ViewpointUsage ownedElement ceaba62886d56995 3 3 +ViewpointUsage ownedEndFeature 255edb3661d089f1 3 0 +ViewpointUsage ownedFeature ceaba62886d56995 3 3 +ViewpointUsage ownedFeatureChaining 255edb3661d089f1 3 0 +ViewpointUsage ownedFeatureInverting 255edb3661d089f1 3 0 +ViewpointUsage ownedFeatureMembership 2db63f4c9c54e15d 3 3 +ViewpointUsage ownedImport 255edb3661d089f1 3 0 +ViewpointUsage ownedIntersecting 255edb3661d089f1 3 0 +ViewpointUsage ownedMember ceaba62886d56995 3 3 +ViewpointUsage ownedMembership 2db63f4c9c54e15d 3 3 +ViewpointUsage ownedRedefinition 255edb3661d089f1 3 0 +ViewpointUsage ownedReferenceSubsetting 581ee364b0a1115a 3 0 +ViewpointUsage ownedRelationship 38998e8cc1946910 3 3 +ViewpointUsage ownedSpecialization d1d30699af5eacd8 3 1 +ViewpointUsage ownedSubsetting 255edb3661d089f1 3 0 +ViewpointUsage ownedTypeFeaturing 255edb3661d089f1 3 0 +ViewpointUsage ownedTyping d1d30699af5eacd8 3 1 +ViewpointUsage ownedUnioning 255edb3661d089f1 3 0 +ViewpointUsage owner d9e41e6de290ec8d 3 3 +ViewpointUsage owningDefinition e19bc833cf56b0d9 3 1 +ViewpointUsage owningFeatureMembership b19f539b0ea23328 3 1 +ViewpointUsage owningMembership 35295b46f1a1f09a 3 3 +ViewpointUsage owningNamespace d9e41e6de290ec8d 3 3 +ViewpointUsage owningRelationship 35295b46f1a1f09a 3 3 +ViewpointUsage owningType e19bc833cf56b0d9 3 1 +ViewpointUsage owningUsage 581ee364b0a1115a 3 0 +ViewpointUsage parameter 255edb3661d089f1 3 0 +ViewpointUsage portionKind 581ee364b0a1115a 3 0 +ViewpointUsage predicate 1c87eec8d0eaae0a 3 1 +ViewpointUsage qualifiedName 5a0cdc0d48690f34 3 3 +ViewpointUsage reqId 581ee364b0a1115a 3 0 +ViewpointUsage requiredConstraint 3c54d831b279328a 3 3 +ViewpointUsage requirementDefinition 1c87eec8d0eaae0a 3 1 +ViewpointUsage result 44e5393cd9875bc5 3 0 +ViewpointUsage shortName 581ee364b0a1115a 3 0 +ViewpointUsage stakeholderParameter 255edb3661d089f1 3 0 +ViewpointUsage subjectParameter 44e5393cd9875bc5 3 0 +ViewpointUsage text 255edb3661d089f1 3 0 +ViewpointUsage textualRepresentation 255edb3661d089f1 3 0 +ViewpointUsage type 2919ff4bc1dccae4 3 1 +ViewpointUsage unioningType 255edb3661d089f1 3 0 +ViewpointUsage usage ceaba62886d56995 3 3 +ViewpointUsage variant 255edb3661d089f1 3 0 +ViewpointUsage variantMembership 255edb3661d089f1 3 0 +ViewpointUsage viewpointDefinition 1c87eec8d0eaae0a 3 1 +ViewpointUsage viewpointStakeholder 255edb3661d089f1 3 0 +WhileLoopActionUsage actionDefinition af37b64d85605618 5 0 +WhileLoopActionUsage aliasIds af37b64d85605618 5 0 +WhileLoopActionUsage behavior af37b64d85605618 5 0 +WhileLoopActionUsage bodyAction 677a9bb769290e1f 5 2 +WhileLoopActionUsage chainingFeature af37b64d85605618 5 0 +WhileLoopActionUsage crossFeature 806f5382440121f5 5 0 +WhileLoopActionUsage declaredName edcce59baa568b71 5 1 +WhileLoopActionUsage declaredShortName 806f5382440121f5 5 0 +WhileLoopActionUsage definition af37b64d85605618 5 0 +WhileLoopActionUsage differencingType af37b64d85605618 5 0 +WhileLoopActionUsage directedFeature ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage directedUsage ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage direction 806f5382440121f5 5 0 +WhileLoopActionUsage documentation af37b64d85605618 5 0 +WhileLoopActionUsage elementId 79249e752e94d388 5 5 +WhileLoopActionUsage endFeature af37b64d85605618 5 0 +WhileLoopActionUsage endOwningType 806f5382440121f5 5 0 +WhileLoopActionUsage feature ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage featureMembership c050ed9fc295f679 5 5 +WhileLoopActionUsage featureTarget 9efe996a25e42931 5 0 +WhileLoopActionUsage featuringType af37b64d85605618 5 0 +WhileLoopActionUsage importedMembership af37b64d85605618 5 0 +WhileLoopActionUsage individualDefinition 806f5382440121f5 5 0 +WhileLoopActionUsage inheritedFeature af37b64d85605618 5 0 +WhileLoopActionUsage inheritedMembership af37b64d85605618 5 0 +WhileLoopActionUsage input ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage intersectingType af37b64d85605618 5 0 +WhileLoopActionUsage isAbstract 800365b9f081c72b 5 0 +WhileLoopActionUsage isComposite bbe0803b15cfe2bc 5 5 +WhileLoopActionUsage isConjugated 800365b9f081c72b 5 0 +WhileLoopActionUsage isConstant 800365b9f081c72b 5 0 +WhileLoopActionUsage isDerived 800365b9f081c72b 5 0 +WhileLoopActionUsage isEnd 800365b9f081c72b 5 0 +WhileLoopActionUsage isImpliedIncluded bbe0803b15cfe2bc 5 5 +WhileLoopActionUsage isIndividual 806f5382440121f5 5 0 +WhileLoopActionUsage isLibraryElement 800365b9f081c72b 5 0 +WhileLoopActionUsage isOrdered 800365b9f081c72b 5 0 +WhileLoopActionUsage isPortion 806f5382440121f5 5 0 +WhileLoopActionUsage isReference 800365b9f081c72b 5 0 +WhileLoopActionUsage isSufficient 806f5382440121f5 5 0 +WhileLoopActionUsage isUnique bbe0803b15cfe2bc 5 5 +WhileLoopActionUsage isVariable 806f5382440121f5 5 0 +WhileLoopActionUsage isVariation 800365b9f081c72b 5 0 +WhileLoopActionUsage mayTimeVary 806f5382440121f5 5 0 +WhileLoopActionUsage member ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage membership c050ed9fc295f679 5 5 +WhileLoopActionUsage multiplicity 806f5382440121f5 5 0 +WhileLoopActionUsage name edcce59baa568b71 5 1 +WhileLoopActionUsage nestedAction c205b7ebdb4471a0 5 5 +WhileLoopActionUsage nestedAllocation af37b64d85605618 5 0 +WhileLoopActionUsage nestedAnalysisCase af37b64d85605618 5 0 +WhileLoopActionUsage nestedAttribute af37b64d85605618 5 0 +WhileLoopActionUsage nestedCalculation af37b64d85605618 5 0 +WhileLoopActionUsage nestedCase af37b64d85605618 5 0 +WhileLoopActionUsage nestedConcern af37b64d85605618 5 0 +WhileLoopActionUsage nestedConnection af37b64d85605618 5 0 +WhileLoopActionUsage nestedConstraint af37b64d85605618 5 0 +WhileLoopActionUsage nestedEnumeration af37b64d85605618 5 0 +WhileLoopActionUsage nestedFlow af37b64d85605618 5 0 +WhileLoopActionUsage nestedInterface 50aef5c1d55c7795 5 4 +WhileLoopActionUsage nestedItem af37b64d85605618 5 0 +WhileLoopActionUsage nestedMetadata af37b64d85605618 5 0 +WhileLoopActionUsage nestedOccurrence c205b7ebdb4471a0 5 5 +WhileLoopActionUsage nestedPart af37b64d85605618 5 0 +WhileLoopActionUsage nestedPort af37b64d85605618 5 0 +WhileLoopActionUsage nestedReference 50aef5c1d55c7795 5 4 +WhileLoopActionUsage nestedRendering af37b64d85605618 5 0 +WhileLoopActionUsage nestedRequirement af37b64d85605618 5 0 +WhileLoopActionUsage nestedState af37b64d85605618 5 0 +WhileLoopActionUsage nestedTransition af37b64d85605618 5 0 +WhileLoopActionUsage nestedUsage ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage nestedUseCase af37b64d85605618 5 0 +WhileLoopActionUsage nestedVerificationCase af37b64d85605618 5 0 +WhileLoopActionUsage nestedView af37b64d85605618 5 0 +WhileLoopActionUsage nestedViewpoint af37b64d85605618 5 0 +WhileLoopActionUsage occurrenceDefinition af37b64d85605618 5 0 +WhileLoopActionUsage output af37b64d85605618 5 0 +WhileLoopActionUsage ownedAnnotation af37b64d85605618 5 0 +WhileLoopActionUsage ownedConjugator 806f5382440121f5 5 0 +WhileLoopActionUsage ownedCrossSubsetting 806f5382440121f5 5 0 +WhileLoopActionUsage ownedDifferencing af37b64d85605618 5 0 +WhileLoopActionUsage ownedDisjoining af37b64d85605618 5 0 +WhileLoopActionUsage ownedElement ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage ownedEndFeature af37b64d85605618 5 0 +WhileLoopActionUsage ownedFeature ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage ownedFeatureChaining af37b64d85605618 5 0 +WhileLoopActionUsage ownedFeatureInverting af37b64d85605618 5 0 +WhileLoopActionUsage ownedFeatureMembership c050ed9fc295f679 5 5 +WhileLoopActionUsage ownedImport af37b64d85605618 5 0 +WhileLoopActionUsage ownedIntersecting af37b64d85605618 5 0 +WhileLoopActionUsage ownedMember ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage ownedMembership c050ed9fc295f679 5 5 +WhileLoopActionUsage ownedRedefinition af37b64d85605618 5 0 +WhileLoopActionUsage ownedReferenceSubsetting 806f5382440121f5 5 0 +WhileLoopActionUsage ownedRelationship c050ed9fc295f679 5 5 +WhileLoopActionUsage ownedSpecialization af37b64d85605618 5 0 +WhileLoopActionUsage ownedSubsetting af37b64d85605618 5 0 +WhileLoopActionUsage ownedTypeFeaturing af37b64d85605618 5 0 +WhileLoopActionUsage ownedTyping af37b64d85605618 5 0 +WhileLoopActionUsage ownedUnioning af37b64d85605618 5 0 +WhileLoopActionUsage owner 75883ac123b4dbd5 5 5 +WhileLoopActionUsage owningDefinition 5a310cf5d8011b6a 5 1 +WhileLoopActionUsage owningFeatureMembership 8603c24a581c5f75 5 5 +WhileLoopActionUsage owningMembership 8603c24a581c5f75 5 5 +WhileLoopActionUsage owningNamespace 75883ac123b4dbd5 5 5 +WhileLoopActionUsage owningRelationship 8603c24a581c5f75 5 5 +WhileLoopActionUsage owningType 75883ac123b4dbd5 5 5 +WhileLoopActionUsage owningUsage 9bc6814d8fb4e260 5 4 +WhileLoopActionUsage parameter ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage portionKind 806f5382440121f5 5 0 +WhileLoopActionUsage qualifiedName 806f5382440121f5 5 0 +WhileLoopActionUsage shortName 806f5382440121f5 5 0 +WhileLoopActionUsage textualRepresentation af37b64d85605618 5 0 +WhileLoopActionUsage type af37b64d85605618 5 0 +WhileLoopActionUsage unioningType af37b64d85605618 5 0 +WhileLoopActionUsage untilArgument 298ae64391f832fe 5 1 +WhileLoopActionUsage usage ad9edd2c31fb89fb 5 5 +WhileLoopActionUsage variant af37b64d85605618 5 0 +WhileLoopActionUsage variantMembership af37b64d85605618 5 0 +WhileLoopActionUsage whileArgument 11d86e8123312527 5 2 diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/LICENSE b/crates/sysmlv2-parser/tests/fixtures/opensysml/LICENSE new file mode 100644 index 0000000..7739fc1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/LICENSE @@ -0,0 +1,202 @@ + + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2026 Open-MBEE + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/README.md b/crates/sysmlv2-parser/tests/fixtures/opensysml/README.md new file mode 100644 index 0000000..581510e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/README.md @@ -0,0 +1,38 @@ +# OpenSysML negative fixtures + +Unmodified source fixtures from Open-MBEE/OpenSysML, pinned by `provenance.json`. +The Apache-2.0 license is retained in `LICENSE`; each source keeps its upstream +comments and references. `probes` ties examples to named validator rules; +`negative` contains the pilot-rejection corpus. Upstream's recorded pilot +adjudications are useful evidence, not an independently rerun oracle here. + +The tests run each file independently through four stages — parsing, +body-context validation, referential checks, and semantic checks — with every +recorded row labelled by stage. `baseline.json` is the run without a standard +library: referential rows there are missing dependencies, so a file whose only +rows are referential stays **unknown without library**, and an empty list is +unknown too, not a successful rejection, except for explicitly adjudicated +accepted models. `baseline-library.json` is the run against the standard +library, where a referential row counts like any other. In neither file does a +nonempty list by itself prove that the diagnostic implements the fixture's +intended rule; the contract manifests and the paired checker tests do that. + +Regenerate only after adjudicating every changed result: + +```sh +UPDATE_OPENSYSML_BASELINE=1 cargo test -p sysmlv2-parser --test opensysml +``` + +The `opensysmlcheck` example prints the full-library run as JSON. It shares +the stage runner (`tests/support/census.rs`) and the contract check with the +tests, so its "unknown" means the same thing as the baseline's. The tests check +the fixture census; remove or modify no case to make a gate pass. +Implementation gaps are deliberately visible in the checked-in baselines. + +`static-contracts.json` and `negative-contracts.json` register 147 intended +rejections and one adjudicated acceptance. The latter preserves the official +GradePoints enum/Real literal-value idiom despite an upstream pilot-negative +expectation. Paired tests check clean legal neighbors, exact diagnostic category +and meaningful source locations. The full-library baseline test and the +reporting example both fail if any registered contract regresses; neither +equates an unrelated diagnostic with success. diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline-library.json b/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline-library.json new file mode 100644 index 0000000..bee303a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline-library.json @@ -0,0 +1,5844 @@ +{ + "negative/extensions/x01-initial-state-marker.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected `;` or `{`, found `start`", + "severity": "Error", + "stage": "parse", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x02-choice-pseudostate.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "expected `;` or `{`, found `evaluate`", + "severity": "Error", + "stage": "parse", + "start": 206 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x03-junction-pseudostate.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "expected `;` or `{`, found `route`", + "severity": "Error", + "stage": "parse", + "start": 217 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x04-orthogonal-region.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "expected `;` or `{`, found `r1`", + "severity": "Error", + "stage": "parse", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x05-defer-member.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "expected `;` or `{`, found `Ping`", + "severity": "Error", + "stage": "parse", + "start": 205 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x06-history-member.sysml": { + "diagnostics": [ + { + "end": 217, + "message": "expected `;` or `{`, found `resume`", + "severity": "Error", + "stage": "parse", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x07-transition-to.sysml": { + "diagnostics": [ + { + "end": 212, + "message": "expected `then`, found `to`", + "severity": "Error", + "stage": "parse", + "start": 210 + }, + { + "end": 212, + "message": "expected a name, found `to`", + "severity": "Error", + "stage": "parse", + "start": 210 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x08-require-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 356, + "message": "a `require` constraint member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 329 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g01-unclosed-package-body.sysml": { + "diagnostics": [ + { + "end": 123, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 123 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g02-import-without-visibility.sysml": { + "diagnostics": [ + { + "end": 204, + "message": "an import must declare an explicit visibility (`public`, `private`, or `protected`)", + "severity": "Error", + "stage": "structure", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g03-alias-without-for.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected `for`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + }, + { + "end": 144, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g04-specialization-without-target.sysml": { + "diagnostics": [ + { + "end": 171, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g05-typing-without-type.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g06-definition-with-multiplicity.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "expected `;` or `{`, found `[`", + "severity": "Error", + "stage": "parse", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g07-entry-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 231, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 223 + }, + { + "end": 230, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g08-do-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 219, + "message": "a `do` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 214 + }, + { + "end": 218, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 217 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g09-value-without-expression.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g10-operator-without-operand.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g11-assignment-without-target.sysml": { + "diagnostics": [ + { + "end": 178, + "message": "expected `:=` in assignment, found `}`", + "severity": "Error", + "stage": "parse", + "start": 177 + }, + { + "end": 178, + "message": "expected an expression, found `}`", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g12-unterminated-block-comment.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "unterminated comment (missing `*/`)", + "severity": "Error", + "stage": "parse", + "start": 140 + }, + { + "end": 158, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g13-entry-then-without-target.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "expected a name, found `then`", + "severity": "Error", + "stage": "parse", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g14-connect-without-to.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "expected `to`, found `b`", + "severity": "Error", + "stage": "parse", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g15-keyword-as-name.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected `;` or `{`, found `part`", + "severity": "Error", + "stage": "parse", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g16-expose-without-name.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g17-render-without-usage.sysml": { + "diagnostics": [ + { + "end": 189, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g18-require-without-constraint.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g19-frame-without-concern.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g20-include-without-target.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g21-filter-without-expression.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "missing `;` after filter expression", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g22-dependency-without-to.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "expected `to`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 181 + }, + { + "end": 182, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g23-rep-without-language.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "expected `language`, found `/* self.x > 0 */`", + "severity": "Error", + "stage": "parse", + "start": 172 + }, + { + "end": 188, + "message": "expected a language string, found `/* self.x > 0 */`", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g24-alias-without-target.sysml": { + "diagnostics": [ + { + "end": 160, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 159 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g25-library-without-package.sysml": { + "diagnostics": [ + { + "end": 127, + "message": "expected `package`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g26-multiplicity-open-range.sysml": { + "diagnostics": [ + { + "end": 175, + "message": "expected a multiplicity bound (literal or feature name), found `]`", + "severity": "Error", + "stage": "parse", + "start": 174 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g27-bind-without-right-end.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g28-succession-without-target.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g29-flow-without-target.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g30-message-without-target.sysml": { + "diagnostics": [ + { + "end": 230, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g31-allocate-without-to.sysml": { + "diagnostics": [ + { + "end": 248, + "message": "expected `to`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 247 + }, + { + "end": 248, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g32-if-without-condition.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g33-while-without-condition.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g34-for-without-in.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "expected `in`, found `{`", + "severity": "Error", + "stage": "parse", + "start": 157 + }, + { + "end": 166, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 165 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g35-accept-without-payload.sysml": { + "diagnostics": [ + { + "end": 194, + "message": "a payload requires a type, specialization, or value", + "severity": "Error", + "stage": "parse", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g36-direction-without-feature.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "expected a definition or usage after prefix, found `;`", + "severity": "Error", + "stage": "parse", + "start": 176 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g37-redefines-without-target.sysml": { + "diagnostics": [ + { + "end": 249, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 248 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g38-references-without-target.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g39-redefinition-symbol-without-target.sysml": { + "diagnostics": [ + { + "end": 230, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g40-modulo-without-operand.sysml": { + "diagnostics": [ + { + "end": 173, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 173 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g41-exponent-without-operand.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g42-implies-without-operand.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g43-null-coalescing-without-operand.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g44-conditional-without-else.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "expected `else`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 176 + }, + { + "end": 177, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g45-classification-test-without-type.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g46-cast-without-type.sysml": { + "diagnostics": [ + { + "end": 140, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 139 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g47-prefix-metadata-without-name.sysml": { + "diagnostics": [ + { + "end": 166, + "message": "expected a name, found `part`", + "severity": "Error", + "stage": "parse", + "start": 162 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g48-decision-without-body.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g49-assign-without-value.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g50-conjugated-port-typing-without-name.sysml": { + "diagnostics": [ + { + "end": 208, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g51-real-without-fraction.sysml": { + "diagnostics": [ + { + "end": 168, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g52-unterminated-string.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "unterminated string literal", + "severity": "Error", + "stage": "parse", + "start": 138 + }, + { + "end": 146, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g53-range-without-upper-bound.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g54-argument-list-trailing-comma.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "expected an expression, found `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + }, + { + "end": 220, + "message": "expected `;` or `{`, found `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + }, + { + "end": 220, + "message": "unsupported or unexpected construct at `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g55-feature-chain-trailing-dot.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g56-qualified-name-trailing-separator.sysml": { + "diagnostics": [ + { + "end": 174, + "message": "expected `;` or `{`, found `::`", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g57-unterminated-unrestricted-name.sysml": { + "diagnostics": [ + { + "end": 163, + "message": "unterminated unrestricted name", + "severity": "Error", + "stage": "parse", + "start": 157 + }, + { + "end": 163, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 163 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g58-satisfy-without-reference.sysml": { + "diagnostics": [ + { + "end": 227, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 226 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g59-crosses-without-target.sysml": { + "diagnostics": [ + { + "end": 203, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g60-alias-keyword-as-name.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "expected `for`, found `part`", + "severity": "Error", + "stage": "parse", + "start": 198 + }, + { + "end": 202, + "message": "expected a name, found `part`", + "severity": "Error", + "stage": "parse", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g61-actor-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 313, + "message": "an `actor` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 289 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g62-subject-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 320, + "message": "validateSubjectMembershipOwningType: a `subject` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g63-objective-outside-case-body.sysml": { + "diagnostics": [ + { + "end": 299, + "message": "validateObjectiveMembershipOwningType: an `objective` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 280 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g64-stakeholder-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 333, + "message": "a `stakeholder` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 306 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g65-entry-action-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 268, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g66-render-outside-view-body.sysml": { + "diagnostics": [ + { + "end": 312, + "message": "a `render` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g67-expose-outside-view-body.sysml": { + "diagnostics": [ + { + "end": 259, + "message": "an `expose` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 244 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g68-definition-in-enumeration-body.sysml": { + "diagnostics": [ + { + "end": 233, + "message": "a `attribute` definition is not allowed in an enumeration definition body", + "severity": "Error", + "stage": "structure", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g69-calc-body-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 333, + "message": "expected `;` or `{`, found `+`", + "severity": "Error", + "stage": "parse", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g70-name-before-usage-keyword.sysml": { + "diagnostics": [ + { + "end": 286, + "message": "expected `;` or `{`, found `attribute`", + "severity": "Error", + "stage": "parse", + "start": 277 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k01-specializes-without-target.kerml": { + "diagnostics": [ + { + "end": 178, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k02-sysml-keyword-in-kerml.kerml": { + "diagnostics": [ + { + "end": 158, + "message": "expected `;` or `{`, found `def`", + "severity": "Error", + "stage": "parse", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k03-feature-typing-without-type.kerml": { + "diagnostics": [ + { + "end": 167, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k04-dangling-visibility.kerml": { + "diagnostics": [ + { + "end": 153, + "message": "unsupported or unexpected construct at `}`", + "severity": "Error", + "stage": "parse", + "start": 152 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k05-unclosed-body.kerml": { + "diagnostics": [ + { + "end": 111, + "message": "expected `}` closing body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 111 + }, + { + "end": 111, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 111 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k06-disjoining-without-target.kerml": { + "diagnostics": [ + { + "end": 151, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k07-conjugation-without-target.kerml": { + "diagnostics": [ + { + "end": 160, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 159 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k08-return-without-feature.kerml": { + "diagnostics": [ + { + "end": 139, + "message": "unsupported or unexpected construct at `;`", + "severity": "Error", + "stage": "parse", + "start": 138 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k09-inverting-without-target.kerml": { + "diagnostics": [ + { + "end": 157, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k10-featuring-without-type.kerml": { + "diagnostics": [ + { + "end": 141, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k11-namespace-prefix-metadata-without-name.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "expected a name, found `namespace`", + "severity": "Error", + "stage": "parse", + "start": 124 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k12-multiplicity-subset-without-target.kerml": { + "diagnostics": [ + { + "end": 161, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 160 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k13-step-without-declaration.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k14-flow-without-payload-target.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k15-conjugation-without-original.kerml": { + "diagnostics": [ + { + "end": 147, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k16-redefinition-without-target.kerml": { + "diagnostics": [ + { + "end": 162, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k17-unions-without-target.kerml": { + "diagnostics": [ + { + "end": 156, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k18-connector-end-without-reference.kerml": { + "diagnostics": [ + { + "end": 223, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 222 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k19-metadata-typing-without-name.kerml": { + "diagnostics": [ + { + "end": 154, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 153 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k20-function-body-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 330, + "message": "expected `;` or `{`, found `+`", + "severity": "Error", + "stage": "parse", + "start": 329 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k21-name-before-feature-keyword.kerml": { + "diagnostics": [ + { + "end": 265, + "message": "expected `;` or `{`, found `feature`", + "severity": "Error", + "stage": "parse", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn01-fork-two-incoming.sysml": { + "diagnostics": [ + { + "end": 295, + "message": "Control node has too many incoming successions [validateForkNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 294 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn02-join-two-outgoing.sysml": { + "diagnostics": [ + { + "end": 296, + "message": "Control node has too many outgoing successions [validateJoinNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 295 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn03-merge-two-outgoing.sysml": { + "diagnostics": [ + { + "end": 300, + "message": "Control node has too many outgoing successions [validateMergeNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 299 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn04-decide-two-incoming.sysml": { + "diagnostics": [ + { + "end": 384, + "message": "Control node has too many incoming successions [validateDecisionNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 383 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn05-control-node-outside-action.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 214 + }, + { + "end": 283, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 282 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn06-fork-incoming-target-multiplicity.sysml": { + "diagnostics": [ + { + "end": 393, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 360 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn07-join-outgoing-source-multiplicity.sysml": { + "diagnostics": [ + { + "end": 443, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 410 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn08-merge-incoming-source-multiplicity.sysml": { + "diagnostics": [ + { + "end": 389, + "message": "Succession end must have multiplicity 0..1 [validateMergeNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 359 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml": { + "diagnostics": [ + { + "end": 422, + "message": "Succession end must have multiplicity 0..1 [validateDecisionNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 392 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k01-two-owned-multiplicities.kerml": { + "diagnostics": [ + { + "end": 183, + "message": "Only one multiplicity is allowed [validateTypeOwnedMultiplicity]", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k02-differences-one-type.kerml": { + "diagnostics": [ + { + "end": 202, + "message": "A type operation must have zero or at least two operands [validateOwnedDifferencingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k03-intersects-one-type.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "A type operation must have zero or at least two operands [validateOwnedIntersectingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k04-unions-one-type.kerml": { + "diagnostics": [ + { + "end": 184, + "message": "A type operation must have zero or at least two operands [validateOwnedUnioningNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 183 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k05-differences-self.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "A type operation cannot name its own type as an operand [validateTypeDifferencingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k06-intersects-self.kerml": { + "diagnostics": [ + { + "end": 198, + "message": "A type operation cannot name its own type as an operand [validateTypeIntersectingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k07-unions-self.kerml": { + "diagnostics": [ + { + "end": 182, + "message": "A type operation cannot name its own type as an operand [validateTypeUnioningTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k08-conjugated-type-specialized.kerml": { + "diagnostics": [ + { + "end": 279, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 278 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k09-two-reference-subsettings.kerml": { + "diagnostics": [ + { + "end": 281, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedReferenceSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 280 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k10-portion-var-feature.kerml": { + "diagnostics": [ + { + "end": 251, + "message": "A portion cannot be variable [validateFeaturePortionNotVariable]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k11-initial-value-nonvariable.kerml": { + "diagnostics": [ + { + "end": 214, + "message": "An initialized feature must be variable [validateFeatureValueIsInitial]", + "severity": "Error", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k12-chain-through-self.kerml": { + "diagnostics": [ + { + "end": 248, + "message": "A feature cannot chain through itself [validateFeatureChainingFeaturesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k13-subsets-inaccessible-feature.kerml": { + "diagnostics": [ + { + "end": 300, + "message": "A subsetted feature must be accessible in the subsetting feature's context [validateSubsettingFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 296 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k14-variable-subsets-constant.kerml": { + "diagnostics": [ + { + "end": 333, + "message": "A variable subset of a constant feature must be constant [validateSubsettingConstantConformance]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k15-nonend-redefines-end.kerml": { + "diagnostics": [ + { + "end": 352, + "message": "A feature redefining an end must itself be an end [validateRedefinitionEndConformance]", + "severity": "Error", + "stage": "semantics", + "start": 351 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k16-crosses-from-nonend.kerml": { + "diagnostics": [ + { + "end": 282, + "message": "A crossing feature must be an end of a type with at least two ends [validateCrossSubsettingCrossingFeature]", + "severity": "Error", + "stage": "semantics", + "start": 281 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k17-crosses-not-through-opposite-end.kerml": { + "diagnostics": [ + { + "end": 275, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k18-cross-feature-type-differs.kerml": { + "diagnostics": [ + { + "end": 298, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k19-cross-feature-not-specializing.kerml": { + "diagnostics": [ + { + "end": 440, + "message": "A cross feature must specialize the cross feature of the redefined end [validateFeatureCrossFeatureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 438 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k20-datatype-specializes-class.kerml": { + "diagnostics": [ + { + "end": 217, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 216 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k21-class-specializes-datatype.kerml": { + "diagnostics": [ + { + "end": 211, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 210 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k22-struct-specializes-behavior.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "A structure cannot specialize a behavior [validateStructureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k23-behavior-specializes-struct.kerml": { + "diagnostics": [ + { + "end": 220, + "message": "A behavior cannot specialize a structure [validateBehaviorSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 219 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k24-binary-assoc-three-ends.kerml": { + "diagnostics": [ + { + "end": 244, + "message": "An association with more than two ends cannot specialize BinaryLink [validateAssociationBinarySpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 243 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k25-assoc-one-end.kerml": { + "diagnostics": [ + { + "end": 209, + "message": "An association must have at least two related types [validateAssociationRelatedTypes]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k26-binary-connector-three-ends.kerml": { + "diagnostics": [ + { + "end": 335, + "message": "connector with 3 ends specializes a binary connector (a binary connector cannot have more than two ends)", + "severity": "Warning", + "stage": "semantics", + "start": 318 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k27-connector-feature-outside-featuring-type.kerml": { + "diagnostics": [ + { + "end": 379, + "message": "A bound feature reference must be accessible in the binding's context [validateConnectorTypeFeaturing]", + "severity": "Error", + "stage": "semantics", + "start": 375 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k28-expr-two-return-parameters.kerml": { + "diagnostics": [ + { + "end": 235, + "message": "Only one return parameter is allowed [validateExpressionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k29-function-inherits-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 326, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 325 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k30-expr-inherits-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 321, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k31-invoke-class.kerml": { + "diagnostics": [ + { + "end": 257, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 254 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k32-too-many-arguments.kerml": { + "diagnostics": [ + { + "end": 353, + "message": "invocation of `F` supplies 2 arguments for 1 parameter(s)", + "severity": "Warning", + "stage": "semantics", + "start": 346 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k33-parameter-bound-twice.kerml": { + "diagnostics": [ + { + "end": 351, + "message": "invocation of `F` binds parameter `x` more than once", + "severity": "Warning", + "stage": "semantics", + "start": 350 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k34-constructor-feature-bound-twice.kerml": { + "diagnostics": [ + { + "end": 360, + "message": "A constructor cannot bind a feature more than once [validateConstructorExpressionNoDuplicateFeatureRedefinition]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k35-metadata-annotates-wrong-kind.kerml": { + "diagnostics": [ + { + "end": 292, + "message": "unresolved reference `annotatedElement`", + "severity": "Warning", + "stage": "referential", + "start": 276 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k36-metadata-body-redefines-outside.kerml": { + "diagnostics": [ + { + "end": 280, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k37-multiplicity-bound-not-natural.kerml": { + "diagnostics": [ + { + "end": 259, + "message": "A multiplicity bound must have a Natural result [validateMultiplicityRangeResultTypes]", + "severity": "Error", + "stage": "semantics", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k38-flow-end-without-dot-notation.kerml": { + "diagnostics": [ + { + "end": 293, + "message": "A flow end must identify a participant's payload feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 276 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k39-feature-reference-to-class.kerml": { + "diagnostics": [ + { + "end": 266, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 265 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k40-metadata-typed-by-class.kerml": { + "diagnostics": [ + { + "end": 404, + "message": "metadata must be typed by a metadata definition or metaclass; `M` is a Class", + "severity": "Error", + "stage": "semantics", + "start": 403 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k41-chain-expression-to-nested-class.kerml": { + "diagnostics": [ + { + "end": 335, + "message": "A feature-chain expression must select a feature [validateFeatureChainExpressionFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k42-two-cross-subsettings.kerml": { + "diagnostics": [ + { + "end": 300, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedCrossSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 299 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 355 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 373, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 372 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k45-conjugated-feature-without-type.kerml": { + "diagnostics": [ + { + "end": 293, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 292 + }, + { + "end": 322, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 321 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k46-conjugated-structure-not-an-object.kerml": { + "diagnostics": [ + { + "end": 342, + "message": "A structure must directly or indirectly specialize Objects::Object [validateClassifierDefaultSupertype]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml": { + "diagnostics": [ + { + "end": 467, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 465 + }, + { + "end": 502, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 500 + }, + { + "end": 533, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 531 + }, + { + "end": 561, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 560 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k48-annotating-element-annotates-itself.kerml": { + "diagnostics": [], + "status": "unknown" + }, + "negative/semantic/k49-binding-connector-with-three-ends.kerml": { + "diagnostics": [ + { + "end": 323, + "message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]", + "severity": "Error", + "stage": "semantics", + "start": 322 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k50-inline-cross-feature-also-crosses.kerml": { + "diagnostics": [ + { + "end": 379, + "message": "An end cannot declare both an inline cross feature and a cross subsetting [feature-cross-feature-single]", + "severity": "Error", + "stage": "semantics", + "start": 378 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k51-return-parameter-in-classifier.kerml": { + "diagnostics": [ + { + "end": 311, + "message": "a `return` parameter member is not allowed in a type body", + "severity": "Error", + "stage": "structure", + "start": 290 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k52-two-conjugators.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "expected `;` or `{`, found `~`", + "severity": "Error", + "stage": "parse", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k53-boolean-expression-subsets-datatype.kerml": { + "diagnostics": [ + { + "end": 475, + "message": "Subsetting::subsettedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 474 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml": { + "diagnostics": [ + { + "end": 382, + "message": "An inline cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 381 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k55-subtype-specific-is-package.kerml": { + "diagnostics": [ + { + "end": 374, + "message": "Specialization::specific must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 344 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k56-subtype-general-is-package.kerml": { + "diagnostics": [ + { + "end": 321, + "message": "Specialization::general must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k57-subclassifier-subclassifier-is-package.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Subclassification::subclassifier must refer to a Classifier [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 335 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml": { + "diagnostics": [ + { + "end": 426, + "message": "Subclassification::superclassifier must refer to a Classifier [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 381 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k59-typing-typed-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 326, + "message": "FeatureTyping::typedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 313 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k60-typing-typed-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 327, + "message": "FeatureTyping::typedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k61-typing-type-is-package.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "FeatureTyping::type must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 287 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k62-subset-subsetting-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 334, + "message": "Subsetting::subsettingFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k63-subset-subsetted-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 345, + "message": "Subsetting::subsettedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 311 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k64-redefinition-redefining-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Redefinition::redefiningFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k65-redefinition-redefined-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 380, + "message": "Redefinition::redefinedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 335 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k66-conjugate-conjugated-type-is-package.kerml": { + "diagnostics": [ + { + "end": 319, + "message": "Conjugation::conjugatedType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k67-conjugate-original-type-is-package.kerml": { + "diagnostics": [ + { + "end": 334, + "message": "Conjugation::originalType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k68-inverse-feature-inverted-is-package.kerml": { + "diagnostics": [ + { + "end": 348, + "message": "FeatureInverting::featureInverted must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 333 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k69-inverse-inverting-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 355, + "message": "FeatureInverting::invertingFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 330 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k70-disjoint-type-disjoined-is-package.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "Disjoining::typeDisjoined must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k71-disjoint-disjoining-type-is-package.kerml": { + "diagnostics": [ + { + "end": 329, + "message": "Disjoining::disjoiningType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k72-featuring-feature-of-type-is-class.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "TypeFeaturing::featureOfType must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 298 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k73-featuring-featuring-type-is-package.kerml": { + "diagnostics": [ + { + "end": 312, + "message": "TypeFeaturing::featuringType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 295 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s01-action-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "ActionUsage must be typed by Behavior; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s02-allocation-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "AllocationUsage must be typed by AllocationDefinition; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 317 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s03-analysis-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "AnalysisCaseUsage must be typed by AnalysisCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s04-assert-references-non-constraint.sysml": { + "diagnostics": [ + { + "end": 255, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 246 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s05-assign-to-package-level-attribute.sysml": { + "diagnostics": [ + { + "end": 251, + "message": "An assignment referent must be time varying [validateAssignmentActionUsageReferentIsTimeVarying]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s06-enum-attribute-two-types.sysml": { + "diagnostics": [ + { + "end": 242, + "message": "AttributeUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 241 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s07-calc-typed-by-action-def.sysml": { + "diagnostics": [ + { + "end": 201, + "message": "CalculationUsage must be typed by Function; the declared type is a ActionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s08-case-def-two-objectives.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "validateCaseDefinitionOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 236 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s09-case-def-two-subjects.sysml": { + "diagnostics": [ + { + "end": 236, + "message": "validateCaseDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s10-case-def-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 257, + "message": "validateCaseDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 243 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s11-case-two-objectives.sysml": { + "diagnostics": [ + { + "end": 235, + "message": "validateCaseUsageOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s12-case-two-subjects.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "validateCaseUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 203 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s13-case-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 239, + "message": "validateCaseUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 225 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s14-case-typed-by-action-def.sysml": { + "diagnostics": [ + { + "end": 173, + "message": "CaseUsage must be typed by CaseDefinition; the declared type is a ActionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 171 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s15-connection-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 305, + "message": "ConnectionUsage must be typed by AssociationStructure; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s16-event-references-non-occurrence.sysml": { + "diagnostics": [ + { + "end": 244, + "message": "EventOccurrenceUsage must reference a OccurrenceUsage [validateEventOccurrenceUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 236 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s17-exhibit-references-non-state.sysml": { + "diagnostics": [ + { + "end": 231, + "message": "ExhibitStateUsage must reference a StateUsage [validateExhibitStateUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s18-flow-def-three-ends.sysml": { + "diagnostics": [ + { + "end": 272, + "message": "validateFlowDefinitionFlowEnds: a flow definition may not have more than two flow ends", + "severity": "Error", + "stage": "structure", + "start": 257 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s19-flow-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 404, + "message": "FlowUsage must be typed by Interaction; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 402 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s20-include-references-non-use-case.sysml": { + "diagnostics": [ + { + "end": 257, + "message": "IncludeUseCaseUsage must reference a UseCaseUsage [validateIncludeUseCaseUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s21-interface-def-end-not-port.sysml": { + "diagnostics": [ + { + "end": 228, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s22-interface-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 344, + "message": "InterfaceUsage must be typed by InterfaceDefinition; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 342 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s23-metadata-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 203, + "message": "metadata must be typed by a metadata definition or metaclass; `PD` is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s24-perform-references-non-action.sysml": { + "diagnostics": [ + { + "end": 237, + "message": "PerformActionUsage must reference a ActionUsage [validatePerformActionUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s25-port-nested-composite-part.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "A non-port usage owned by a port must be referential [validatePortUsageNestedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 273 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s26-port-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "PortUsage must be typed by PortDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s27-rendering-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "RenderingUsage must be typed by RenderingDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s28-requirement-def-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 291, + "message": "validateRequirementDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 277 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s29-requirement-two-subjects.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "validateRequirementUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 238 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s30-requirement-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "validateRequirementUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 260 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s31-requirement-typed-by-constraint-def.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "RequirementUsage must be typed by RequirementDefinition; the declared type is a ConstraintDefinition", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s32-satisfy-references-non-requirement.sysml": { + "diagnostics": [ + { + "end": 244, + "message": "SatisfyRequirementUsage must reference a RequirementUsage [validateSatisfyRequirementUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s33-parallel-state-usage-with-succession.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "A parallel state cannot own successions or transitions [validateStateUsageParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 195 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s34-state-usage-two-entry-actions.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "A state may have at most one subaction of each kind [validateStateUsageSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s35-state-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "StateUsage must be typed by StateDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s36-usage-typed-by-feature.sysml": { + "diagnostics": [ + { + "end": 165, + "message": "ReferenceUsage must be typed by Classifier; the declared type is a Feature", + "severity": "Error", + "stage": "semantics", + "start": 153 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s37-variation-usage-member-not-variant.sysml": { + "diagnostics": [ + { + "end": 275, + "message": "A usage owned by a variation must be a variant [validateUsageVariationMembership]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s38-use-case-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 192, + "message": "UseCaseUsage must be typed by UseCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s39-verification-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 236, + "message": "VerificationCaseUsage must be typed by VerificationCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s40-view-def-two-renderings.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "A view may have at most one rendering [validateViewDefinitionOnlyOnvViewRendering]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s41-view-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "ViewUsage must be typed by ViewDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml": { + "diagnostics": [ + { + "end": 224, + "message": "ViewpointUsage must be typed by ViewpointDefinition; the declared type is a RequirementDefinition", + "severity": "Error", + "stage": "semantics", + "start": 222 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s43-assign-to-non-feature.sysml": { + "diagnostics": [ + { + "end": 210, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 208 + }, + { + "end": 210, + "message": "An assignment must refer to a feature [validateAssignmentActionUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s44-transition-target-not-action.sysml": { + "diagnostics": [ + { + "end": 292, + "message": "A transition's succession must target an action usage [validateTransitionUsageSuccession]", + "severity": "Error", + "stage": "semantics", + "start": 265 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s45-snapshot-outside-occurrence.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "A snapshot or timeslice must be owned by an occurrence definition or usage [validateOccurrenceUsageIsPortion]", + "severity": "Error", + "stage": "semantics", + "start": 240 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s46-feature-value-overriding.sysml": { + "diagnostics": [ + { + "end": 374, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 373 + }, + { + "end": 431, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 430 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s47-enumeration-specializes-enumeration.sysml": { + "diagnostics": [ + { + "end": 374, + "message": "A variation cannot specialize another variation [validateDefinitionVariationSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 373 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s48-after-trigger-not-duration.sysml": { + "diagnostics": [ + { + "end": 295, + "message": "A 'after' trigger argument must conform to ISQ::DurationValue [validateTriggerInvocationActionAfterArgument]", + "severity": "Error", + "stage": "semantics", + "start": 294 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s49-at-trigger-not-time-instant.sysml": { + "diagnostics": [ + { + "end": 387, + "message": "A 'at' trigger argument must conform to Time::TimeInstantValue [validateTriggerInvocationActionAtArgument]", + "severity": "Error", + "stage": "semantics", + "start": 382 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s50-when-trigger-not-boolean.sysml": { + "diagnostics": [ + { + "end": 356, + "message": "A 'when' trigger argument must conform to ScalarValues::Boolean [validateTriggerInvocationActionWhenArgument]", + "severity": "Error", + "stage": "semantics", + "start": 351 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml": { + "diagnostics": [ + { + "end": 351, + "message": "An expression body is not a value of the owning enumeration [validateEnumerationUsageType]", + "severity": "Error", + "stage": "semantics", + "start": 342 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s52-variant-port-composite.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 318 + }, + { + "end": 449, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 448 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s80-constant-attribute-not-variable.sysml": { + "diagnostics": [ + { + "end": 306, + "message": "Only a variable feature can be constant [validateFeatureConstantIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 305 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s81-guarded-succession-guard-not-boolean.sysml": { + "diagnostics": [ + { + "end": 390, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 386 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 392, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 389 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 538, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 497 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 415, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 414 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 430, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 429 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s86-end-with-direction.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "expected a definition or usage after prefix, found `in`", + "severity": "Error", + "stage": "parse", + "start": 211 + }, + { + "end": 265, + "message": "expected a definition or usage after prefix, found `out`", + "severity": "Error", + "stage": "parse", + "start": 262 + }, + { + "end": 312, + "message": "expected a definition or usage after prefix, found `inout`", + "severity": "Error", + "stage": "parse", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s87-end-derived-or-abstract.sysml": { + "diagnostics": [ + { + "end": 298, + "message": "expected a definition or usage after prefix, found `derived`", + "severity": "Error", + "stage": "parse", + "start": 291 + }, + { + "end": 355, + "message": "expected a definition or usage after prefix, found `abstract`", + "severity": "Error", + "stage": "parse", + "start": 347 + }, + { + "end": 413, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 404 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml": { + "diagnostics": [ + { + "end": 393, + "message": "An inline cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 392 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s89-case-def-inherits-two-objectives.sysml": { + "diagnostics": [ + { + "end": 316, + "message": "At most one effective member with this parameter role is allowed [validateCaseDefinitionOnlyOneObjective]", + "severity": "Error", + "stage": "semantics", + "start": 315 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s90-requirement-def-inherits-two-subjects.sysml": { + "diagnostics": [ + { + "end": 321, + "message": "At most one effective member with this parameter role is allowed [validateRequirementDefinitionOnlyOneSubject]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s91-case-references-second-objective.sysml": { + "diagnostics": [ + { + "end": 334, + "message": "At most one effective member with this parameter role is allowed [validateCaseUsageOnlyOneObjective]", + "severity": "Error", + "stage": "semantics", + "start": 333 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s92-requirement-references-second-subject.sysml": { + "diagnostics": [ + { + "end": 348, + "message": "At most one effective member with this parameter role is allowed [validateRequirementUsageOnlyOneSubject]", + "severity": "Error", + "stage": "semantics", + "start": 347 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml": { + "diagnostics": [ + { + "end": 421, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 412 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-constructor-non-type.sysml": { + "diagnostics": [ + { + "end": 401, + "message": "A constructor must instantiate a type [validateInstantiationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 388 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-payload-non-behavior.sysml": { + "diagnostics": [ + { + "end": 388, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 383 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-subaction-no-payload.sysml": { + "diagnostics": [ + { + "end": 470, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 449 + }, + { + "end": 523, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 479 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p01-public-root-import.kerml": { + "diagnostics": [ + { + "end": 177, + "message": "validateImportTopLevelVisibility: a top-level import must be private", + "severity": "Error", + "stage": "structure", + "start": 148 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p02-association-end-two-types.kerml": { + "diagnostics": [ + { + "end": 291, + "message": "An association end must have exactly one non-redundant type [validateAssociationEndTypes]", + "severity": "Error", + "stage": "semantics", + "start": 290 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p03-variable-in-datatype.kerml": { + "diagnostics": [ + { + "end": 251, + "message": "A variable feature must be owned by an occurrence type [validateFeatureIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p04-nonunique-subsets-unique.kerml": { + "diagnostics": [ + { + "end": 280, + "message": "A subset of a unique feature must be unique [validateSubsettingUniquenessConformance]", + "severity": "Error", + "stage": "semantics", + "start": 279 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p05-single-chaining-feature.kerml": { + "diagnostics": [ + { + "end": 286, + "message": "A feature chain must have at least two features [validateFeatureChainingFeatureNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p06-private-member-reference.kerml": { + "diagnostics": [ + { + "end": 237, + "message": "unresolved reference `A::X` — `P06PrivateMemberReference::A::X` exists but is private", + "severity": "Warning", + "stage": "referential", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p07-extraneous-closing-brace.kerml": { + "diagnostics": [ + { + "end": 194, + "message": "unsupported or unexpected construct at `}`", + "severity": "Error", + "stage": "parse", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p08-variant-outside-variation.sysml": { + "diagnostics": [ + { + "end": 277, + "message": "a `variant` member is only allowed in the body of a `variation` definition or usage", + "severity": "Error", + "stage": "structure", + "start": 266 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p09-variation-member-not-variant.sysml": { + "diagnostics": [ + { + "end": 286, + "message": "A usage owned by a variation must be a variant [validateDefinitionVariationMembership]", + "severity": "Error", + "stage": "semantics", + "start": 284 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p10-variation-specializes-variation.sysml": { + "diagnostics": [ + { + "end": 317, + "message": "A variation cannot specialize another variation [validateDefinitionVariationSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p11-metadata-body-not-evaluable.sysml": { + "diagnostics": [ + { + "end": 287, + "message": "A metadata body value must be model-level evaluable [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p12-filter-integer-condition.sysml": { + "diagnostics": [ + { + "end": 216, + "message": "An element filter must have a Boolean result [validateElementFilterMembershipIsBoolean]", + "severity": "Error", + "stage": "semantics", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p13-state-two-entry-actions.sysml": { + "diagnostics": [ + { + "end": 194, + "message": "A state may have at most one subaction of each kind [validateStateDefinitionSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p14-requirement-two-subjects.sysml": { + "diagnostics": [ + { + "end": 264, + "message": "validateRequirementDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 249 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p15-attribute-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "AttributeUsage must be typed by DataType; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p16-part-typed-by-attribute-def.sysml": { + "diagnostics": [ + { + "end": 238, + "message": "PartUsage must be typed by Class; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 232 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p17-calc-two-return-parameters.sysml": { + "diagnostics": [ + { + "end": 254, + "message": "Only one return parameter is allowed [validateFunctionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 253 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p18-enum-two-types.sysml": { + "diagnostics": [ + { + "end": 247, + "message": "EnumerationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 245 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p18-enum-value-typed-outside-enumeration.sysml": { + "diagnostics": [], + "status": "accepted (adjudicated)" + }, + "negative/xpect/p19-parallel-state-with-transition.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "A parallel state cannot own successions or transitions [validateStateDefinitionParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p20-connection-with-one-end.sysml": { + "diagnostics": [ + { + "end": 296, + "message": "A concrete connector must relate at least two features [validateConnectorRelatedFeatures]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p21-filter-constructor-condition.sysml": { + "diagnostics": [ + { + "end": 320, + "message": "An element filter must have a Boolean result [validateElementFilterMembershipIsBoolean]", + "severity": "Error", + "stage": "semantics", + "start": 306 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p22-filter-not-model-level-evaluable.sysml": { + "diagnostics": [ + { + "end": 415, + "message": "An element filter must be model-level evaluable [validateElementFilterMembershipIsModelLevelEvaluable]", + "severity": "Error", + "stage": "semantics", + "start": 404 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p23-metadata-body-feature-not-redefining.sysml": { + "diagnostics": [ + { + "end": 344, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p24-metadata-abstract-type.sysml": { + "diagnostics": [ + { + "end": 266, + "message": "Metadata must have a concrete type [validateMetadataFeatureMetadataNotAbstract]", + "severity": "Error", + "stage": "semantics", + "start": 241 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p25-two-individual-definitions.sysml": { + "diagnostics": [ + { + "end": 309, + "message": "At most one individual definition may type an occurrence [validateOccurrenceUsageIndividualDefinition]", + "severity": "Error", + "stage": "semantics", + "start": 300 + }, + { + "end": 309, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p26-port-def-nonreferential-usage.sysml": { + "diagnostics": [ + { + "end": 272, + "message": "A non-port usage owned by a port must be referential [validatePortDefinitionOwnedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p27-interface-end-not-port.sysml": { + "diagnostics": [ + { + "end": 336, + "message": "An interface end must be a port [validateInterfaceUsageEnd]", + "severity": "Error", + "stage": "semantics", + "start": 318 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p28-package-level-feature-redefined.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "A package-level feature cannot redefine another package-level feature [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 269 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p29-verify-outside-objective.sysml": { + "diagnostics": [ + { + "end": 317, + "message": "A requirement verification must be in the objective of a verification case [validateRequirementVerificationMembershipOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 308 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p30-two-view-renderings.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "A view may have at most one rendering [validateViewUsageOnlyOneRendering]", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p31-redefinition-incompatible-direction.sysml": { + "diagnostics": [ + { + "end": 367, + "message": "A redefining feature must have a compatible direction [validateRedefinitionDirectionConformance]", + "severity": "Error", + "stage": "semantics", + "start": 362 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p32-redefinition-same-featuring-type.sysml": { + "diagnostics": [ + { + "end": 425, + "message": "Redefining and redefined features cannot have the same owning type [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 421 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p33-individual-typed-by-plain-def.sysml": { + "diagnostics": [ + { + "end": 239, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p34-accepter-source-not-state.sysml": { + "diagnostics": [ + { + "end": 315, + "message": "A triggered transition must have a state usage as its source [validateTransitionUsageTriggerActions]", + "severity": "Error", + "stage": "semantics", + "start": 282 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateActionUsageType.sysml": { + "diagnostics": [ + { + "end": 136, + "message": "ActionUsage must be typed by Behavior; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 135 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateActorMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "an `actor` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAllocationUsageType.sysml": { + "diagnostics": [ + { + "end": 190, + "message": "AllocationUsage must be typed by AllocationDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAnalysisCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "AnalysisCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 186 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAnnotationAnnotatedElementOwnership.kerml": { + "diagnostics": [], + "status": "unknown" + }, + "probes/validateAssertConstraintUsageReference.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssignmentActionUsageReferent.sysml": { + "diagnostics": [ + { + "end": 150, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 149 + }, + { + "end": 150, + "message": "An assignment must refer to a feature [validateAssignmentActionUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 149 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "An assignment referent must be time varying [validateAssignmentActionUsageReferentIsTimeVarying]", + "severity": "Error", + "stage": "semantics", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssociationBinarySpecialization.kerml": { + "diagnostics": [ + { + "end": 162, + "message": "An association with more than two ends cannot specialize BinaryLink [validateAssociationBinarySpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 159 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssociationEndTypes.kerml": { + "diagnostics": [ + { + "end": 152, + "message": "An association end must have exactly one non-redundant type [validateAssociationEndTypes]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssociationRelatedTypes.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "An association must have at least two related types [validateAssociationRelatedTypes]", + "severity": "Error", + "stage": "semantics", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAttributeUsageEnumerationType.sysml": { + "diagnostics": [ + { + "end": 190, + "message": "EnumerationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAttributeUsageType.sysml": { + "diagnostics": [ + { + "end": 148, + "message": "AttributeUsage must be typed by DataType; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBehaviorSpecialization.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "A behavior cannot specialize a structure [validateBehaviorSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorIsBinary.kerml": { + "diagnostics": [ + { + "end": 192, + "message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]", + "severity": "Error", + "stage": "semantics", + "start": 191 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.kerml": { + "diagnostics": [ + { + "end": 222, + "message": "Bound feature types (String) and (Integer) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.result.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "Bound feature types (D) and (C) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.satisfy.sysml": { + "diagnostics": [ + { + "end": 247, + "message": "Bound feature types (PD) and (ID) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 246 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.subject.sysml": { + "diagnostics": [ + { + "end": 211, + "message": "Bound feature types (ID) and (PD) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 205 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCalculationUsageType.sysml": { + "diagnostics": [ + { + "end": 235, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 234 + }, + { + "end": 244, + "message": "CalculationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 242 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionOnlyOneObjective.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "validateCaseDefinitionOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 138 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 161, + "message": "validateCaseDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "validateCaseDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageOnlyOneObjective.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "validateCaseUsageOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 168, + "message": "validateCaseUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 154 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "validateCaseUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 163 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 149, + "message": "CaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.connection.sysml": { + "diagnostics": [ + { + "end": 162, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.kerml": { + "diagnostics": [ + { + "end": 149, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 148 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.subsets.kerml": { + "diagnostics": [ + { + "end": 189, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.sysml": { + "diagnostics": [ + { + "end": 140, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 139 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassifierDefaultSupertype.kerml": { + "diagnostics": [ + { + "end": 152, + "message": "A structure must directly or indirectly specialize Objects::Object [validateClassifierDefaultSupertype]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectionUsageType.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "ConnectionUsage must be typed by AssociationStructure; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectorBinarySpecialization.kerml": { + "diagnostics": [ + { + "end": 216, + "message": "connector with 3 ends specializes a binary connector (a binary connector cannot have more than two ends)", + "severity": "Warning", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectorRelatedFeatures.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "A concrete connector must relate at least two features [validateConnectorRelatedFeatures]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectorTypeFeaturing.kerml": { + "diagnostics": [ + { + "end": 202, + "message": "connector end references `x`, which is featured in `A` — no featuring context of the connector reaches it", + "severity": "Warning", + "stage": "semantics", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml": { + "diagnostics": [ + { + "end": 234, + "message": "A constructor cannot bind a feature more than once [validateConstructorExpressionNoDuplicateFeatureRedefinition]", + "severity": "Error", + "stage": "semantics", + "start": 215 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 254, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeOwningType.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCrossSubsettingCrossedFeature.kerml": { + "diagnostics": [ + { + "end": 230, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 229 + }, + { + "end": 233, + "message": "unresolved reference `ax`", + "severity": "Warning", + "stage": "referential", + "start": 231 + }, + { + "end": 216, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 215 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCrossSubsettingCrossingFeature.kerml": { + "diagnostics": [ + { + "end": 182, + "message": "A crossing feature must be an end of a type with at least two ends [validateCrossSubsettingCrossingFeature]", + "severity": "Error", + "stage": "semantics", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.kerml": { + "diagnostics": [ + { + "end": 148, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.subsets.kerml": { + "diagnostics": [ + { + "end": 191, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.sysml": { + "diagnostics": [ + { + "end": 138, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDecisionNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 229, + "message": "Control node has too many incoming successions [validateDecisionNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 228 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDecisionNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 237, + "message": "Succession end must have multiplicity 0..1 [validateDecisionNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDefinitionVariationMembership.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDefinitionVariationSpecialization.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 143 + }, + { + "end": 184, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateElementFilterMembershipIsBoolean.kerml": { + "diagnostics": [ + { + "end": 131, + "message": "An element filter must have a Boolean result [validateElementFilterMembershipIsBoolean]", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "An element filter must be model-level evaluable [validateElementFilterMembershipIsModelLevelEvaluable]", + "severity": "Error", + "stage": "semantics", + "start": 230 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateEnumerationUsageType.sysml": { + "diagnostics": [ + { + "end": 176, + "message": "EnumerationUsage must be typed by EnumerationDefinition; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateEventOccurrenceUsageReferent.sysml": { + "diagnostics": [ + { + "end": 163, + "message": "EventOccurrenceUsage must reference a OccurrenceUsage [validateEventOccurrenceUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExhibitStateUsageReference.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "ExhibitStateUsage must reference a StateUsage [validateExhibitStateUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExposeOwningNamespace.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "an `expose` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.kerml": { + "diagnostics": [ + { + "end": 193, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.sysml": { + "diagnostics": [ + { + "end": 380, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 339 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.typed.kerml": { + "diagnostics": [ + { + "end": 217, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 216 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultParameterMembership.kerml": { + "diagnostics": [ + { + "end": 130, + "message": "Only one return parameter is allowed [validateExpressionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 129 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainExpressionFeatureConformance.kerml": { + "diagnostics": [ + { + "end": 223, + "message": "A feature-chain expression must select a feature [validateFeatureChainExpressionFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeatureConformance.kerml": { + "diagnostics": [ + { + "end": 212, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeatureNotOne.kerml": { + "diagnostics": [ + { + "end": 169, + "message": "A feature chain must have at least two features [validateFeatureChainingFeatureNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeaturesNotSelf.kerml": { + "diagnostics": [ + { + "end": 198, + "message": "A feature cannot chain through itself [validateFeatureChainingFeaturesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureConstantIsVariable.sysml": { + "diagnostics": [ + { + "end": 189, + "message": "Only a variable feature can be constant [validateFeatureConstantIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureCrossFeatureSpecialization.kerml": { + "diagnostics": [ + { + "end": 319, + "message": "unresolved reference `y`", + "severity": "Warning", + "stage": "referential", + "start": 318 + }, + { + "end": 321, + "message": "unresolved reference `b`", + "severity": "Warning", + "stage": "referential", + "start": 320 + }, + { + "end": 304, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureCrossFeatureType.kerml": { + "diagnostics": [ + { + "end": 206, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 205 + }, + { + "end": 230, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndFeatureMultiplicity.kerml": { + "diagnostics": [ + { + "end": 163, + "message": "An end feature should have multiplicity 1..1 [validateFeatureEndFeatureMultiplicity]", + "severity": "Warning", + "stage": "semantics", + "start": 162 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndNoDirection.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "expected a definition or usage after prefix, found `in`", + "severity": "Error", + "stage": "parse", + "start": 144 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml": { + "diagnostics": [ + { + "end": 204, + "message": "expected a definition or usage after prefix, found `derived`", + "severity": "Error", + "stage": "parse", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureHasType.kerml": { + "diagnostics": [ + { + "end": 123, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 122 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureIsVariable.kerml": { + "diagnostics": [ + { + "end": 131, + "message": "A variable feature must be owned by an occurrence type [validateFeatureIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureOwnedCrossSubsetting.kerml": { + "diagnostics": [ + { + "end": 189, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedCrossSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureOwnedReferenceSubsetting.kerml": { + "diagnostics": [ + { + "end": 168, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedReferenceSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 167 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeaturePortionNotVariable.kerml": { + "diagnostics": [ + { + "end": 137, + "message": "A portion cannot be variable [validateFeaturePortionNotVariable]", + "severity": "Error", + "stage": "semantics", + "start": 136 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureReferenceExpressionReferentIsFeature.kerml": { + "diagnostics": [ + { + "end": 167, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueIsInitial.kerml": { + "diagnostics": [ + { + "end": 143, + "message": "An initialized feature must be variable [validateFeatureValueIsInitial]", + "severity": "Error", + "stage": "semantics", + "start": 142 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueOverriding.kerml": { + "diagnostics": [ + { + "end": 254, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 253 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueOverriding.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowDefinitionConnectionEnds.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "validateFlowDefinitionFlowEnds: a flow definition may not have more than two flow ends", + "severity": "Error", + "stage": "structure", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndImplicitSubsetting.kerml": { + "diagnostics": [ + { + "end": 271, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndImplicitSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndImplicitSubsetting.sysml": { + "diagnostics": [ + { + "end": 272, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndImplicitSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 271 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndSubsetting.kerml": { + "diagnostics": [ + { + "end": 281, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowUsageType.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "A flow end must identify a participant's payload feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 181 + }, + { + "end": 186, + "message": "FlowUsage must be typed by Interaction; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 185 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateForkNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "Control node has too many incoming successions [validateForkNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.kerml": { + "diagnostics": [ + { + "end": 196, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 194 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.specialization.kerml": { + "diagnostics": [ + { + "end": 219, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultParameterMembership.kerml": { + "diagnostics": [ + { + "end": 132, + "message": "Only one return parameter is allowed [validateFunctionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateImportTopLevelVisibility.kerml": { + "diagnostics": [ + { + "end": 125, + "message": "validateImportTopLevelVisibility: a top-level import must be private", + "severity": "Error", + "stage": "structure", + "start": 95 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateIncludeUseCaseUsageReference.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "IncludeUseCaseUsage must reference a UseCaseUsage [validateIncludeUseCaseUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInstantiationExpressionInstantiatedType.kerml": { + "diagnostics": [ + { + "end": 158, + "message": "A constructor must instantiate a type [validateInstantiationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceDefinitionEnd.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 155 + }, + { + "end": 172, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 171 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceUsageEnd.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "An interface end must be a port [validateInterfaceUsageEnd]", + "severity": "Error", + "stage": "semantics", + "start": 235 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceUsageType.sysml": { + "diagnostics": [ + { + "end": 197, + "message": "InterfaceUsage must be typed by InterfaceDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 196 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionInstantiatedType.kerml": { + "diagnostics": [ + { + "end": 161, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml": { + "diagnostics": [ + { + "end": 231, + "message": "invocation of `F` binds parameter `x` more than once", + "severity": "Warning", + "stage": "semantics", + "start": 230 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionParameterRedefinition.kerml": { + "diagnostics": [ + { + "end": 272, + "message": "unresolved reference `y`", + "severity": "Warning", + "stage": "referential", + "start": 271 + }, + { + "end": 276, + "message": "invocation of `F` names unknown parameter `y`", + "severity": "Warning", + "stage": "semantics", + "start": 275 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateJoinNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "Control node has too many outgoing successions [validateJoinNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateLibraryPackageNotStandard.kerml": { + "diagnostics": [ + { + "end": 146, + "message": "A user library package must not be marked standard [validateLibraryPackageNotStandard]", + "severity": "Error", + "stage": "semantics", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMergeNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "Succession end must have multiplicity 0..1 [validateMergeNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMergeNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "Control node has too many outgoing successions [validateMergeNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 154 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureAnnotatedElement.kerml": { + "diagnostics": [ + { + "end": 216, + "message": "The annotated element's metaclass does not conform to annotatedElement's type [validateMetadataFeatureAnnotatedElement]", + "severity": "Error", + "stage": "semantics", + "start": 215 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureBody.kerml": { + "diagnostics": [ + { + "end": 214, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureMetadata.kerml": { + "diagnostics": [ + { + "end": 154, + "message": "metadata must be typed by a metadata definition or metaclass; `NotAMetaclass` is a Class", + "severity": "Error", + "stage": "semantics", + "start": 141 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureMetadataNotAbstract.kerml": { + "diagnostics": [ + { + "end": 149, + "message": "Metadata must have a concrete type [validateMetadataFeatureMetadataNotAbstract]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataUsageType.sysml": { + "diagnostics": [ + { + "end": 185, + "message": "metadata must be typed by a metadata definition or metaclass; `NotMetadata` is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 174 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMultiplicityRangeResultTypes.kerml": { + "diagnostics": [ + { + "end": 132, + "message": "multiplicity bound must be a Natural number (or `*` for the upper bound)", + "severity": "Error", + "stage": "semantics", + "start": 127 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateNamespaceDistinguishablity.kerml": { + "diagnostics": [ + { + "end": 135, + "message": "the name `A` is already used by an earlier member of the same namespace whose metaclass is not distinguishable from this member", + "severity": "Error", + "stage": "structure", + "start": 134 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateObjectiveMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "validateObjectiveMembershipOwningType: an `objective` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIndividualDefinition.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "At most one individual definition may type an occurrence [validateOccurrenceUsageIndividualDefinition]", + "severity": "Error", + "stage": "semantics", + "start": 195 + }, + { + "end": 196, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 195 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIndividualUsage.sysml": { + "diagnostics": [ + { + "end": 167, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIsPortion.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "A snapshot or timeslice must be owned by an occurrence definition or usage [validateOccurrenceUsageIsPortion]", + "severity": "Error", + "stage": "semantics", + "start": 152 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageType.sysml": { + "diagnostics": [ + { + "end": 171, + "message": "OccurrenceUsage must be typed by Class; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOperatorExpressionBracketOperator.kerml": { + "diagnostics": [ + { + "end": 188, + "message": "Square brackets do not index a sequence; use #(index) [validateOperatorExpressionBracketOperator]", + "severity": "Warning", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOperatorExpressionCastConformance.kerml": { + "diagnostics": [ + { + "end": 227, + "message": "Cast types should conform in at least one direction [validateOperatorExpressionCastConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOperatorExpressionQuantity.sysml": { + "diagnostics": [ + { + "end": 174, + "message": "A quantity unit must be a measurement reference [validateOperatorExpressionQuantity]", + "severity": "Warning", + "stage": "semantics", + "start": 173 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedDifferencingNotOne.kerml": { + "diagnostics": [ + { + "end": 127, + "message": "A type operation must have zero or at least two operands [validateOwnedDifferencingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedIntersectingNotOne.kerml": { + "diagnostics": [ + { + "end": 127, + "message": "A type operation must have zero or at least two operands [validateOwnedIntersectingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedUnioningNotOne.kerml": { + "diagnostics": [ + { + "end": 119, + "message": "A type operation must have zero or at least two operands [validateOwnedUnioningNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 118 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePerformActionUsageReference.sysml": { + "diagnostics": [ + { + "end": 150, + "message": "PerformActionUsage must reference a ActionUsage [validatePerformActionUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortDefinitionOwnedUsagesNotComposite.sysml": { + "diagnostics": [ + { + "end": 192, + "message": "A non-port usage owned by a port must be referential [validatePortDefinitionOwnedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 191 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageIsReference.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageNestedUsagesNotComposite.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "A non-port usage owned by a port must be referential [validatePortUsageNestedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageType.sysml": { + "diagnostics": [ + { + "end": 127, + "message": "PortUsage must be typed by PortDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionDirectionConformance.kerml": { + "diagnostics": [ + { + "end": 213, + "message": "A redefining feature must have a compatible direction [validateRedefinitionDirectionConformance]", + "severity": "Error", + "stage": "semantics", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionEndConformance.kerml": { + "diagnostics": [ + { + "end": 221, + "message": "A feature redefining an end must itself be an end [validateRedefinitionEndConformance]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionFeaturingTypes.kerml": { + "diagnostics": [ + { + "end": 156, + "message": "A package-level feature cannot redefine another package-level feature [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionMultiplicityConformance.kerml": { + "diagnostics": [ + { + "end": 229, + "message": "redefining multiplicity [0..2] is not within the redefined feature's [1..2]", + "severity": "Warning", + "stage": "semantics", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRenderingUsageType.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "RenderingUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementConstraintMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "a `require` constraint member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementDefinitionOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 175, + "message": "validateRequirementDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementDefinitionSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "validateRequirementDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 189, + "message": "validateRequirementUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 198, + "message": "validateRequirementUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageType.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "RequirementUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementVerificationMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 228, + "message": "A requirement verification must be in the objective of a verification case [validateRequirementVerificationMembershipOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateReturnParameterMembershipOwningType.kerml": { + "diagnostics": [ + { + "end": 187, + "message": "a `return` parameter member is not allowed in a type body", + "severity": "Error", + "stage": "structure", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSatisfyRequirementUsageReference.sysml": { + "diagnostics": [ + { + "end": 165, + "message": "SatisfyRequirementUsage must reference a RequirementUsage [validateSatisfyRequirementUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSendActionUsagePayloadArgument.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSendActionUsageReceiver.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "Sending through a port should use 'via' [validateSendActionUsageReceiver]", + "severity": "Warning", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSpecializationSpecificNotConjugated.kerml": { + "diagnostics": [ + { + "end": 195, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSpecializationSpecificNotConjugated.subset.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStakeholderMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "a `stakeholder` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateDefinitionParallelSubactions.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "A parallel state cannot own successions or transitions [validateStateDefinitionParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateDefinitionSubactionKind.sysml": { + "diagnostics": [ + { + "end": 132, + "message": "A state may have at most one subaction of each kind [validateStateDefinitionSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateSubactionMembershioOwningType.sysml": { + "diagnostics": [ + { + "end": 208, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageParallelSubactions.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "A parallel state cannot own successions or transitions [validateStateUsageParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageSubactionKind.sysml": { + "diagnostics": [ + { + "end": 137, + "message": "A state may have at most one subaction of each kind [validateStateUsageSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 136 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageType.sysml": { + "diagnostics": [ + { + "end": 131, + "message": "StateUsage must be typed by StateDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStructureSpecialization.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "A structure cannot specialize a behavior [validateStructureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubjectMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "validateSubjectMembershipOwningType: a `subject` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingConstantConformance.kerml": { + "diagnostics": [ + { + "end": 308, + "message": "A variable subset of a constant feature must be constant [validateSubsettingConstantConformance]", + "severity": "Error", + "stage": "semantics", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingFeaturingTypes.kerml": { + "diagnostics": [ + { + "end": 194, + "message": "A subsetted feature must be accessible in the subsetting feature's context [validateSubsettingFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingMultiplicityConformance.kerml": { + "diagnostics": [ + { + "end": 237, + "message": "subsetting multiplicity upper bound 5 exceeds the subsetted feature's upper bound 2", + "severity": "Warning", + "stage": "semantics", + "start": 231 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingUniquenessConformance.kerml": { + "diagnostics": [ + { + "end": 260, + "message": "A subset of a unique feature must be unique [validateSubsettingUniquenessConformance]", + "severity": "Error", + "stage": "semantics", + "start": 259 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionFeatureMembershipGuardExpression.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 183 + }, + { + "end": 250, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 249 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionUsageSuccession.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "A transition's succession must target an action usage [validateTransitionUsageSuccession]", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionUsageTriggerActions.sysml": { + "diagnostics": [ + { + "end": 232, + "message": "A triggered transition must have a state usage as its source [validateTransitionUsageTriggerActions]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTriggerInvocationActionAfterArgument.sysml": { + "diagnostics": [ + { + "end": 305, + "message": "A 'after' trigger argument must conform to ISQ::DurationValue [validateTriggerInvocationActionAfterArgument]", + "severity": "Error", + "stage": "semantics", + "start": 304 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTriggerInvocationActionAtArgument.sysml": { + "diagnostics": [ + { + "end": 360, + "message": "A 'at' trigger argument must conform to Time::TimeInstantValue [validateTriggerInvocationActionAtArgument]", + "severity": "Error", + "stage": "semantics", + "start": 355 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTriggerInvocationActionWhenArgument.sysml": { + "diagnostics": [ + { + "end": 341, + "message": "A 'when' trigger argument must conform to ScalarValues::Boolean [validateTriggerInvocationActionWhenArgument]", + "severity": "Error", + "stage": "semantics", + "start": 336 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeAtMostOneConjugator.kerml": { + "diagnostics": [ + { + "end": 159, + "message": "expected `;` or `{`, found `~`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeDifferencingTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "A type operation cannot name its own type as an operand [validateTypeDifferencingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeIntersectingTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 132, + "message": "A type operation cannot name its own type as an operand [validateTypeIntersectingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeOwnedMultiplicity.kerml": { + "diagnostics": [ + { + "end": 113, + "message": "Only one multiplicity is allowed [validateTypeOwnedMultiplicity]", + "severity": "Error", + "stage": "semantics", + "start": 112 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeUnioningTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 124, + "message": "A type operation cannot name its own type as an operand [validateTypeUnioningTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 123 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUsageType.sysml": { + "diagnostics": [ + { + "end": 142, + "message": "ReferenceUsage must be typed by Classifier; the declared type is a Feature", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUsageVariationMembership.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 144 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUsageVariationSpecialization.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 150 + }, + { + "end": 191, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUseCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "UseCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateVariationMembershipOwningNamespace.sysml": { + "diagnostics": [ + { + "end": 162, + "message": "a `variant` member is only allowed in the body of a `variation` definition or usage", + "severity": "Error", + "stage": "structure", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateVerificationCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 211, + "message": "VerificationCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 209 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewDefinitionOnlyOnvViewRendering.sysml": { + "diagnostics": [ + { + "end": 166, + "message": "A view may have at most one rendering [validateViewDefinitionOnlyOnvViewRendering]", + "severity": "Error", + "stage": "semantics", + "start": 165 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewRenderingMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "a `render` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 185 + }, + { + "end": 199, + "message": "unresolved reference `asTable`", + "severity": "Warning", + "stage": "referential", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewUsageOnlyOneRendering.sysml": { + "diagnostics": [ + { + "end": 154, + "message": "A view may have at most one rendering [validateViewUsageOnlyOneRendering]", + "severity": "Error", + "stage": "semantics", + "start": 153 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewUsageType.sysml": { + "diagnostics": [ + { + "end": 149, + "message": "ViewUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewpointUsageType.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "ViewpointUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline.json b/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline.json new file mode 100644 index 0000000..5d2d857 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/baseline.json @@ -0,0 +1,6327 @@ +{ + "negative/extensions/x01-initial-state-marker.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected `;` or `{`, found `start`", + "severity": "Error", + "stage": "parse", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x02-choice-pseudostate.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "expected `;` or `{`, found `evaluate`", + "severity": "Error", + "stage": "parse", + "start": 206 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x03-junction-pseudostate.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "expected `;` or `{`, found `route`", + "severity": "Error", + "stage": "parse", + "start": 217 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x04-orthogonal-region.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "expected `;` or `{`, found `r1`", + "severity": "Error", + "stage": "parse", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x05-defer-member.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "expected `;` or `{`, found `Ping`", + "severity": "Error", + "stage": "parse", + "start": 205 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x06-history-member.sysml": { + "diagnostics": [ + { + "end": 217, + "message": "expected `;` or `{`, found `resume`", + "severity": "Error", + "stage": "parse", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x07-transition-to.sysml": { + "diagnostics": [ + { + "end": 212, + "message": "expected `then`, found `to`", + "severity": "Error", + "stage": "parse", + "start": 210 + }, + { + "end": 212, + "message": "expected a name, found `to`", + "severity": "Error", + "stage": "parse", + "start": 210 + } + ], + "status": "diagnostic baseline" + }, + "negative/extensions/x08-require-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 356, + "message": "a `require` constraint member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 329 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g01-unclosed-package-body.sysml": { + "diagnostics": [ + { + "end": 123, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 123 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g02-import-without-visibility.sysml": { + "diagnostics": [ + { + "end": 204, + "message": "an import must declare an explicit visibility (`public`, `private`, or `protected`)", + "severity": "Error", + "stage": "structure", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g03-alias-without-for.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected `for`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + }, + { + "end": 144, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g04-specialization-without-target.sysml": { + "diagnostics": [ + { + "end": 171, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g05-typing-without-type.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 143 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g06-definition-with-multiplicity.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "expected `;` or `{`, found `[`", + "severity": "Error", + "stage": "parse", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g07-entry-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 231, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 223 + }, + { + "end": 230, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g08-do-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 219, + "message": "a `do` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 214 + }, + { + "end": 218, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 217 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g09-value-without-expression.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g10-operator-without-operand.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g11-assignment-without-target.sysml": { + "diagnostics": [ + { + "end": 178, + "message": "expected `:=` in assignment, found `}`", + "severity": "Error", + "stage": "parse", + "start": 177 + }, + { + "end": 178, + "message": "expected an expression, found `}`", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g12-unterminated-block-comment.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "unterminated comment (missing `*/`)", + "severity": "Error", + "stage": "parse", + "start": 140 + }, + { + "end": 158, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g13-entry-then-without-target.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "expected a name, found `then`", + "severity": "Error", + "stage": "parse", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g14-connect-without-to.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "expected `to`, found `b`", + "severity": "Error", + "stage": "parse", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g15-keyword-as-name.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "expected `;` or `{`, found `part`", + "severity": "Error", + "stage": "parse", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g16-expose-without-name.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g17-render-without-usage.sysml": { + "diagnostics": [ + { + "end": 189, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g18-require-without-constraint.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g19-frame-without-concern.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g20-include-without-target.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g21-filter-without-expression.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "missing `;` after filter expression", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g22-dependency-without-to.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "expected `to`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 181 + }, + { + "end": 182, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g23-rep-without-language.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "expected `language`, found `/* self.x > 0 */`", + "severity": "Error", + "stage": "parse", + "start": 172 + }, + { + "end": 188, + "message": "expected a language string, found `/* self.x > 0 */`", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g24-alias-without-target.sysml": { + "diagnostics": [ + { + "end": 160, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 159 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g25-library-without-package.sysml": { + "diagnostics": [ + { + "end": 127, + "message": "expected `package`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g26-multiplicity-open-range.sysml": { + "diagnostics": [ + { + "end": 175, + "message": "expected a multiplicity bound (literal or feature name), found `]`", + "severity": "Error", + "stage": "parse", + "start": 174 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g27-bind-without-right-end.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g28-succession-without-target.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g29-flow-without-target.sysml": { + "diagnostics": [ + { + "end": 234, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g30-message-without-target.sysml": { + "diagnostics": [ + { + "end": 230, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g31-allocate-without-to.sysml": { + "diagnostics": [ + { + "end": 248, + "message": "expected `to`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 247 + }, + { + "end": 248, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g32-if-without-condition.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g33-while-without-condition.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g34-for-without-in.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "expected `in`, found `{`", + "severity": "Error", + "stage": "parse", + "start": 157 + }, + { + "end": 166, + "message": "expected `{`, found `}`", + "severity": "Error", + "stage": "parse", + "start": 165 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g35-accept-without-payload.sysml": { + "diagnostics": [ + { + "end": 194, + "message": "a payload requires a type, specialization, or value", + "severity": "Error", + "stage": "parse", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g36-direction-without-feature.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "expected a definition or usage after prefix, found `;`", + "severity": "Error", + "stage": "parse", + "start": 176 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g37-redefines-without-target.sysml": { + "diagnostics": [ + { + "end": 249, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 248 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g38-references-without-target.sysml": { + "diagnostics": [ + { + "end": 193, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g39-redefinition-symbol-without-target.sysml": { + "diagnostics": [ + { + "end": 230, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g40-modulo-without-operand.sysml": { + "diagnostics": [ + { + "end": 173, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 173 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g41-exponent-without-operand.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g42-implies-without-operand.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g43-null-coalescing-without-operand.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g44-conditional-without-else.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "expected `else`, found `;`", + "severity": "Error", + "stage": "parse", + "start": 176 + }, + { + "end": 177, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g45-classification-test-without-type.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g46-cast-without-type.sysml": { + "diagnostics": [ + { + "end": 140, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 139 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g47-prefix-metadata-without-name.sysml": { + "diagnostics": [ + { + "end": 166, + "message": "expected a name, found `part`", + "severity": "Error", + "stage": "parse", + "start": 162 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g48-decision-without-body.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g49-assign-without-value.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g50-conjugated-port-typing-without-name.sysml": { + "diagnostics": [ + { + "end": 208, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g51-real-without-fraction.sysml": { + "diagnostics": [ + { + "end": 168, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g52-unterminated-string.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "unterminated string literal", + "severity": "Error", + "stage": "parse", + "start": 138 + }, + { + "end": 146, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g53-range-without-upper-bound.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g54-argument-list-trailing-comma.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "expected an expression, found `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + }, + { + "end": 220, + "message": "expected `;` or `{`, found `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + }, + { + "end": 220, + "message": "unsupported or unexpected construct at `)`", + "severity": "Error", + "stage": "parse", + "start": 219 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g55-feature-chain-trailing-dot.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "missing `;` at end of declaration", + "severity": "Error", + "stage": "parse", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g56-qualified-name-trailing-separator.sysml": { + "diagnostics": [ + { + "end": 174, + "message": "expected `;` or `{`, found `::`", + "severity": "Error", + "stage": "parse", + "start": 172 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g57-unterminated-unrestricted-name.sysml": { + "diagnostics": [ + { + "end": 163, + "message": "unterminated unrestricted name", + "severity": "Error", + "stage": "parse", + "start": 157 + }, + { + "end": 163, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 163 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g58-satisfy-without-reference.sysml": { + "diagnostics": [ + { + "end": 227, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 226 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g59-crosses-without-target.sysml": { + "diagnostics": [ + { + "end": 203, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g60-alias-keyword-as-name.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "expected `for`, found `part`", + "severity": "Error", + "stage": "parse", + "start": 198 + }, + { + "end": 202, + "message": "expected a name, found `part`", + "severity": "Error", + "stage": "parse", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g61-actor-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 313, + "message": "an `actor` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 289 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g62-subject-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 320, + "message": "validateSubjectMembershipOwningType: a `subject` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g63-objective-outside-case-body.sysml": { + "diagnostics": [ + { + "end": 299, + "message": "validateObjectiveMembershipOwningType: an `objective` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 280 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g64-stakeholder-outside-requirement-body.sysml": { + "diagnostics": [ + { + "end": 333, + "message": "a `stakeholder` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 306 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g65-entry-action-outside-state-body.sysml": { + "diagnostics": [ + { + "end": 268, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g66-render-outside-view-body.sysml": { + "diagnostics": [ + { + "end": 312, + "message": "a `render` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g67-expose-outside-view-body.sysml": { + "diagnostics": [ + { + "end": 259, + "message": "an `expose` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 244 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g68-definition-in-enumeration-body.sysml": { + "diagnostics": [ + { + "end": 233, + "message": "a `attribute` definition is not allowed in an enumeration definition body", + "severity": "Error", + "stage": "structure", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g69-calc-body-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 333, + "message": "expected `;` or `{`, found `+`", + "severity": "Error", + "stage": "parse", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/g70-name-before-usage-keyword.sysml": { + "diagnostics": [ + { + "end": 286, + "message": "expected `;` or `{`, found `attribute`", + "severity": "Error", + "stage": "parse", + "start": 277 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k01-specializes-without-target.kerml": { + "diagnostics": [ + { + "end": 178, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k02-sysml-keyword-in-kerml.kerml": { + "diagnostics": [ + { + "end": 158, + "message": "expected `;` or `{`, found `def`", + "severity": "Error", + "stage": "parse", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k03-feature-typing-without-type.kerml": { + "diagnostics": [ + { + "end": 167, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k04-dangling-visibility.kerml": { + "diagnostics": [ + { + "end": 153, + "message": "unsupported or unexpected construct at `}`", + "severity": "Error", + "stage": "parse", + "start": 152 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k05-unclosed-body.kerml": { + "diagnostics": [ + { + "end": 111, + "message": "expected `}` closing body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 111 + }, + { + "end": 111, + "message": "expected `}` closing package body, found `end of input`", + "severity": "Error", + "stage": "parse", + "start": 111 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k06-disjoining-without-target.kerml": { + "diagnostics": [ + { + "end": 151, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k07-conjugation-without-target.kerml": { + "diagnostics": [ + { + "end": 160, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 159 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k08-return-without-feature.kerml": { + "diagnostics": [ + { + "end": 139, + "message": "unsupported or unexpected construct at `;`", + "severity": "Error", + "stage": "parse", + "start": 138 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k09-inverting-without-target.kerml": { + "diagnostics": [ + { + "end": 157, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k10-featuring-without-type.kerml": { + "diagnostics": [ + { + "end": 141, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k11-namespace-prefix-metadata-without-name.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "expected a name, found `namespace`", + "severity": "Error", + "stage": "parse", + "start": 124 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k12-multiplicity-subset-without-target.kerml": { + "diagnostics": [ + { + "end": 161, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 160 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k13-step-without-declaration.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k14-flow-without-payload-target.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k15-conjugation-without-original.kerml": { + "diagnostics": [ + { + "end": 147, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k16-redefinition-without-target.kerml": { + "diagnostics": [ + { + "end": 162, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k17-unions-without-target.kerml": { + "diagnostics": [ + { + "end": 156, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k18-connector-end-without-reference.kerml": { + "diagnostics": [ + { + "end": 223, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 222 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k19-metadata-typing-without-name.kerml": { + "diagnostics": [ + { + "end": 154, + "message": "expected a name, found `;`", + "severity": "Error", + "stage": "parse", + "start": 153 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k20-function-body-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 330, + "message": "expected `;` or `{`, found `+`", + "severity": "Error", + "stage": "parse", + "start": 329 + } + ], + "status": "diagnostic baseline" + }, + "negative/grammar/k21-name-before-feature-keyword.kerml": { + "diagnostics": [ + { + "end": 265, + "message": "expected `;` or `{`, found `feature`", + "severity": "Error", + "stage": "parse", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn01-fork-two-incoming.sysml": { + "diagnostics": [ + { + "end": 295, + "message": "Control node has too many incoming successions [validateForkNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 294 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn02-join-two-outgoing.sysml": { + "diagnostics": [ + { + "end": 296, + "message": "Control node has too many outgoing successions [validateJoinNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 295 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn03-merge-two-outgoing.sysml": { + "diagnostics": [ + { + "end": 300, + "message": "Control node has too many outgoing successions [validateMergeNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 299 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn04-decide-two-incoming.sysml": { + "diagnostics": [ + { + "end": 276, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 255 + }, + { + "end": 330, + "message": "unresolved reference `Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 323 + }, + { + "end": 384, + "message": "Control node has too many incoming successions [validateDecisionNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 383 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn05-control-node-outside-action.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 214 + }, + { + "end": 283, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 282 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn06-fork-incoming-target-multiplicity.sysml": { + "diagnostics": [ + { + "end": 393, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 360 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn07-join-outgoing-source-multiplicity.sysml": { + "diagnostics": [ + { + "end": 443, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 410 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn08-merge-incoming-source-multiplicity.sysml": { + "diagnostics": [ + { + "end": 389, + "message": "Succession end must have multiplicity 0..1 [validateMergeNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 359 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml": { + "diagnostics": [ + { + "end": 422, + "message": "Succession end must have multiplicity 0..1 [validateDecisionNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 392 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k01-two-owned-multiplicities.kerml": { + "diagnostics": [ + { + "end": 183, + "message": "Only one multiplicity is allowed [validateTypeOwnedMultiplicity]", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k02-differences-one-type.kerml": { + "diagnostics": [ + { + "end": 202, + "message": "A type operation must have zero or at least two operands [validateOwnedDifferencingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k03-intersects-one-type.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "A type operation must have zero or at least two operands [validateOwnedIntersectingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k04-unions-one-type.kerml": { + "diagnostics": [ + { + "end": 184, + "message": "A type operation must have zero or at least two operands [validateOwnedUnioningNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 183 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k05-differences-self.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "A type operation cannot name its own type as an operand [validateTypeDifferencingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k06-intersects-self.kerml": { + "diagnostics": [ + { + "end": 198, + "message": "A type operation cannot name its own type as an operand [validateTypeIntersectingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k07-unions-self.kerml": { + "diagnostics": [ + { + "end": 182, + "message": "A type operation cannot name its own type as an operand [validateTypeUnioningTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k08-conjugated-type-specialized.kerml": { + "diagnostics": [ + { + "end": 279, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 278 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k09-two-reference-subsettings.kerml": { + "diagnostics": [ + { + "end": 281, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedReferenceSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 280 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k10-portion-var-feature.kerml": { + "diagnostics": [ + { + "end": 219, + "message": "unresolved reference `Occurrences::Occurrence`", + "severity": "Warning", + "stage": "referential", + "start": 196 + }, + { + "end": 251, + "message": "A portion cannot be variable [validateFeaturePortionNotVariable]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k11-initial-value-nonvariable.kerml": { + "diagnostics": [ + { + "end": 214, + "message": "An initialized feature must be variable [validateFeatureValueIsInitial]", + "severity": "Error", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k12-chain-through-self.kerml": { + "diagnostics": [ + { + "end": 248, + "message": "A feature cannot chain through itself [validateFeatureChainingFeaturesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k13-subsets-inaccessible-feature.kerml": { + "diagnostics": [ + { + "end": 300, + "message": "A subsetted feature must be accessible in the subsetting feature's context [validateSubsettingFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 296 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k14-variable-subsets-constant.kerml": { + "diagnostics": [ + { + "end": 266, + "message": "unresolved reference `Occurrences::Occurrence`", + "severity": "Warning", + "stage": "referential", + "start": 243 + }, + { + "end": 333, + "message": "A variable subset of a constant feature must be constant [validateSubsettingConstantConformance]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k15-nonend-redefines-end.kerml": { + "diagnostics": [ + { + "end": 352, + "message": "A feature redefining an end must itself be an end [validateRedefinitionEndConformance]", + "severity": "Error", + "stage": "semantics", + "start": 351 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k16-crosses-from-nonend.kerml": { + "diagnostics": [ + { + "end": 282, + "message": "A crossing feature must be an end of a type with at least two ends [validateCrossSubsettingCrossingFeature]", + "severity": "Error", + "stage": "semantics", + "start": 281 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k17-crosses-not-through-opposite-end.kerml": { + "diagnostics": [ + { + "end": 275, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k18-cross-feature-type-differs.kerml": { + "diagnostics": [ + { + "end": 298, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k19-cross-feature-not-specializing.kerml": { + "diagnostics": [ + { + "end": 440, + "message": "A cross feature must specialize the cross feature of the redefined end [validateFeatureCrossFeatureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 438 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k20-datatype-specializes-class.kerml": { + "diagnostics": [ + { + "end": 217, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 216 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k21-class-specializes-datatype.kerml": { + "diagnostics": [ + { + "end": 211, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 210 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k22-struct-specializes-behavior.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "A structure cannot specialize a behavior [validateStructureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k23-behavior-specializes-struct.kerml": { + "diagnostics": [ + { + "end": 220, + "message": "A behavior cannot specialize a structure [validateBehaviorSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 219 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k24-binary-assoc-three-ends.kerml": { + "diagnostics": [ + { + "end": 274, + "message": "unresolved reference `Links::BinaryLink`", + "severity": "Warning", + "stage": "referential", + "start": 257 + } + ], + "status": "unknown without library" + }, + "negative/semantic/k25-assoc-one-end.kerml": { + "diagnostics": [ + { + "end": 209, + "message": "An association must have at least two related types [validateAssociationRelatedTypes]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k26-binary-connector-three-ends.kerml": { + "diagnostics": [ + { + "end": 335, + "message": "unresolved reference `Links::BinaryLink`", + "severity": "Warning", + "stage": "referential", + "start": 318 + } + ], + "status": "unknown without library" + }, + "negative/semantic/k27-connector-feature-outside-featuring-type.kerml": { + "diagnostics": [ + { + "end": 379, + "message": "A bound feature reference must be accessible in the binding's context [validateConnectorTypeFeaturing]", + "severity": "Error", + "stage": "semantics", + "start": 375 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k28-expr-two-return-parameters.kerml": { + "diagnostics": [ + { + "end": 235, + "message": "Only one return parameter is allowed [validateExpressionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k29-function-inherits-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 326, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 325 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k30-expr-inherits-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 321, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k31-invoke-class.kerml": { + "diagnostics": [ + { + "end": 257, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 254 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k32-too-many-arguments.kerml": { + "diagnostics": [ + { + "end": 353, + "message": "invocation of `F` supplies 2 arguments for 1 parameter(s)", + "severity": "Warning", + "stage": "semantics", + "start": 346 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k33-parameter-bound-twice.kerml": { + "diagnostics": [ + { + "end": 351, + "message": "invocation of `F` binds parameter `x` more than once", + "severity": "Warning", + "stage": "semantics", + "start": 350 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k34-constructor-feature-bound-twice.kerml": { + "diagnostics": [ + { + "end": 360, + "message": "A constructor cannot bind a feature more than once [validateConstructorExpressionNoDuplicateFeatureRedefinition]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k35-metadata-annotates-wrong-kind.kerml": { + "diagnostics": [ + { + "end": 292, + "message": "unresolved reference `annotatedElement`", + "severity": "Warning", + "stage": "referential", + "start": 276 + }, + { + "end": 307, + "message": "unresolved reference `KerML::Class`", + "severity": "Warning", + "stage": "referential", + "start": 295 + } + ], + "status": "unknown without library" + }, + "negative/semantic/k36-metadata-body-redefines-outside.kerml": { + "diagnostics": [ + { + "end": 280, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k37-multiplicity-bound-not-natural.kerml": { + "diagnostics": [ + { + "end": 259, + "message": "A multiplicity bound must have a Natural result [validateMultiplicityRangeResultTypes]", + "severity": "Error", + "stage": "semantics", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k38-flow-end-without-dot-notation.kerml": { + "diagnostics": [ + { + "end": 293, + "message": "A flow end must identify a participant's payload feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 276 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k39-feature-reference-to-class.kerml": { + "diagnostics": [ + { + "end": 266, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 265 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k40-metadata-typed-by-class.kerml": { + "diagnostics": [ + { + "end": 404, + "message": "metadata must be typed by a metadata definition or metaclass; `M` is a Class", + "severity": "Error", + "stage": "semantics", + "start": 403 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k41-chain-expression-to-nested-class.kerml": { + "diagnostics": [ + { + "end": 335, + "message": "A feature-chain expression must select a feature [validateFeatureChainExpressionFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k42-two-cross-subsettings.kerml": { + "diagnostics": [ + { + "end": 300, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedCrossSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 299 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 355 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml": { + "diagnostics": [ + { + "end": 373, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 372 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k45-conjugated-feature-without-type.kerml": { + "diagnostics": [ + { + "end": 293, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 292 + }, + { + "end": 322, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 321 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k46-conjugated-structure-not-an-object.kerml": { + "diagnostics": [ + { + "end": 342, + "message": "A structure must directly or indirectly specialize Objects::Object [validateClassifierDefaultSupertype]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml": { + "diagnostics": [ + { + "end": 467, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 465 + }, + { + "end": 502, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 500 + }, + { + "end": 533, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 531 + }, + { + "end": 561, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 560 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k48-annotating-element-annotates-itself.kerml": { + "diagnostics": [], + "status": "unknown without library" + }, + "negative/semantic/k49-binding-connector-with-three-ends.kerml": { + "diagnostics": [ + { + "end": 323, + "message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]", + "severity": "Error", + "stage": "semantics", + "start": 322 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k50-inline-cross-feature-also-crosses.kerml": { + "diagnostics": [ + { + "end": 379, + "message": "An end cannot declare both an inline cross feature and a cross subsetting [feature-cross-feature-single]", + "severity": "Error", + "stage": "semantics", + "start": 378 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k51-return-parameter-in-classifier.kerml": { + "diagnostics": [ + { + "end": 311, + "message": "a `return` parameter member is not allowed in a type body", + "severity": "Error", + "stage": "structure", + "start": 290 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k52-two-conjugators.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "expected `;` or `{`, found `~`", + "severity": "Error", + "stage": "parse", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k53-boolean-expression-subsets-datatype.kerml": { + "diagnostics": [ + { + "end": 475, + "message": "Subsetting::subsettedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 474 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml": { + "diagnostics": [ + { + "end": 382, + "message": "An inline cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 381 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k55-subtype-specific-is-package.kerml": { + "diagnostics": [ + { + "end": 374, + "message": "Specialization::specific must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 344 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k56-subtype-general-is-package.kerml": { + "diagnostics": [ + { + "end": 321, + "message": "Specialization::general must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k57-subclassifier-subclassifier-is-package.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Subclassification::subclassifier must refer to a Classifier [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 335 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml": { + "diagnostics": [ + { + "end": 426, + "message": "Subclassification::superclassifier must refer to a Classifier [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 381 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k59-typing-typed-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 326, + "message": "FeatureTyping::typedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 313 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k60-typing-typed-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 327, + "message": "FeatureTyping::typedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k61-typing-type-is-package.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "FeatureTyping::type must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 287 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k62-subset-subsetting-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 334, + "message": "Subsetting::subsettingFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k63-subset-subsetted-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 345, + "message": "Subsetting::subsettedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 311 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k64-redefinition-redefining-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 356, + "message": "Redefinition::redefiningFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 332 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k65-redefinition-redefined-feature-is-package.kerml": { + "diagnostics": [ + { + "end": 380, + "message": "Redefinition::redefinedFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 335 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k66-conjugate-conjugated-type-is-package.kerml": { + "diagnostics": [ + { + "end": 319, + "message": "Conjugation::conjugatedType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k67-conjugate-original-type-is-package.kerml": { + "diagnostics": [ + { + "end": 334, + "message": "Conjugation::originalType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k68-inverse-feature-inverted-is-package.kerml": { + "diagnostics": [ + { + "end": 348, + "message": "FeatureInverting::featureInverted must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 333 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k69-inverse-inverting-feature-is-class.kerml": { + "diagnostics": [ + { + "end": 355, + "message": "FeatureInverting::invertingFeature must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 330 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k70-disjoint-type-disjoined-is-package.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "Disjoining::typeDisjoined must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 297 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k71-disjoint-disjoining-type-is-package.kerml": { + "diagnostics": [ + { + "end": 329, + "message": "Disjoining::disjoiningType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k72-featuring-feature-of-type-is-class.kerml": { + "diagnostics": [ + { + "end": 315, + "message": "TypeFeaturing::featureOfType must refer to a Feature [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 298 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/k73-featuring-featuring-type-is-package.kerml": { + "diagnostics": [ + { + "end": 312, + "message": "TypeFeaturing::featuringType must refer to a Type [relationship-endpoint-metaclass]", + "severity": "Error", + "stage": "semantics", + "start": 295 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s01-action-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "ActionUsage must be typed by Behavior; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s02-allocation-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "AllocationUsage must be typed by AllocationDefinition; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 317 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s03-analysis-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "AnalysisCaseUsage must be typed by AnalysisCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s04-assert-references-non-constraint.sysml": { + "diagnostics": [ + { + "end": 255, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 246 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s05-assign-to-package-level-attribute.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 197 + }, + { + "end": 251, + "message": "An assignment referent must be time varying [validateAssignmentActionUsageReferentIsTimeVarying]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s06-enum-attribute-two-types.sysml": { + "diagnostics": [ + { + "end": 242, + "message": "AttributeUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 241 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s07-calc-typed-by-action-def.sysml": { + "diagnostics": [ + { + "end": 201, + "message": "CalculationUsage must be typed by Function; the declared type is a ActionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s08-case-def-two-objectives.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "validateCaseDefinitionOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 236 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s09-case-def-two-subjects.sysml": { + "diagnostics": [ + { + "end": 236, + "message": "validateCaseDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s10-case-def-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 257, + "message": "validateCaseDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 243 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s11-case-two-objectives.sysml": { + "diagnostics": [ + { + "end": 235, + "message": "validateCaseUsageOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s12-case-two-subjects.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "validateCaseUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 203 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s13-case-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 239, + "message": "validateCaseUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 225 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s14-case-typed-by-action-def.sysml": { + "diagnostics": [ + { + "end": 173, + "message": "CaseUsage must be typed by CaseDefinition; the declared type is a ActionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 171 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s15-connection-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 305, + "message": "ConnectionUsage must be typed by AssociationStructure; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s16-event-references-non-occurrence.sysml": { + "diagnostics": [ + { + "end": 244, + "message": "EventOccurrenceUsage must reference a OccurrenceUsage [validateEventOccurrenceUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 236 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s17-exhibit-references-non-state.sysml": { + "diagnostics": [ + { + "end": 231, + "message": "ExhibitStateUsage must reference a StateUsage [validateExhibitStateUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s18-flow-def-three-ends.sysml": { + "diagnostics": [ + { + "end": 272, + "message": "validateFlowDefinitionFlowEnds: a flow definition may not have more than two flow ends", + "severity": "Error", + "stage": "structure", + "start": 257 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s19-flow-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 404, + "message": "FlowUsage must be typed by Interaction; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 402 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s20-include-references-non-use-case.sysml": { + "diagnostics": [ + { + "end": 257, + "message": "IncludeUseCaseUsage must reference a UseCaseUsage [validateIncludeUseCaseUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 247 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s21-interface-def-end-not-port.sysml": { + "diagnostics": [ + { + "end": 228, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s22-interface-typed-by-connection-def.sysml": { + "diagnostics": [ + { + "end": 344, + "message": "InterfaceUsage must be typed by InterfaceDefinition; the declared type is a ConnectionDefinition", + "severity": "Error", + "stage": "semantics", + "start": 342 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s23-metadata-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 203, + "message": "metadata must be typed by a metadata definition or metaclass; `PD` is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s24-perform-references-non-action.sysml": { + "diagnostics": [ + { + "end": 237, + "message": "PerformActionUsage must reference a ActionUsage [validatePerformActionUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s25-port-nested-composite-part.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "A non-port usage owned by a port must be referential [validatePortUsageNestedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 273 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s26-port-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "PortUsage must be typed by PortDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s27-rendering-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "RenderingUsage must be typed by RenderingDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s28-requirement-def-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 291, + "message": "validateRequirementDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 277 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s29-requirement-two-subjects.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "validateRequirementUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 238 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s30-requirement-subject-not-first.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "validateRequirementUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 260 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s31-requirement-typed-by-constraint-def.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "RequirementUsage must be typed by RequirementDefinition; the declared type is a ConstraintDefinition", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s32-satisfy-references-non-requirement.sysml": { + "diagnostics": [ + { + "end": 244, + "message": "SatisfyRequirementUsage must reference a RequirementUsage [validateSatisfyRequirementUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s33-parallel-state-usage-with-succession.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "A parallel state cannot own successions or transitions [validateStateUsageParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 195 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s34-state-usage-two-entry-actions.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "A state may have at most one subaction of each kind [validateStateUsageSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 169 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s35-state-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "StateUsage must be typed by StateDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s36-usage-typed-by-feature.sysml": { + "diagnostics": [ + { + "end": 165, + "message": "unresolved reference `Base::things`", + "severity": "Warning", + "stage": "referential", + "start": 153 + } + ], + "status": "unknown without library" + }, + "negative/semantic/s37-variation-usage-member-not-variant.sysml": { + "diagnostics": [ + { + "end": 275, + "message": "A usage owned by a variation must be a variant [validateUsageVariationMembership]", + "severity": "Error", + "stage": "semantics", + "start": 274 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s38-use-case-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 192, + "message": "UseCaseUsage must be typed by UseCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s39-verification-typed-by-case-def.sysml": { + "diagnostics": [ + { + "end": 236, + "message": "VerificationCaseUsage must be typed by VerificationCaseDefinition; the declared type is a CaseDefinition", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s40-view-def-two-renderings.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "A view may have at most one rendering [validateViewDefinitionOnlyOnvViewRendering]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s41-view-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "ViewUsage must be typed by ViewDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml": { + "diagnostics": [ + { + "end": 224, + "message": "ViewpointUsage must be typed by ViewpointDefinition; the declared type is a RequirementDefinition", + "severity": "Error", + "stage": "semantics", + "start": 222 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s43-assign-to-non-feature.sysml": { + "diagnostics": [ + { + "end": 210, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 208 + }, + { + "end": 210, + "message": "An assignment must refer to a feature [validateAssignmentActionUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s44-transition-target-not-action.sysml": { + "diagnostics": [ + { + "end": 292, + "message": "A transition's succession must target an action usage [validateTransitionUsageSuccession]", + "severity": "Error", + "stage": "semantics", + "start": 265 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s45-snapshot-outside-occurrence.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "A snapshot or timeslice must be owned by an occurrence definition or usage [validateOccurrenceUsageIsPortion]", + "severity": "Error", + "stage": "semantics", + "start": 240 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s46-feature-value-overriding.sysml": { + "diagnostics": [ + { + "end": 270, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 249 + }, + { + "end": 318, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 311 + }, + { + "end": 374, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 373 + }, + { + "end": 431, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 430 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s47-enumeration-specializes-enumeration.sysml": { + "diagnostics": [ + { + "end": 374, + "message": "A variation cannot specialize another variation [validateDefinitionVariationSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 373 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s48-after-trigger-not-duration.sysml": { + "diagnostics": [ + { + "end": 295, + "message": "A 'after' trigger argument must conform to ISQ::DurationValue [validateTriggerInvocationActionAfterArgument]", + "severity": "Error", + "stage": "semantics", + "start": 294 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s49-at-trigger-not-time-instant.sysml": { + "diagnostics": [ + { + "end": 221, + "message": "unresolved reference `ISQ`", + "severity": "Warning", + "stage": "referential", + "start": 218 + }, + { + "end": 247, + "message": "unresolved reference `SI`", + "severity": "Warning", + "stage": "referential", + "start": 245 + }, + { + "end": 309, + "message": "unresolved reference `DurationValue`", + "severity": "Warning", + "stage": "referential", + "start": 296 + } + ], + "status": "unknown without library" + }, + "negative/semantic/s50-when-trigger-not-boolean.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "unresolved reference `ScalarValues`", + "severity": "Warning", + "stage": "referential", + "start": 208 + }, + { + "end": 276, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 269 + } + ], + "status": "unknown without library" + }, + "negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml": { + "diagnostics": [ + { + "end": 351, + "message": "An expression body is not a value of the owning enumeration [validateEnumerationUsageType]", + "severity": "Error", + "stage": "semantics", + "start": 342 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s52-variant-port-composite.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 318 + }, + { + "end": 449, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 448 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s80-constant-attribute-not-variable.sysml": { + "diagnostics": [ + { + "end": 306, + "message": "Only a variable feature can be constant [validateFeatureConstantIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 305 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s81-guarded-succession-guard-not-boolean.sysml": { + "diagnostics": [ + { + "end": 390, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 386 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 301 + }, + { + "end": 358, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 354 + }, + { + "end": 392, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 389 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 340, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 322 + }, + { + "end": 397, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 393 + }, + { + "end": 538, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 497 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 344, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 326 + }, + { + "end": 368, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 364 + }, + { + "end": 415, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 414 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 301 + }, + { + "end": 343, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 339 + }, + { + "end": 430, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 429 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s86-end-with-direction.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "expected a definition or usage after prefix, found `in`", + "severity": "Error", + "stage": "parse", + "start": 211 + }, + { + "end": 265, + "message": "expected a definition or usage after prefix, found `out`", + "severity": "Error", + "stage": "parse", + "start": 262 + }, + { + "end": 312, + "message": "expected a definition or usage after prefix, found `inout`", + "severity": "Error", + "stage": "parse", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s87-end-derived-or-abstract.sysml": { + "diagnostics": [ + { + "end": 298, + "message": "expected a definition or usage after prefix, found `derived`", + "severity": "Error", + "stage": "parse", + "start": 291 + }, + { + "end": 355, + "message": "expected a definition or usage after prefix, found `abstract`", + "severity": "Error", + "stage": "parse", + "start": 347 + }, + { + "end": 413, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 404 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml": { + "diagnostics": [ + { + "end": 393, + "message": "An inline cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 392 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s89-case-def-inherits-two-objectives.sysml": { + "diagnostics": [ + { + "end": 316, + "message": "At most one effective member with this parameter role is allowed [validateCaseDefinitionOnlyOneObjective]", + "severity": "Error", + "stage": "semantics", + "start": 315 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s90-requirement-def-inherits-two-subjects.sysml": { + "diagnostics": [ + { + "end": 321, + "message": "At most one effective member with this parameter role is allowed [validateRequirementDefinitionOnlyOneSubject]", + "severity": "Error", + "stage": "semantics", + "start": 320 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s91-case-references-second-objective.sysml": { + "diagnostics": [ + { + "end": 334, + "message": "At most one effective member with this parameter role is allowed [validateCaseUsageOnlyOneObjective]", + "severity": "Error", + "stage": "semantics", + "start": 333 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s92-requirement-references-second-subject.sysml": { + "diagnostics": [ + { + "end": 348, + "message": "At most one effective member with this parameter role is allowed [validateRequirementUsageOnlyOneSubject]", + "severity": "Error", + "stage": "semantics", + "start": 347 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml": { + "diagnostics": [ + { + "end": 421, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 412 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-constructor-non-type.sysml": { + "diagnostics": [ + { + "end": 401, + "message": "A constructor must instantiate a type [validateInstantiationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 388 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-payload-non-behavior.sysml": { + "diagnostics": [ + { + "end": 388, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 383 + } + ], + "status": "diagnostic baseline" + }, + "negative/semantic/send-subaction-no-payload.sysml": { + "diagnostics": [ + { + "end": 470, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 449 + }, + { + "end": 523, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 479 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p01-public-root-import.kerml": { + "diagnostics": [ + { + "end": 177, + "message": "validateImportTopLevelVisibility: a top-level import must be private", + "severity": "Error", + "stage": "structure", + "start": 148 + }, + { + "end": 176, + "message": "unresolved reference `Base::Anything`", + "severity": "Warning", + "stage": "referential", + "start": 162 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p02-association-end-two-types.kerml": { + "diagnostics": [ + { + "end": 291, + "message": "An association end must have exactly one non-redundant type [validateAssociationEndTypes]", + "severity": "Error", + "stage": "semantics", + "start": 290 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p03-variable-in-datatype.kerml": { + "diagnostics": [ + { + "end": 251, + "message": "A variable feature must be owned by an occurrence type [validateFeatureIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p04-nonunique-subsets-unique.kerml": { + "diagnostics": [ + { + "end": 280, + "message": "A subset of a unique feature must be unique [validateSubsettingUniquenessConformance]", + "severity": "Error", + "stage": "semantics", + "start": 279 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p05-single-chaining-feature.kerml": { + "diagnostics": [ + { + "end": 286, + "message": "A feature chain must have at least two features [validateFeatureChainingFeatureNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p06-private-member-reference.kerml": { + "diagnostics": [ + { + "end": 237, + "message": "unresolved reference `A::X` — `P06PrivateMemberReference::A::X` exists but is private", + "severity": "Warning", + "stage": "referential", + "start": 233 + } + ], + "status": "unknown without library" + }, + "negative/xpect/p07-extraneous-closing-brace.kerml": { + "diagnostics": [ + { + "end": 194, + "message": "unsupported or unexpected construct at `}`", + "severity": "Error", + "stage": "parse", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p08-variant-outside-variation.sysml": { + "diagnostics": [ + { + "end": 277, + "message": "a `variant` member is only allowed in the body of a `variation` definition or usage", + "severity": "Error", + "stage": "structure", + "start": 266 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p09-variation-member-not-variant.sysml": { + "diagnostics": [ + { + "end": 286, + "message": "A usage owned by a variation must be a variant [validateDefinitionVariationMembership]", + "severity": "Error", + "stage": "semantics", + "start": 284 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p10-variation-specializes-variation.sysml": { + "diagnostics": [ + { + "end": 317, + "message": "A variation cannot specialize another variation [validateDefinitionVariationSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p11-metadata-body-not-evaluable.sysml": { + "diagnostics": [ + { + "end": 287, + "message": "A metadata body value must be model-level evaluable [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 285 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p12-filter-integer-condition.sysml": { + "diagnostics": [], + "status": "unknown without library" + }, + "negative/xpect/p13-state-two-entry-actions.sysml": { + "diagnostics": [ + { + "end": 194, + "message": "A state may have at most one subaction of each kind [validateStateDefinitionSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 193 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p14-requirement-two-subjects.sysml": { + "diagnostics": [ + { + "end": 264, + "message": "validateRequirementDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 249 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p15-attribute-typed-by-part-def.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "AttributeUsage must be typed by DataType; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p16-part-typed-by-attribute-def.sysml": { + "diagnostics": [ + { + "end": 238, + "message": "PartUsage must be typed by Class; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 232 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p17-calc-two-return-parameters.sysml": { + "diagnostics": [ + { + "end": 254, + "message": "Only one return parameter is allowed [validateFunctionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 253 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p18-enum-two-types.sysml": { + "diagnostics": [ + { + "end": 247, + "message": "EnumerationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 245 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p18-enum-value-typed-outside-enumeration.sysml": { + "diagnostics": [ + { + "end": 319, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 301 + }, + { + "end": 343, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 339 + } + ], + "status": "accepted (adjudicated)" + }, + "negative/xpect/p19-parallel-state-with-transition.sysml": { + "diagnostics": [ + { + "end": 215, + "message": "A parallel state cannot own successions or transitions [validateStateDefinitionParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p20-connection-with-one-end.sysml": { + "diagnostics": [ + { + "end": 296, + "message": "A concrete connector must relate at least two features [validateConnectorRelatedFeatures]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p21-filter-constructor-condition.sysml": { + "diagnostics": [ + { + "end": 287, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 266 + } + ], + "status": "unknown without library" + }, + "negative/xpect/p22-filter-not-model-level-evaluable.sysml": { + "diagnostics": [ + { + "end": 304, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 283 + }, + { + "end": 357, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 336 + }, + { + "end": 389, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 368 + }, + { + "end": 415, + "message": "An element filter must be model-level evaluable [validateElementFilterMembershipIsModelLevelEvaluable]", + "severity": "Error", + "stage": "semantics", + "start": 404 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p23-metadata-body-feature-not-redefining.sysml": { + "diagnostics": [ + { + "end": 271, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 250 + }, + { + "end": 344, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 341 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p24-metadata-abstract-type.sysml": { + "diagnostics": [ + { + "end": 265, + "message": "unresolved reference `Metaobjects::Metaobject`", + "severity": "Warning", + "stage": "referential", + "start": 242 + } + ], + "status": "unknown without library" + }, + "negative/xpect/p25-two-individual-definitions.sysml": { + "diagnostics": [ + { + "end": 309, + "message": "At most one individual definition may type an occurrence [validateOccurrenceUsageIndividualDefinition]", + "severity": "Error", + "stage": "semantics", + "start": 300 + }, + { + "end": 309, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 300 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p26-port-def-nonreferential-usage.sysml": { + "diagnostics": [ + { + "end": 272, + "message": "A non-port usage owned by a port must be referential [validatePortDefinitionOwnedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p27-interface-end-not-port.sysml": { + "diagnostics": [ + { + "end": 336, + "message": "An interface end must be a port [validateInterfaceUsageEnd]", + "severity": "Error", + "stage": "semantics", + "start": 318 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p28-package-level-feature-redefined.sysml": { + "diagnostics": [ + { + "end": 274, + "message": "A package-level feature cannot redefine another package-level feature [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 269 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p29-verify-outside-objective.sysml": { + "diagnostics": [ + { + "end": 317, + "message": "A requirement verification must be in the objective of a verification case [validateRequirementVerificationMembershipOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 308 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p30-two-view-renderings.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "A view may have at most one rendering [validateViewUsageOnlyOneRendering]", + "severity": "Error", + "stage": "semantics", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p31-redefinition-incompatible-direction.sysml": { + "diagnostics": [ + { + "end": 367, + "message": "A redefining feature must have a compatible direction [validateRedefinitionDirectionConformance]", + "severity": "Error", + "stage": "semantics", + "start": 362 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p32-redefinition-same-featuring-type.sysml": { + "diagnostics": [ + { + "end": 425, + "message": "Redefining and redefined features cannot have the same owning type [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 421 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p33-individual-typed-by-plain-def.sysml": { + "diagnostics": [ + { + "end": 239, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 234 + } + ], + "status": "diagnostic baseline" + }, + "negative/xpect/p34-accepter-source-not-state.sysml": { + "diagnostics": [ + { + "end": 315, + "message": "A triggered transition must have a state usage as its source [validateTransitionUsageTriggerActions]", + "severity": "Error", + "stage": "semantics", + "start": 282 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateActionUsageType.sysml": { + "diagnostics": [ + { + "end": 136, + "message": "ActionUsage must be typed by Behavior; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 135 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateActorMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 213, + "message": "an `actor` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 201 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAllocationUsageType.sysml": { + "diagnostics": [ + { + "end": 190, + "message": "AllocationUsage must be typed by AllocationDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAnalysisCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "AnalysisCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 186 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAnnotationAnnotatedElementOwnership.kerml": { + "diagnostics": [], + "status": "unknown without library" + }, + "probes/validateAssertConstraintUsageReference.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "AssertConstraintUsage must reference a ConstraintUsage [validateAssertConstraintUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssignmentActionUsageReferent.sysml": { + "diagnostics": [ + { + "end": 150, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 149 + }, + { + "end": 150, + "message": "An assignment must refer to a feature [validateAssignmentActionUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 149 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml": { + "diagnostics": [ + { + "end": 176, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 155 + }, + { + "end": 215, + "message": "An assignment referent must be time varying [validateAssignmentActionUsageReferentIsTimeVarying]", + "severity": "Error", + "stage": "semantics", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssociationBinarySpecialization.kerml": { + "diagnostics": [ + { + "end": 192, + "message": "unresolved reference `Links::BinaryLink`", + "severity": "Warning", + "stage": "referential", + "start": 175 + } + ], + "status": "unknown without library" + }, + "probes/validateAssociationEndTypes.kerml": { + "diagnostics": [ + { + "end": 152, + "message": "An association end must have exactly one non-redundant type [validateAssociationEndTypes]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAssociationRelatedTypes.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "An association must have at least two related types [validateAssociationRelatedTypes]", + "severity": "Error", + "stage": "semantics", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAttributeUsageEnumerationType.sysml": { + "diagnostics": [ + { + "end": 190, + "message": "EnumerationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateAttributeUsageType.sysml": { + "diagnostics": [ + { + "end": 148, + "message": "AttributeUsage must be typed by DataType; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBehaviorSpecialization.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "A behavior cannot specialize a structure [validateBehaviorSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorIsBinary.kerml": { + "diagnostics": [ + { + "end": 192, + "message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]", + "severity": "Error", + "stage": "semantics", + "start": 191 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.kerml": { + "diagnostics": [ + { + "end": 171, + "message": "unresolved reference `ScalarValues::String`", + "severity": "Warning", + "stage": "referential", + "start": 151 + }, + { + "end": 206, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 185 + } + ], + "status": "unknown without library" + }, + "probes/validateBindingConnectorTypeConformance.result.kerml": { + "diagnostics": [ + { + "end": 200, + "message": "Bound feature types (D) and (C) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.satisfy.sysml": { + "diagnostics": [ + { + "end": 247, + "message": "Bound feature types (PD) and (ID) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 246 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateBindingConnectorTypeConformance.subject.sysml": { + "diagnostics": [ + { + "end": 211, + "message": "Bound feature types (ID) and (PD) should conform [validateBindingConnectorTypeConformance]", + "severity": "Warning", + "stage": "semantics", + "start": 205 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCalculationUsageType.sysml": { + "diagnostics": [ + { + "end": 173, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 152 + }, + { + "end": 223, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 202 + }, + { + "end": 235, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 234 + }, + { + "end": 244, + "message": "CalculationUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 242 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionOnlyOneObjective.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "validateCaseDefinitionOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 138 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 161, + "message": "validateCaseDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseDefinitionSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 170, + "message": "validateCaseDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageOnlyOneObjective.sysml": { + "diagnostics": [ + { + "end": 158, + "message": "validateCaseUsageOnlyOneObjective: a case may own at most one objective", + "severity": "Error", + "stage": "structure", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 168, + "message": "validateCaseUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 154 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 177, + "message": "validateCaseUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 163 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 149, + "message": "CaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.connection.sysml": { + "diagnostics": [ + { + "end": 162, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.kerml": { + "diagnostics": [ + { + "end": 149, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 148 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.subsets.kerml": { + "diagnostics": [ + { + "end": 189, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassSpecialization.sysml": { + "diagnostics": [ + { + "end": 140, + "message": "A class cannot specialize a data type or an unrelated association family [validateClassSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 139 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateClassifierDefaultSupertype.kerml": { + "diagnostics": [ + { + "end": 152, + "message": "A structure must directly or indirectly specialize Objects::Object [validateClassifierDefaultSupertype]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectionUsageType.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "ConnectionUsage must be typed by AssociationStructure; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectorBinarySpecialization.kerml": { + "diagnostics": [ + { + "end": 216, + "message": "unresolved reference `Links::BinaryLink`", + "severity": "Warning", + "stage": "referential", + "start": 199 + } + ], + "status": "unknown without library" + }, + "probes/validateConnectorRelatedFeatures.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "A concrete connector must relate at least two features [validateConnectorRelatedFeatures]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConnectorTypeFeaturing.kerml": { + "diagnostics": [ + { + "end": 202, + "message": "connector end references `x`, which is featured in `A` — no featuring context of the connector reaches it", + "severity": "Warning", + "stage": "semantics", + "start": 198 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml": { + "diagnostics": [ + { + "end": 234, + "message": "A constructor cannot bind a feature more than once [validateConstructorExpressionNoDuplicateFeatureRedefinition]", + "severity": "Error", + "stage": "semantics", + "start": 215 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 254, + "message": "Succession end must have multiplicity 1..1 [validateControlNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 221 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateControlNodeOwningType.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "A control node must be owned by an action [validateControlNodeOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCrossSubsettingCrossedFeature.kerml": { + "diagnostics": [ + { + "end": 230, + "message": "unresolved reference `a`", + "severity": "Warning", + "stage": "referential", + "start": 229 + }, + { + "end": 233, + "message": "unresolved reference `ax`", + "severity": "Warning", + "stage": "referential", + "start": 231 + }, + { + "end": 216, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 215 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateCrossSubsettingCrossingFeature.kerml": { + "diagnostics": [ + { + "end": 182, + "message": "A crossing feature must be an end of a type with at least two ends [validateCrossSubsettingCrossingFeature]", + "severity": "Error", + "stage": "semantics", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.kerml": { + "diagnostics": [ + { + "end": 148, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.subsets.kerml": { + "diagnostics": [ + { + "end": 191, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDataTypeSpecialization.sysml": { + "diagnostics": [ + { + "end": 138, + "message": "A data type cannot specialize a class or association [validateDataTypeSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDecisionNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 134 + }, + { + "end": 199, + "message": "unresolved reference `Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 192 + }, + { + "end": 229, + "message": "Control node has too many incoming successions [validateDecisionNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 228 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDecisionNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 237, + "message": "Succession end must have multiplicity 0..1 [validateDecisionNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 207 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDefinitionVariationMembership.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateDefinitionVariationSpecialization.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 143 + }, + { + "end": 184, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateElementFilterMembershipIsBoolean.kerml": { + "diagnostics": [ + { + "end": 131, + "message": "An element filter must have a Boolean result [validateElementFilterMembershipIsBoolean]", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 148 + }, + { + "end": 201, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 180 + }, + { + "end": 241, + "message": "An element filter must be model-level evaluable [validateElementFilterMembershipIsModelLevelEvaluable]", + "severity": "Error", + "stage": "semantics", + "start": 230 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateEnumerationUsageType.sysml": { + "diagnostics": [ + { + "end": 176, + "message": "EnumerationUsage must be typed by EnumerationDefinition; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateEventOccurrenceUsageReferent.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 135 + }, + { + "end": 163, + "message": "EventOccurrenceUsage must reference a OccurrenceUsage [validateEventOccurrenceUsageReferent]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExhibitStateUsageReference.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "ExhibitStateUsage must reference a StateUsage [validateExhibitStateUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExposeOwningNamespace.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "an `expose` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.kerml": { + "diagnostics": [ + { + "end": 193, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 164 + }, + { + "end": 239, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 235 + }, + { + "end": 380, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 339 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultExpressionMembership.typed.kerml": { + "diagnostics": [ + { + "end": 217, + "message": "Only one owned or inherited result expression is allowed [validateExpressionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 216 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateExpressionResultParameterMembership.kerml": { + "diagnostics": [ + { + "end": 166, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 145 + }, + { + "end": 201, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 180 + }, + { + "end": 130, + "message": "Only one return parameter is allowed [validateExpressionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 129 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainExpressionFeatureConformance.kerml": { + "diagnostics": [ + { + "end": 223, + "message": "A feature-chain expression must select a feature [validateFeatureChainExpressionFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeatureConformance.kerml": { + "diagnostics": [ + { + "end": 212, + "message": "Each chain member must be a feature accessible through the preceding feature [validateFeatureChainingFeatureConformance]", + "severity": "Error", + "stage": "semantics", + "start": 211 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeatureNotOne.kerml": { + "diagnostics": [ + { + "end": 169, + "message": "A feature chain must have at least two features [validateFeatureChainingFeatureNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureChainingFeaturesNotSelf.kerml": { + "diagnostics": [ + { + "end": 198, + "message": "A feature cannot chain through itself [validateFeatureChainingFeaturesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureConstantIsVariable.sysml": { + "diagnostics": [ + { + "end": 144, + "message": "unresolved reference `ScalarValues`", + "severity": "Warning", + "stage": "referential", + "start": 132 + }, + { + "end": 199, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 192 + }, + { + "end": 189, + "message": "Only a variable feature can be constant [validateFeatureConstantIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureCrossFeatureSpecialization.kerml": { + "diagnostics": [ + { + "end": 319, + "message": "unresolved reference `y`", + "severity": "Warning", + "stage": "referential", + "start": 318 + }, + { + "end": 321, + "message": "unresolved reference `b`", + "severity": "Warning", + "stage": "referential", + "start": 320 + }, + { + "end": 304, + "message": "A cross subsetting must chain through an opposite end to a feature [validateCrossSubsettingCrossedFeature]", + "severity": "Error", + "stage": "semantics", + "start": 303 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureCrossFeatureType.kerml": { + "diagnostics": [ + { + "end": 206, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 205 + }, + { + "end": 230, + "message": "A cross feature must have the same types as its end feature [validateFeatureCrossFeatureType]", + "severity": "Error", + "stage": "semantics", + "start": 229 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndFeatureMultiplicity.kerml": { + "diagnostics": [ + { + "end": 163, + "message": "An end feature should have multiplicity 1..1 [validateFeatureEndFeatureMultiplicity]", + "severity": "Warning", + "stage": "semantics", + "start": 162 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndNoDirection.sysml": { + "diagnostics": [ + { + "end": 146, + "message": "expected a definition or usage after prefix, found `in`", + "severity": "Error", + "stage": "parse", + "start": 144 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml": { + "diagnostics": [ + { + "end": 204, + "message": "expected a definition or usage after prefix, found `derived`", + "severity": "Error", + "stage": "parse", + "start": 197 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureHasType.kerml": { + "diagnostics": [ + { + "end": 123, + "message": "Conjugating a classifier does not provide a feature type [validateFeatureHasType]", + "severity": "Error", + "stage": "semantics", + "start": 122 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureIsVariable.kerml": { + "diagnostics": [ + { + "end": 155, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 134 + }, + { + "end": 131, + "message": "A variable feature must be owned by an occurrence type [validateFeatureIsVariable]", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureOwnedCrossSubsetting.kerml": { + "diagnostics": [ + { + "end": 189, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedCrossSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 188 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureOwnedReferenceSubsetting.kerml": { + "diagnostics": [ + { + "end": 168, + "message": "At most one relationship of this kind is allowed [validateFeatureOwnedReferenceSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 167 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeaturePortionNotVariable.kerml": { + "diagnostics": [ + { + "end": 137, + "message": "A portion cannot be variable [validateFeaturePortionNotVariable]", + "severity": "Error", + "stage": "semantics", + "start": 136 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureReferenceExpressionReferentIsFeature.kerml": { + "diagnostics": [ + { + "end": 163, + "message": "unresolved reference `ScalarValues::Boolean`", + "severity": "Warning", + "stage": "referential", + "start": 142 + }, + { + "end": 167, + "message": "A feature reference expression must name a feature [validateFeatureReferenceExpressionReferentIsFeature]", + "severity": "Error", + "stage": "semantics", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueIsInitial.kerml": { + "diagnostics": [ + { + "end": 143, + "message": "An initialized feature must be variable [validateFeatureValueIsInitial]", + "severity": "Error", + "stage": "semantics", + "start": 142 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueOverriding.kerml": { + "diagnostics": [ + { + "end": 146, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 125 + }, + { + "end": 189, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 182 + }, + { + "end": 254, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 253 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFeatureValueOverriding.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 132 + }, + { + "end": 189, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 182 + }, + { + "end": 234, + "message": "Cannot override an inherited binding value; the redefined value must be default [validateFeatureValueOverriding]", + "severity": "Error", + "stage": "semantics", + "start": 233 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowDefinitionConnectionEnds.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "validateFlowDefinitionFlowEnds: a flow definition may not have more than two flow ends", + "severity": "Error", + "stage": "structure", + "start": 181 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndImplicitSubsetting.kerml": { + "diagnostics": [ + { + "end": 201, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 180 + }, + { + "end": 257, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 236 + }, + { + "end": 271, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndImplicitSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 270 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndImplicitSubsetting.sysml": { + "diagnostics": [ + { + "end": 203, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 182 + }, + { + "end": 258, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 237 + }, + { + "end": 272, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndImplicitSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 271 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowEndSubsetting.kerml": { + "diagnostics": [ + { + "end": 160, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 139 + }, + { + "end": 212, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 191 + }, + { + "end": 281, + "message": "A nested flow end must identify an accessible feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 258 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFlowUsageType.sysml": { + "diagnostics": [ + { + "end": 182, + "message": "A flow end must identify a participant's payload feature using dot notation [validateFlowEndSubsetting]", + "severity": "Error", + "stage": "semantics", + "start": 181 + }, + { + "end": 186, + "message": "FlowUsage must be typed by Interaction; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 185 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateForkNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "Control node has too many incoming successions [validateForkNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.kerml": { + "diagnostics": [ + { + "end": 196, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 194 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.specialization.kerml": { + "diagnostics": [ + { + "end": 219, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 218 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultExpressionMembership.sysml": { + "diagnostics": [ + { + "end": 180, + "message": "unresolved reference `ScalarValues::Real`", + "severity": "Warning", + "stage": "referential", + "start": 162 + }, + { + "end": 219, + "message": "unresolved reference `Real`", + "severity": "Warning", + "stage": "referential", + "start": 215 + }, + { + "end": 253, + "message": "Only one owned or inherited result expression is allowed [validateFunctionResultExpressionMembership]", + "severity": "Error", + "stage": "semantics", + "start": 250 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateFunctionResultParameterMembership.kerml": { + "diagnostics": [ + { + "end": 168, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 147 + }, + { + "end": 203, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 182 + }, + { + "end": 132, + "message": "Only one return parameter is allowed [validateFunctionResultParameterMembership]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateImportTopLevelVisibility.kerml": { + "diagnostics": [ + { + "end": 125, + "message": "validateImportTopLevelVisibility: a top-level import must be private", + "severity": "Error", + "stage": "structure", + "start": 95 + }, + { + "end": 121, + "message": "unresolved reference `ScalarValues`", + "severity": "Warning", + "stage": "referential", + "start": 109 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateIncludeUseCaseUsageReference.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "IncludeUseCaseUsage must reference a UseCaseUsage [validateIncludeUseCaseUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInstantiationExpressionInstantiatedType.kerml": { + "diagnostics": [ + { + "end": 158, + "message": "A constructor must instantiate a type [validateInstantiationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceDefinitionEnd.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 155 + }, + { + "end": 172, + "message": "An interface end must be a port [validateInterfaceDefinitionEnd]", + "severity": "Error", + "stage": "semantics", + "start": 171 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceUsageEnd.sysml": { + "diagnostics": [ + { + "end": 253, + "message": "An interface end must be a port [validateInterfaceUsageEnd]", + "severity": "Error", + "stage": "semantics", + "start": 235 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInterfaceUsageType.sysml": { + "diagnostics": [ + { + "end": 197, + "message": "InterfaceUsage must be typed by InterfaceDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 196 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionInstantiatedType.kerml": { + "diagnostics": [ + { + "end": 161, + "message": "An invocation must invoke a behavior or behavioral feature [validateInvocationExpressionInstantiatedType]", + "severity": "Error", + "stage": "semantics", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml": { + "diagnostics": [ + { + "end": 231, + "message": "invocation of `F` binds parameter `x` more than once", + "severity": "Warning", + "stage": "semantics", + "start": 230 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateInvocationExpressionParameterRedefinition.kerml": { + "diagnostics": [ + { + "end": 193, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 172 + }, + { + "end": 225, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 204 + }, + { + "end": 266, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 245 + }, + { + "end": 272, + "message": "unresolved reference `y`", + "severity": "Warning", + "stage": "referential", + "start": 271 + }, + { + "end": 276, + "message": "invocation of `F` names unknown parameter `y`", + "severity": "Warning", + "stage": "semantics", + "start": 275 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateJoinNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 152, + "message": "Control node has too many outgoing successions [validateJoinNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 151 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateLibraryPackageNotStandard.kerml": { + "diagnostics": [ + { + "end": 146, + "message": "A user library package must not be marked standard [validateLibraryPackageNotStandard]", + "severity": "Error", + "stage": "semantics", + "start": 145 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMergeNodeIncomingSuccessions.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "Succession end must have multiplicity 0..1 [validateMergeNodeIncomingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMergeNodeOutgoingSuccessions.sysml": { + "diagnostics": [ + { + "end": 155, + "message": "Control node has too many outgoing successions [validateMergeNodeOutgoingSuccessions]", + "severity": "Error", + "stage": "semantics", + "start": 154 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureAnnotatedElement.kerml": { + "diagnostics": [ + { + "end": 146, + "message": "unresolved reference `Metaobjects::Metaobject`", + "severity": "Warning", + "stage": "referential", + "start": 123 + }, + { + "end": 183, + "message": "unresolved reference `annotatedElement`", + "severity": "Warning", + "stage": "referential", + "start": 167 + }, + { + "end": 200, + "message": "unresolved reference `KerML::Feature`", + "severity": "Warning", + "stage": "referential", + "start": 186 + } + ], + "status": "unknown without library" + }, + "probes/validateMetadataFeatureBody.kerml": { + "diagnostics": [ + { + "end": 155, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 134 + }, + { + "end": 194, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 173 + }, + { + "end": 214, + "message": "A metadata body feature must redefine one feature of its metadata type [validateMetadataFeatureBody]", + "severity": "Error", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureMetadata.kerml": { + "diagnostics": [ + { + "end": 154, + "message": "metadata must be typed by a metadata definition or metaclass; `NotAMetaclass` is a Class", + "severity": "Error", + "stage": "semantics", + "start": 141 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataFeatureMetadataNotAbstract.kerml": { + "diagnostics": [ + { + "end": 149, + "message": "Metadata must have a concrete type [validateMetadataFeatureMetadataNotAbstract]", + "severity": "Error", + "stage": "semantics", + "start": 146 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMetadataUsageType.sysml": { + "diagnostics": [ + { + "end": 185, + "message": "metadata must be typed by a metadata definition or metaclass; `NotMetadata` is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 174 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateMultiplicityRangeResultTypes.kerml": { + "diagnostics": [ + { + "end": 132, + "message": "multiplicity bound must be a Natural number (or `*` for the upper bound)", + "severity": "Error", + "stage": "semantics", + "start": 127 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateNamespaceDistinguishablity.kerml": { + "diagnostics": [ + { + "end": 135, + "message": "the name `A` is already used by an earlier member of the same namespace whose metaclass is not distinguishable from this member", + "severity": "Error", + "stage": "structure", + "start": 134 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateObjectiveMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "validateObjectiveMembershipOwningType: an `objective` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIndividualDefinition.sysml": { + "diagnostics": [ + { + "end": 196, + "message": "At most one individual definition may type an occurrence [validateOccurrenceUsageIndividualDefinition]", + "severity": "Error", + "stage": "semantics", + "start": 195 + }, + { + "end": 196, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 195 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIndividualUsage.sysml": { + "diagnostics": [ + { + "end": 167, + "message": "An individual usage must be typed by one individual definition [validateOccurrenceUsageIndividualUsage]", + "severity": "Error", + "stage": "semantics", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageIsPortion.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "A snapshot or timeslice must be owned by an occurrence definition or usage [validateOccurrenceUsageIsPortion]", + "severity": "Error", + "stage": "semantics", + "start": 152 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOccurrenceUsageType.sysml": { + "diagnostics": [ + { + "end": 171, + "message": "OccurrenceUsage must be typed by Class; the declared type is a AttributeDefinition", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOperatorExpressionBracketOperator.kerml": { + "diagnostics": [ + { + "end": 146, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 125 + }, + { + "end": 188, + "message": "Square brackets do not index a sequence; use #(index) [validateOperatorExpressionBracketOperator]", + "severity": "Warning", + "stage": "semantics", + "start": 187 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOperatorExpressionCastConformance.kerml": { + "diagnostics": [ + { + "end": 185, + "message": "unresolved reference `ScalarValues::String`", + "severity": "Warning", + "stage": "referential", + "start": 165 + }, + { + "end": 227, + "message": "unresolved reference `ScalarValues::Integer`", + "severity": "Warning", + "stage": "referential", + "start": 206 + } + ], + "status": "unknown without library" + }, + "probes/validateOperatorExpressionQuantity.sysml": { + "diagnostics": [ + { + "end": 174, + "message": "A quantity unit must be a measurement reference [validateOperatorExpressionQuantity]", + "severity": "Warning", + "stage": "semantics", + "start": 173 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedDifferencingNotOne.kerml": { + "diagnostics": [ + { + "end": 127, + "message": "A type operation must have zero or at least two operands [validateOwnedDifferencingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedIntersectingNotOne.kerml": { + "diagnostics": [ + { + "end": 127, + "message": "A type operation must have zero or at least two operands [validateOwnedIntersectingNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateOwnedUnioningNotOne.kerml": { + "diagnostics": [ + { + "end": 119, + "message": "A type operation must have zero or at least two operands [validateOwnedUnioningNotOne]", + "severity": "Error", + "stage": "semantics", + "start": 118 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePerformActionUsageReference.sysml": { + "diagnostics": [ + { + "end": 150, + "message": "PerformActionUsage must reference a ActionUsage [validatePerformActionUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 140 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortDefinitionOwnedUsagesNotComposite.sysml": { + "diagnostics": [ + { + "end": 192, + "message": "A non-port usage owned by a port must be referential [validatePortDefinitionOwnedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 191 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageIsReference.sysml": { + "diagnostics": [ + { + "end": 169, + "message": "A port nested in a port must be referential [validatePortUsageIsReference]", + "severity": "Error", + "stage": "semantics", + "start": 168 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageNestedUsagesNotComposite.sysml": { + "diagnostics": [ + { + "end": 209, + "message": "A non-port usage owned by a port must be referential [validatePortUsageNestedUsagesNotComposite]", + "severity": "Error", + "stage": "semantics", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "probes/validatePortUsageType.sysml": { + "diagnostics": [ + { + "end": 127, + "message": "PortUsage must be typed by PortDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 126 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionDirectionConformance.kerml": { + "diagnostics": [ + { + "end": 213, + "message": "A redefining feature must have a compatible direction [validateRedefinitionDirectionConformance]", + "severity": "Error", + "stage": "semantics", + "start": 212 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionEndConformance.kerml": { + "diagnostics": [ + { + "end": 221, + "message": "A feature redefining an end must itself be an end [validateRedefinitionEndConformance]", + "severity": "Error", + "stage": "semantics", + "start": 220 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionFeaturingTypes.kerml": { + "diagnostics": [ + { + "end": 156, + "message": "A package-level feature cannot redefine another package-level feature [validateRedefinitionFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRedefinitionMultiplicityConformance.kerml": { + "diagnostics": [ + { + "end": 229, + "message": "redefining multiplicity [0..2] is not within the redefined feature's [1..2]", + "severity": "Warning", + "stage": "semantics", + "start": 223 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRenderingUsageType.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "RenderingUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementConstraintMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 202, + "message": "a `require` constraint member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 177 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementDefinitionOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 175, + "message": "validateRequirementDefinitionOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 161 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementDefinitionSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 184, + "message": "validateRequirementDefinitionSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageOnlyOneSubject.sysml": { + "diagnostics": [ + { + "end": 189, + "message": "validateRequirementUsageOnlyOneSubject: a requirement or case may own at most one subject", + "severity": "Error", + "stage": "structure", + "start": 175 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageSubjectParameterPosition.sysml": { + "diagnostics": [ + { + "end": 198, + "message": "validateRequirementUsageSubjectParameterPosition: the subject parameter must be the first input", + "severity": "Error", + "stage": "structure", + "start": 184 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementUsageType.sysml": { + "diagnostics": [ + { + "end": 191, + "message": "RequirementUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 189 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateRequirementVerificationMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 228, + "message": "A requirement verification must be in the objective of a verification case [validateRequirementVerificationMembershipOwningType]", + "severity": "Error", + "stage": "semantics", + "start": 227 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateReturnParameterMembershipOwningType.kerml": { + "diagnostics": [ + { + "end": 187, + "message": "a `return` parameter member is not allowed in a type body", + "severity": "Error", + "stage": "structure", + "start": 166 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSatisfyRequirementUsageReference.sysml": { + "diagnostics": [ + { + "end": 165, + "message": "SatisfyRequirementUsage must reference a RequirementUsage [validateSatisfyRequirementUsageReference]", + "severity": "Error", + "stage": "semantics", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSendActionUsagePayloadArgument.sysml": { + "diagnostics": [ + { + "end": 218, + "message": "A send used as a state subaction or transition effect must supply a payload [validateSendActionUsagePayloadArgument]", + "severity": "Error", + "stage": "semantics", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSendActionUsageReceiver.sysml": { + "diagnostics": [ + { + "end": 214, + "message": "Sending through a port should use 'via' [validateSendActionUsageReceiver]", + "severity": "Warning", + "stage": "semantics", + "start": 213 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSpecializationSpecificNotConjugated.kerml": { + "diagnostics": [ + { + "end": 195, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 156 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSpecializationSpecificNotConjugated.subset.kerml": { + "diagnostics": [ + { + "end": 224, + "message": "A conjugated type cannot be the specific type of a specialization [validateSpecializationSpecificNotConjugated]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStakeholderMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 220, + "message": "a `stakeholder` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 202 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateDefinitionParallelSubactions.sysml": { + "diagnostics": [ + { + "end": 151, + "message": "A parallel state cannot own successions or transitions [validateStateDefinitionParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 150 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateDefinitionSubactionKind.sysml": { + "diagnostics": [ + { + "end": 132, + "message": "A state may have at most one subaction of each kind [validateStateDefinitionSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateSubactionMembershioOwningType.sysml": { + "diagnostics": [ + { + "end": 208, + "message": "an `entry` action member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageParallelSubactions.sysml": { + "diagnostics": [ + { + "end": 156, + "message": "A parallel state cannot own successions or transitions [validateStateUsageParallelSubactions]", + "severity": "Error", + "stage": "semantics", + "start": 155 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageSubactionKind.sysml": { + "diagnostics": [ + { + "end": 137, + "message": "A state may have at most one subaction of each kind [validateStateUsageSubactionKind]", + "severity": "Error", + "stage": "semantics", + "start": 136 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStateUsageType.sysml": { + "diagnostics": [ + { + "end": 131, + "message": "StateUsage must be typed by StateDefinition; the declared type is a PartDefinition", + "severity": "Error", + "stage": "semantics", + "start": 130 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateStructureSpecialization.kerml": { + "diagnostics": [ + { + "end": 138, + "message": "A structure cannot specialize a behavior [validateStructureSpecialization]", + "severity": "Error", + "stage": "semantics", + "start": 137 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubjectMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 222, + "message": "validateSubjectMembershipOwningType: a `subject` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 208 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingConstantConformance.kerml": { + "diagnostics": [ + { + "end": 241, + "message": "unresolved reference `Occurrences::Occurrence`", + "severity": "Warning", + "stage": "referential", + "start": 218 + }, + { + "end": 308, + "message": "A variable subset of a constant feature must be constant [validateSubsettingConstantConformance]", + "severity": "Error", + "stage": "semantics", + "start": 307 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingFeaturingTypes.kerml": { + "diagnostics": [ + { + "end": 194, + "message": "A subsetted feature must be accessible in the subsetting feature's context [validateSubsettingFeaturingTypes]", + "severity": "Error", + "stage": "semantics", + "start": 190 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingMultiplicityConformance.kerml": { + "diagnostics": [ + { + "end": 237, + "message": "subsetting multiplicity upper bound 5 exceeds the subsetted feature's upper bound 2", + "severity": "Warning", + "stage": "semantics", + "start": 231 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateSubsettingUniquenessConformance.kerml": { + "diagnostics": [ + { + "end": 260, + "message": "A subset of a unique feature must be unique [validateSubsettingUniquenessConformance]", + "severity": "Error", + "stage": "semantics", + "start": 259 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionFeatureMembershipGuardExpression.sysml": { + "diagnostics": [ + { + "end": 188, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 183 + }, + { + "end": 250, + "message": "A transition guard must have a Boolean result with multiplicity 1..1 [validateTransitionFeatureMembershipGuardExpression]", + "severity": "Error", + "stage": "semantics", + "start": 249 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionUsageSuccession.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "A transition's succession must target an action usage [validateTransitionUsageSuccession]", + "severity": "Error", + "stage": "semantics", + "start": 214 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTransitionUsageTriggerActions.sysml": { + "diagnostics": [ + { + "end": 232, + "message": "A triggered transition must have a state usage as its source [validateTransitionUsageTriggerActions]", + "severity": "Error", + "stage": "semantics", + "start": 199 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTriggerInvocationActionAfterArgument.sysml": { + "diagnostics": [ + { + "end": 305, + "message": "A 'after' trigger argument must conform to ISQ::DurationValue [validateTriggerInvocationActionAfterArgument]", + "severity": "Error", + "stage": "semantics", + "start": 304 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTriggerInvocationActionAtArgument.sysml": { + "diagnostics": [ + { + "end": 256, + "message": "unresolved reference `ISQ`", + "severity": "Warning", + "stage": "referential", + "start": 253 + }, + { + "end": 306, + "message": "unresolved reference `DurationValue`", + "severity": "Warning", + "stage": "referential", + "start": 293 + } + ], + "status": "unknown without library" + }, + "probes/validateTriggerInvocationActionWhenArgument.sysml": { + "diagnostics": [ + { + "end": 241, + "message": "unresolved reference `ScalarValues`", + "severity": "Warning", + "stage": "referential", + "start": 229 + }, + { + "end": 285, + "message": "unresolved reference `Integer`", + "severity": "Warning", + "stage": "referential", + "start": 278 + } + ], + "status": "unknown without library" + }, + "probes/validateTypeAtMostOneConjugator.kerml": { + "diagnostics": [ + { + "end": 159, + "message": "expected `;` or `{`, found `~`", + "severity": "Error", + "stage": "parse", + "start": 158 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeDifferencingTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 133, + "message": "A type operation cannot name its own type as an operand [validateTypeDifferencingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 132 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeIntersectingTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 132, + "message": "A type operation cannot name its own type as an operand [validateTypeIntersectingTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 131 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeOwnedMultiplicity.kerml": { + "diagnostics": [ + { + "end": 113, + "message": "Only one multiplicity is allowed [validateTypeOwnedMultiplicity]", + "severity": "Error", + "stage": "semantics", + "start": 112 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateTypeUnioningTypesNotSelf.kerml": { + "diagnostics": [ + { + "end": 124, + "message": "A type operation cannot name its own type as an operand [validateTypeUnioningTypesNotSelf]", + "severity": "Error", + "stage": "semantics", + "start": 123 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUsageType.sysml": { + "diagnostics": [ + { + "end": 142, + "message": "unresolved reference `Base::things`", + "severity": "Warning", + "stage": "referential", + "start": 130 + } + ], + "status": "unknown without library" + }, + "probes/validateUsageVariationMembership.sysml": { + "diagnostics": [ + { + "end": 153, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 144 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUsageVariationSpecialization.sysml": { + "diagnostics": [ + { + "end": 159, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 150 + }, + { + "end": 191, + "message": "expected a definition or usage after prefix, found `variation`", + "severity": "Error", + "stage": "parse", + "start": 182 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateUseCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 172, + "message": "UseCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 170 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateVariationMembershipOwningNamespace.sysml": { + "diagnostics": [ + { + "end": 162, + "message": "a `variant` member is only allowed in the body of a `variation` definition or usage", + "severity": "Error", + "stage": "structure", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateVerificationCaseUsageType.sysml": { + "diagnostics": [ + { + "end": 211, + "message": "VerificationCaseUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 209 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewDefinitionOnlyOnvViewRendering.sysml": { + "diagnostics": [ + { + "end": 166, + "message": "A view may have at most one rendering [validateViewDefinitionOnlyOnvViewRendering]", + "severity": "Error", + "stage": "semantics", + "start": 165 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewRenderingMembershipOwningType.sysml": { + "diagnostics": [ + { + "end": 200, + "message": "a `render` member is not allowed in a definition or usage body", + "severity": "Error", + "stage": "structure", + "start": 185 + }, + { + "end": 199, + "message": "unresolved reference `asTable`", + "severity": "Warning", + "stage": "referential", + "start": 192 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewUsageOnlyOneRendering.sysml": { + "diagnostics": [ + { + "end": 154, + "message": "A view may have at most one rendering [validateViewUsageOnlyOneRendering]", + "severity": "Error", + "stage": "semantics", + "start": 153 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewUsageType.sysml": { + "diagnostics": [ + { + "end": 149, + "message": "ViewUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 147 + } + ], + "status": "diagnostic baseline" + }, + "probes/validateViewpointUsageType.sysml": { + "diagnostics": [ + { + "end": 179, + "message": "ViewpointUsage must have exactly one non-redundant type; found 2", + "severity": "Error", + "stage": "semantics", + "start": 177 + } + ], + "status": "diagnostic baseline" + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative-contracts.json b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative-contracts.json new file mode 100644 index 0000000..5a2e627 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative-contracts.json @@ -0,0 +1,394 @@ +{ + "contracts": [ + { + "fixture": "negative/semantic/k17-crosses-not-through-opposite-end.kerml", + "rule": "validateCrossSubsettingCrossedFeature", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "crosses a", + "to": "" + }, + { + "fixture": "negative/semantic/k19-cross-feature-not-specializing.kerml", + "rule": "validateFeatureCrossFeatureSpecialization", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "feature y : A;", + "to": "feature y : A subsets x;" + }, + { + "fixture": "negative/semantic/k27-connector-feature-outside-featuring-type.kerml", + "rule": "validateConnectorTypeFeaturing", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class B {", + "to": "class B specializes A {" + }, + { + "fixture": "negative/semantic/k37-multiplicity-bound-not-natural.kerml", + "rule": "validateMultiplicityRangeResultTypes", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "feature n : C;", + "to": "feature n : ScalarValues::Natural;" + }, + { + "fixture": "negative/semantic/k38-flow-end-without-dot-notation.kerml", + "rule": "validateFlowEndSubsetting", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "flow from x to y;", + "to": "flow from x.o to y.o;", + "extra_from": "class T;", + "extra_to": "class T { feature o : T; }" + }, + { + "fixture": "negative/semantic/k50-inline-cross-feature-also-crosses.kerml", + "rule": "feature-cross-feature-single", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "end [1] feature x", + "to": "end feature x" + }, + { + "fixture": "negative/semantic/k53-boolean-expression-subsets-datatype.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "datatype D;", + "to": "feature D;" + }, + { + "fixture": "negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml", + "rule": "validateFeatureCrossFeatureType", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "x1 : Sub1", + "to": "x1 : C1" + }, + { + "fixture": "negative/semantic/k55-subtype-specific-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k56-subtype-general-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k57-subclassifier-subclassifier-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "feature f;", + "to": "class f;" + }, + { + "fixture": "negative/semantic/k59-typing-typed-feature-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "feature Q;" + }, + { + "fixture": "negative/semantic/k60-typing-typed-feature-is-class.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class C;", + "to": "feature C;" + }, + { + "fixture": "negative/semantic/k61-typing-type-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k62-subset-subsetting-feature-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "feature Q;" + }, + { + "fixture": "negative/semantic/k63-subset-subsetted-feature-is-class.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class C;", + "to": "feature C;" + }, + { + "fixture": "negative/semantic/k64-redefinition-redefining-feature-is-class.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class C;", + "to": "feature C;" + }, + { + "fixture": "negative/semantic/k65-redefinition-redefined-feature-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "feature Q;" + }, + { + "fixture": "negative/semantic/k66-conjugate-conjugated-type-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k67-conjugate-original-type-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k68-inverse-feature-inverted-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "feature Q;" + }, + { + "fixture": "negative/semantic/k69-inverse-inverting-feature-is-class.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class C;", + "to": "feature C;" + }, + { + "fixture": "negative/semantic/k70-disjoint-type-disjoined-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k71-disjoint-disjoining-type-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/k72-featuring-feature-of-type-is-class.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "class C;", + "to": "feature C;" + }, + { + "fixture": "negative/semantic/k73-featuring-featuring-type-is-package.kerml", + "rule": "relationship-endpoint-metaclass", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "package Q;", + "to": "class Q;" + }, + { + "fixture": "negative/semantic/s37-variation-usage-member-not-variant.sysml", + "rule": "validateUsageVariationMembership", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "part b : P;", + "to": "variant part b : P;" + }, + { + "fixture": "negative/semantic/s47-enumeration-specializes-enumeration.sysml", + "rule": "validateDefinitionVariationSpecialization", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "enum def F :> E", + "to": "enum def F" + }, + { + "fixture": "negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml", + "rule": "validateEnumerationUsageType", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "a = { 1 + 2 };", + "to": "a;" + }, + { + "fixture": "negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml", + "rule": "validateFeatureCrossFeatureType", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "x1 : Sub1", + "to": "x1 : A" + }, + { + "fixture": "negative/semantic/s89-case-def-inherits-two-objectives.sysml", + "rule": "validateCaseDefinitionOnlyOneObjective", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": ":> A, B", + "to": ":> A" + }, + { + "fixture": "negative/semantic/s90-requirement-def-inherits-two-subjects.sysml", + "rule": "validateRequirementDefinitionOnlyOneSubject", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": ":> A, B", + "to": ":> A" + }, + { + "fixture": "negative/semantic/s91-case-references-second-objective.sysml", + "rule": "validateCaseUsageOnlyOneObjective", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "case c : A ::> b", + "to": "case c : A" + }, + { + "fixture": "negative/semantic/s92-requirement-references-second-subject.sysml", + "rule": "validateRequirementUsageOnlyOneSubject", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "requirement c : A ::> b", + "to": "requirement c : A" + }, + { + "fixture": "negative/semantic/send-constructor-non-type.sysml", + "rule": "validateInstantiationExpressionInstantiatedType", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "new Signals()", + "to": "new Signals::Sig()" + }, + { + "fixture": "negative/semantic/send-payload-non-behavior.sysml", + "rule": "validateInvocationExpressionInstantiatedType", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "attribute def Sig;", + "to": "calc def Sig;" + }, + { + "fixture": "negative/xpect/p09-variation-member-not-variant.sysml", + "rule": "validateDefinitionVariationMembership", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "attribute a2;", + "to": "variant attribute a2;" + }, + { + "fixture": "negative/xpect/p10-variation-specializes-variation.sysml", + "rule": "validateDefinitionVariationSpecialization", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "AttributeChoices1 :> AttributeChoices", + "to": "AttributeChoices1" + }, + { + "fixture": "negative/xpect/p11-metadata-body-not-evaluable.sysml", + "rule": "validateMetadataFeatureBody", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "~3", + "to": "3" + }, + { + "fixture": "negative/xpect/p12-filter-integer-condition.sysml", + "rule": "validateElementFilterMembershipIsBoolean", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "filter 1 + 2 * 3;", + "to": "filter 1 + 2 * 3 > 0;" + }, + { + "fixture": "negative/xpect/p18-enum-value-typed-outside-enumeration.sysml", + "rule": "validateEnumerationUsageType", + "severity": "Error", + "authority": "The pinned official training model Enumeration Definitions-2.sysml uses the identical enum-over-Real with named literal values (GradePoints). This pilot-negative expectation conflicts with the supported enumeration-restriction idiom.", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "a = 4.0;\n b = 3;", + "to": "a;\n b;", + "verdict": "accepted" + }, + { + "fixture": "negative/xpect/p32-redefinition-same-featuring-type.sysml", + "rule": "validateRedefinitionFeaturingTypes", + "severity": "Error", + "authority": "pinned KerML/SysML reference property types or validator rule; see preserved fixture source citation", + "prerequisites": "resolved relationship endpoints and effective members; unresolved prerequisites remain unknown", + "from": "part smallEng : Engine redefines eng1;", + "to": "part smallEng : Engine;" + } + ] +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x01-initial-state-marker.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x01-initial-state-marker.sysml new file mode 100644 index 0000000..9e787cb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x01-initial-state-marker.sysml @@ -0,0 +1,8 @@ +// Invalid: 'initial' is an OpenSysML invention; the pinned StateBodyItem has no such member (SysML.xtext StateBodyItem). +package X01InitialStateMarker { + state def S { + initial start; + state idle; + transition start then idle; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x02-choice-pseudostate.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x02-choice-pseudostate.sysml new file mode 100644 index 0000000..85d1821 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x02-choice-pseudostate.sysml @@ -0,0 +1,7 @@ +// Invalid: 'choice' is an OpenSysML invention; the pinned StateBodyItem has no pseudostates (SysML.xtext StateBodyItem). +package X02ChoicePseudostate { + state def S { + state idle; + choice evaluate; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x03-junction-pseudostate.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x03-junction-pseudostate.sysml new file mode 100644 index 0000000..3bfbbf3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x03-junction-pseudostate.sysml @@ -0,0 +1,7 @@ +// Invalid: 'junction' is an OpenSysML invention; the pinned StateBodyItem has no pseudostates (SysML.xtext StateBodyItem). +package X03JunctionPseudostate { + state def S { + state receiving; + junction route; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x04-orthogonal-region.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x04-orthogonal-region.sysml new file mode 100644 index 0000000..64f5942 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x04-orthogonal-region.sysml @@ -0,0 +1,11 @@ +// Invalid: 'region' is an OpenSysML invention; the pinned grammar spells concurrency 'state ... parallel' (SysML.xtext StateDefBody). +package X04OrthogonalRegion { + state def S { + region r1 { + state a; + } + region r2 { + state b; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x05-defer-member.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x05-defer-member.sysml new file mode 100644 index 0000000..3727339 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x05-defer-member.sysml @@ -0,0 +1,8 @@ +// Invalid: 'defer' is an OpenSysML invention; the pinned StateBodyItem has no event deferral (SysML.xtext StateBodyItem). +package X05DeferMember { + state def S { + state idle { + defer Ping; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x06-history-member.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x06-history-member.sysml new file mode 100644 index 0000000..0d6e223 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x06-history-member.sysml @@ -0,0 +1,7 @@ +// Invalid: 'history' is an OpenSysML invention; the pinned StateBodyItem has no history pseudostate (SysML.xtext StateBodyItem). +package X06HistoryMember { + state def S { + state idle; + history resume; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x07-transition-to.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x07-transition-to.sysml new file mode 100644 index 0000000..301ccb4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x07-transition-to.sysml @@ -0,0 +1,8 @@ +// Invalid: TransitionUsage connects with 'first ... then', never 'to' (SysML.xtext TransitionUsage). +package X07TransitionTo { + state def S { + state idle; + state busy; + transition idle to busy; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x08-require-outside-requirement-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x08-require-outside-requirement-body.sysml new file mode 100644 index 0000000..0825b39 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/extensions/x08-require-outside-requirement-body.sysml @@ -0,0 +1,6 @@ +// Invalid: Only requirements can have assumed or required constraints; 'require' in a part def body is an OpenSysML extension (SysML 7.20 Requirements; pilot validateRequirementConstraintMembershipOwningType, enforced by SysML.xtext RequirementBodyItem). +package X08RequireOutsideRequirementBody { + part def System { + require constraint { true } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g01-unclosed-package-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g01-unclosed-package-body.sysml new file mode 100644 index 0000000..159c25f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g01-unclosed-package-body.sysml @@ -0,0 +1,3 @@ +// Invalid: PackageBody requires a closing '}' (SysML.xtext PackageBody). +package G01UnclosedPackageBody { + part def D; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g02-import-without-visibility.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g02-import-without-visibility.sysml new file mode 100644 index 0000000..6e7df64 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g02-import-without-visibility.sysml @@ -0,0 +1,7 @@ +// Invalid: ImportPrefix requires an explicit visibility keyword before 'import' (SysML.xtext ImportPrefix). +package G02ImportWithoutVisibility { + package Q { + part def D; + } + import Q::*; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g03-alias-without-for.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g03-alias-without-for.sysml new file mode 100644 index 0000000..5a0559d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g03-alias-without-for.sysml @@ -0,0 +1,5 @@ +// Invalid: AliasMember requires 'for' and a target element (SysML.xtext AliasMember). +package G03AliasWithoutFor { + part def D; + alias A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g04-specialization-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g04-specialization-without-target.sysml new file mode 100644 index 0000000..2baee15 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g04-specialization-without-target.sysml @@ -0,0 +1,4 @@ +// Invalid: OwnedSubclassification requires a superclassifier after ':>' (SysML.xtext OwnedSubclassification). +package G04SpecializationWithoutTarget { + part def A :> ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g05-typing-without-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g05-typing-without-type.sysml new file mode 100644 index 0000000..59c4218 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g05-typing-without-type.sysml @@ -0,0 +1,4 @@ +// Invalid: OwnedFeatureTyping requires a type after ':' (SysML.xtext TypedBy/OwnedFeatureTyping). +package G05TypingWithoutType { + part p : ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g06-definition-with-multiplicity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g06-definition-with-multiplicity.sysml new file mode 100644 index 0000000..9427501 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g06-definition-with-multiplicity.sysml @@ -0,0 +1,4 @@ +// Invalid: DefinitionDeclaration admits no multiplicity; '[..]' belongs to FeatureDeclaration (SysML.xtext DefinitionDeclaration). +package G06DefinitionWithMultiplicity { + part def P [3]; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g07-entry-outside-state-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g07-entry-outside-state-body.sysml new file mode 100644 index 0000000..0d2e7b0 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g07-entry-outside-state-body.sysml @@ -0,0 +1,6 @@ +// Invalid: EntryActionMember is a StateBodyItem; a part def body admits no 'entry' (SysML.xtext StateBodyItem; pilot validateStateSubactionMembershioOwningType). +package G07EntryOutsideStateBody { + part def P { + entry a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g08-do-outside-state-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g08-do-outside-state-body.sysml new file mode 100644 index 0000000..8a6916f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g08-do-outside-state-body.sysml @@ -0,0 +1,6 @@ +// Invalid: DoActionMember is a StateBodyItem; a part def body admits no 'do' (SysML.xtext StateBodyItem; pilot validateStateSubactionMembershioOwningType). +package G08DoOutsideStateBody { + part def P { + do a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g09-value-without-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g09-value-without-expression.sysml new file mode 100644 index 0000000..5721d9c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g09-value-without-expression.sysml @@ -0,0 +1,4 @@ +// Invalid: ValuePart requires an expression after '=' (SysML.xtext ValuePart/OwnedExpression). +package G09ValueWithoutExpression { + attribute a = ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g10-operator-without-operand.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g10-operator-without-operand.sysml new file mode 100644 index 0000000..de2a79e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g10-operator-without-operand.sysml @@ -0,0 +1,4 @@ +// Invalid: AdditiveExpression requires a right operand after '+' (KerMLExpressions.xtext AdditiveExpression). +package G10OperatorWithoutOperand { + attribute a = 1 + ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g11-assignment-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g11-assignment-without-target.sysml new file mode 100644 index 0000000..167ab20 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g11-assignment-without-target.sysml @@ -0,0 +1,6 @@ +// Invalid: AssignmentNode requires a target and value after 'assign' (SysML.xtext AssignmentNode). +package G11AssignmentWithoutTarget { + action def A { + assign ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g12-unterminated-block-comment.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g12-unterminated-block-comment.sysml new file mode 100644 index 0000000..63602e8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g12-unterminated-block-comment.sysml @@ -0,0 +1,5 @@ +// Invalid: ML_COMMENT requires a closing '*/' (SysML.xtext terminal ML_COMMENT). +package G12UnterminatedBlockComment { + part def P; + /* unterminated +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g13-entry-then-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g13-entry-then-without-target.sysml new file mode 100644 index 0000000..81da8a1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g13-entry-then-without-target.sysml @@ -0,0 +1,6 @@ +// Invalid: EntryTransitionMember 'then' requires a transition target (SysML.xtext EntryTransitionMember). +package G13EntryThenWithoutTarget { + state def S { + entry then ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g14-connect-without-to.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g14-connect-without-to.sysml new file mode 100644 index 0000000..8441893 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g14-connect-without-to.sysml @@ -0,0 +1,8 @@ +// Invalid: BinaryConnectorPart requires 'to' between the two ends (SysML.xtext BinaryConnectorPart). +package G14ConnectWithoutTo { + part def P { + part a; + part b; + connect a b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g15-keyword-as-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g15-keyword-as-name.sysml new file mode 100644 index 0000000..fdccb16 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g15-keyword-as-name.sysml @@ -0,0 +1,4 @@ +// Invalid: 'part' is a reserved keyword, not a NAME token (SysML.xtext terminal ID / PartKeyword). +package G15KeywordAsName { + part def part; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g16-expose-without-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g16-expose-without-name.sysml new file mode 100644 index 0000000..0b69744 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g16-expose-without-name.sysml @@ -0,0 +1,7 @@ +// Invalid: NamespaceExpose requires an imported namespace or filter package after the expose prefix (SysML.xtext:2383 NamespaceExpose). +package G16ExposeWithoutName { + part def Engine; + view def V { + expose ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g17-render-without-usage.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g17-render-without-usage.sysml new file mode 100644 index 0000000..f7e5684 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g17-render-without-usage.sysml @@ -0,0 +1,6 @@ +// Invalid: ViewRenderingMember requires a rendering usage after the render keyword (SysML.xtext:2335 ViewRenderingMember). +package G17RenderWithoutUsage { + view def V { + render ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g18-require-without-constraint.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g18-require-without-constraint.sysml new file mode 100644 index 0000000..9dc243e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g18-require-without-constraint.sysml @@ -0,0 +1,6 @@ +// Invalid: RequirementConstraintMember requires a constraint usage after the require keyword (SysML.xtext:2057 RequirementConstraintMember). +package G18RequireWithoutConstraint { + requirement def R { + require ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g19-frame-without-concern.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g19-frame-without-concern.sysml new file mode 100644 index 0000000..65063cb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g19-frame-without-concern.sysml @@ -0,0 +1,6 @@ +// Invalid: FramedConcernMember requires a concern usage after the frame keyword (SysML.xtext:2073 FramedConcernMember). +package G19FrameWithoutConcern { + requirement def R { + frame ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g20-include-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g20-include-without-target.sysml new file mode 100644 index 0000000..7871524 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g20-include-without-target.sysml @@ -0,0 +1,6 @@ +// Invalid: IncludeUseCaseUsage requires a referenced use case or a use case declaration after include (SysML.xtext:2300 IncludeUseCaseUsage). +package G20IncludeWithoutTarget { + use case def U { + include ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g21-filter-without-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g21-filter-without-expression.sysml new file mode 100644 index 0000000..e03f42a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g21-filter-without-expression.sysml @@ -0,0 +1,4 @@ +// Invalid: ElementFilterMember requires an owned expression between filter and the semicolon (SysML.xtext:229 ElementFilterMember). +package G21FilterWithoutExpression { + filter ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g22-dependency-without-to.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g22-dependency-without-to.sysml new file mode 100644 index 0000000..712296e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g22-dependency-without-to.sysml @@ -0,0 +1,6 @@ +// Invalid: Dependency requires a to clause naming its supplier (SysML.xtext:55 Dependency). +package G22DependencyWithoutTo { + part def A; + part def B; + dependency d from A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g23-rep-without-language.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g23-rep-without-language.sysml new file mode 100644 index 0000000..e0d2188 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g23-rep-without-language.sysml @@ -0,0 +1,4 @@ +// Invalid: TextualRepresentation requires a language string before its comment body (SysML.xtext:103 TextualRepresentation). +package G23RepWithoutLanguage { + rep inOCL /* self.x > 0 */ +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g24-alias-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g24-alias-without-target.sysml new file mode 100644 index 0000000..1abef74 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g24-alias-without-target.sysml @@ -0,0 +1,5 @@ +// Invalid: AliasMember requires an element reference after for (SysML.xtext:234 AliasMember). +package G24AliasWithoutTarget { + part def D; + alias A for ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g25-library-without-package.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g25-library-without-package.sysml new file mode 100644 index 0000000..30e94c7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g25-library-without-package.sysml @@ -0,0 +1,2 @@ +// Invalid: LibraryPackage requires a package declaration after the library keyword (SysML.xtext:188 LibraryPackage). +library ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g26-multiplicity-open-range.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g26-multiplicity-open-range.sysml new file mode 100644 index 0000000..2366a08 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g26-multiplicity-open-range.sysml @@ -0,0 +1,5 @@ +// Invalid: MultiplicityRange requires a bound expression after .. (SysML.xtext:478 MultiplicityRange). +package G26MultiplicityOpenRange { + part def D; + part p : D [1..]; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g27-bind-without-right-end.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g27-bind-without-right-end.sysml new file mode 100644 index 0000000..27ba5a5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g27-bind-without-right-end.sysml @@ -0,0 +1,8 @@ +// Invalid: BindingConnectorAsUsage requires a connector end after = (SysML.xtext:1020 BindingConnectorAsUsage). +package G27BindWithoutRightEnd { + part def D { + attribute a; + attribute b; + binding bb bind a = ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g28-succession-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g28-succession-without-target.sysml new file mode 100644 index 0000000..ced91f6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g28-succession-without-target.sysml @@ -0,0 +1,8 @@ +// Invalid: SuccessionAsUsage requires a connector end after then (SysML.xtext:1033 SuccessionAsUsage). +package G28SuccessionWithoutTarget { + action def A { + action a1; + action a2; + succession s first a1 then ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g29-flow-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g29-flow-without-target.sysml new file mode 100644 index 0000000..73ea306 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g29-flow-without-target.sysml @@ -0,0 +1,8 @@ +// Invalid: FlowUsage requires a flow declaration with both ends (SysML.xtext:1269 FlowUsage, :1289 FlowDeclaration). +package G29FlowWithoutTarget { + part def D { + attribute a; + attribute b; + flow f from a to ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g30-message-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g30-message-without-target.sysml new file mode 100644 index 0000000..78df0d8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g30-message-without-target.sysml @@ -0,0 +1,8 @@ +// Invalid: Message requires a message declaration with both ends (SysML.xtext:1245 Message). +package G30MessageWithoutTarget { + part def D { + event occurrence a; + event occurrence b; + message m from a to ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g31-allocate-without-to.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g31-allocate-without-to.sysml new file mode 100644 index 0000000..ef446f3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g31-allocate-without-to.sysml @@ -0,0 +1,8 @@ +// Invalid: AllocationUsage requires a to clause naming the allocation target (SysML.xtext:1214 AllocationUsage, :1218 AllocationUsageDeclaration). +package G31AllocateWithoutTo { + part def D { + part a; + part b; + allocate a ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g32-if-without-condition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g32-if-without-condition.sysml new file mode 100644 index 0000000..96a93e5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g32-if-without-condition.sysml @@ -0,0 +1,6 @@ +// Invalid: IfNode requires an expression parameter after if (SysML.xtext:1596 IfNode). +package G32IfWithoutCondition { + action def A { + if { } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g33-while-without-condition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g33-while-without-condition.sysml new file mode 100644 index 0000000..f5baa76 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g33-while-without-condition.sysml @@ -0,0 +1,6 @@ +// Invalid: WhileLoopNode requires an expression parameter after while (SysML.xtext:1615 WhileLoopNode). +package G33WhileWithoutCondition { + action def A { + while { } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g34-for-without-in.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g34-for-without-in.sysml new file mode 100644 index 0000000..ebc4b5b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g34-for-without-in.sysml @@ -0,0 +1,6 @@ +// Invalid: ForLoopNode requires an in clause naming the sequence (SysML.xtext:1624 ForLoopNode). +package G34ForWithoutIn { + action def A { + for x { } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g35-accept-without-payload.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g35-accept-without-payload.sysml new file mode 100644 index 0000000..3c59de5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g35-accept-without-payload.sysml @@ -0,0 +1,6 @@ +// Invalid: AcceptNode requires a payload parameter after accept (SysML.xtext:1442 AcceptNode, :1446 AcceptNodeDeclaration). +package G35AcceptWithoutPayload { + action def A { + accept ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g36-direction-without-feature.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g36-direction-without-feature.sysml new file mode 100644 index 0000000..5d70d83 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g36-direction-without-feature.sysml @@ -0,0 +1,6 @@ +// Invalid: A feature direction prefixes a feature, which must follow it (SysML.xtext:554 FeatureDirection). +package G36DirectionWithoutFeature { + action def A { + in ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g37-redefines-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g37-redefines-without-target.sysml new file mode 100644 index 0000000..8a3de4c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g37-redefines-without-target.sysml @@ -0,0 +1,9 @@ +// Invalid: Redefines requires a redefined feature reference after the redefines keyword (SysML.xtext:429 Redefines). +package G37RedefinesWithoutTarget { + part def D { + attribute a; + } + part def E :> D { + attribute redefines ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g38-references-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g38-references-without-target.sysml new file mode 100644 index 0000000..7390e4c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g38-references-without-target.sysml @@ -0,0 +1,7 @@ +// Invalid: References requires a referenced feature after ::> (SysML.xtext:413 References). +package G38ReferencesWithoutTarget { + part def D { + attribute a; + attribute b ::> ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g39-redefinition-symbol-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g39-redefinition-symbol-without-target.sysml new file mode 100644 index 0000000..6b91bdf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g39-redefinition-symbol-without-target.sysml @@ -0,0 +1,9 @@ +// Invalid: Redefinition requires a redefined feature after :>> (KerML.xtext:712 Redefinition). +package G39RedefinitionSymbolWithoutTarget { + part def D { + attribute a; + } + part def E :> D { + attribute :>> ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g40-modulo-without-operand.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g40-modulo-without-operand.sysml new file mode 100644 index 0000000..8355313 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g40-modulo-without-operand.sysml @@ -0,0 +1,4 @@ +// Invalid: A multiplicative operator requires a right operand (KerMLExpressions.xtext:267 MultiplicativeOperator). +package G40ModuloWithoutOperand { + attribute x = 7 % ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g41-exponent-without-operand.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g41-exponent-without-operand.sysml new file mode 100644 index 0000000..2efb941 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g41-exponent-without-operand.sysml @@ -0,0 +1,4 @@ +// Invalid: An exponentiation operator requires a right operand (KerMLExpressions.xtext:276 ExponentiationOperator). +package G41ExponentWithoutOperand { + attribute x = 2 ** ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g42-implies-without-operand.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g42-implies-without-operand.sysml new file mode 100644 index 0000000..adb2ada --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g42-implies-without-operand.sysml @@ -0,0 +1,4 @@ +// Invalid: An implies operator requires a right operand (KerMLExpressions.xtext:89 ImpliesOperator). +package G42ImpliesWithoutOperand { + attribute x = true implies ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g43-null-coalescing-without-operand.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g43-null-coalescing-without-operand.sysml new file mode 100644 index 0000000..c821309 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g43-null-coalescing-without-operand.sysml @@ -0,0 +1,4 @@ +// Invalid: A null-coalescing operator requires a right operand (KerMLExpressions.xtext:70 NullCoalescingOperator). +package G43NullCoalescingWithoutOperand { + attribute x = 1 ?? ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g44-conditional-without-else.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g44-conditional-without-else.sysml new file mode 100644 index 0000000..a72578b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g44-conditional-without-else.sysml @@ -0,0 +1,4 @@ +// Invalid: A conditional expression requires an else branch (KerMLExpressions.xtext:59 ConditionalOperator). +package G44ConditionalWithoutElse { + attribute x = if true ? 1 ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g45-classification-test-without-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g45-classification-test-without-type.sysml new file mode 100644 index 0000000..5053eaf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g45-classification-test-without-type.sysml @@ -0,0 +1,4 @@ +// Invalid: A classification test requires a type after istype (KerMLExpressions.xtext:185 ClassificationTestOperator). +package G45ClassificationTestWithoutType { + attribute x = 1 istype ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g46-cast-without-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g46-cast-without-type.sysml new file mode 100644 index 0000000..f73de7c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g46-cast-without-type.sysml @@ -0,0 +1,4 @@ +// Invalid: A cast requires a type after as (KerMLExpressions.xtext:193 CastOperator). +package G46CastWithoutType { + attribute x = 1 as ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g47-prefix-metadata-without-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g47-prefix-metadata-without-name.sysml new file mode 100644 index 0000000..0043b18 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g47-prefix-metadata-without-name.sysml @@ -0,0 +1,4 @@ +// Invalid: PrefixMetadataAnnotation requires a metadata feature after # (SysML.xtext:129 PrefixMetadataAnnotation). +package G47PrefixMetadataWithoutName { + # part def D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g48-decision-without-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g48-decision-without-body.sysml new file mode 100644 index 0000000..2269f7f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g48-decision-without-body.sysml @@ -0,0 +1,6 @@ +// Invalid: DecisionNode requires an action body after its declaration (SysML.xtext:1670 DecisionNode). +package G48DecisionWithoutBody { + action def A { + decide d + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g49-assign-without-value.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g49-assign-without-value.sysml new file mode 100644 index 0000000..4a4f25b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g49-assign-without-value.sysml @@ -0,0 +1,7 @@ +// Invalid: AssignmentNode requires an expression after := (SysML.xtext:1535 AssignmentNode, :1539 AssignmentNodeDeclaration). +package G49AssignWithoutValue { + action def A { + attribute a; + assign a := ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g50-conjugated-port-typing-without-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g50-conjugated-port-typing-without-name.sysml new file mode 100644 index 0000000..6c3bd25 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g50-conjugated-port-typing-without-name.sysml @@ -0,0 +1,7 @@ +// Invalid: A conjugated port typing requires a qualified name after ~ (SysML.xtext:974 ConjugatedPortTyping). +package G50ConjugatedPortTypingWithoutName { + port def P; + part def D { + port p : ~; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g51-real-without-fraction.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g51-real-without-fraction.sysml new file mode 100644 index 0000000..19bcbd9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g51-real-without-fraction.sysml @@ -0,0 +1,4 @@ +// Invalid: A real literal requires digits or an exponent after the point (KerMLExpressions.xtext:526 RealValue). +package G51RealWithoutFraction { + attribute x = 1.; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g52-unterminated-string.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g52-unterminated-string.sysml new file mode 100644 index 0000000..212d8cf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g52-unterminated-string.sysml @@ -0,0 +1,4 @@ +// Invalid: A string literal must be closed (KerMLExpressions.xtext:514 LiteralString). +package G52UnterminatedString { + attribute s = "abc; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g53-range-without-upper-bound.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g53-range-without-upper-bound.sysml new file mode 100644 index 0000000..6229feb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g53-range-without-upper-bound.sysml @@ -0,0 +1,4 @@ +// Invalid: A range expression requires a right operand after .. (KerMLExpressions.xtext:246 RangeExpression). +package G53RangeWithoutUpperBound { + attribute r = 1..; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g54-argument-list-trailing-comma.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g54-argument-list-trailing-comma.sysml new file mode 100644 index 0000000..a665097 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g54-argument-list-trailing-comma.sysml @@ -0,0 +1,5 @@ +// Invalid: A positional argument must follow the comma (KerMLExpressions.xtext:456 PositionalArgumentList). +package G54ArgumentListTrailingComma { + calc def F { in a; in b; return : Integer; } + attribute y = F(1,); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g55-feature-chain-trailing-dot.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g55-feature-chain-trailing-dot.sysml new file mode 100644 index 0000000..73673aa --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g55-feature-chain-trailing-dot.sysml @@ -0,0 +1,6 @@ +// Invalid: A feature chain requires a feature after the dot (KerMLExpressions.xtext:448 OwnedFeatureChaining). +package G55FeatureChainTrailingDot { + part def A { attribute b; } + part a : A; + attribute y = a.; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g56-qualified-name-trailing-separator.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g56-qualified-name-trailing-separator.sysml new file mode 100644 index 0000000..9fa1ac9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g56-qualified-name-trailing-separator.sysml @@ -0,0 +1,5 @@ +// Invalid: A qualified name requires a name after :: (KerMLExpressions.xtext:548 QualifiedName). +package G56QualifiedNameTrailingSeparator { + part def A; + part p : A::; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g57-unterminated-unrestricted-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g57-unterminated-unrestricted-name.sysml new file mode 100644 index 0000000..e11d507 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g57-unterminated-unrestricted-name.sysml @@ -0,0 +1,4 @@ +// Invalid: An unrestricted name must be closed (KerMLExpressions.xtext:536 Name, UNRESTRICTED_NAME). +package G57UnterminatedUnrestrictedName { + part def 'A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g58-satisfy-without-reference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g58-satisfy-without-reference.sysml new file mode 100644 index 0000000..bb854f7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g58-satisfy-without-reference.sysml @@ -0,0 +1,7 @@ +// Invalid: A satisfaction subject requires a feature reference after by (SysML.xtext:2135 SatisfactionFeatureValue). +package G58SatisfyWithoutReference { + requirement def R; + part p { + satisfy requirement : R by ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g59-crosses-without-target.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g59-crosses-without-target.sysml new file mode 100644 index 0000000..67a5033 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g59-crosses-without-target.sysml @@ -0,0 +1,7 @@ +// Invalid: A crossing feature requires a crossed feature after crosses (SysML.xtext:458 OwnedCrossSubsetting). +package G59CrossesWithoutTarget { + part def P { + part a; + part b crosses ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g60-alias-keyword-as-name.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g60-alias-keyword-as-name.sysml new file mode 100644 index 0000000..a7decbc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g60-alias-keyword-as-name.sysml @@ -0,0 +1,6 @@ +// Invalid: an alias name comes from the ID terminal, so 'part' cannot spell it +// (SysML.xtext AliasMember / Identification, terminal ID). +package G60AliasKeywordAsName { + part def B; + alias part for G60AliasKeywordAsName::B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g61-actor-outside-requirement-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g61-actor-outside-requirement-body.sysml new file mode 100644 index 0000000..4f5be7d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g61-actor-outside-requirement-body.sysml @@ -0,0 +1,7 @@ +// Invalid: ActorMember is a RequirementBodyItem/CaseBodyItem; a part def body admits no 'actor' (SysML.xtext:2089 ActorMember, :2039 RequirementBodyItem; pilot validateActorMembershipOwningType). +package G61ActorOutsideRequirementBody { + part def Person; + part def System { + actor operator : Person; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g62-subject-outside-requirement-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g62-subject-outside-requirement-body.sysml new file mode 100644 index 0000000..878f64e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g62-subject-outside-requirement-body.sysml @@ -0,0 +1,7 @@ +// Invalid: SubjectMember is a RequirementBodyItem/CaseBodyItem; a part def body admits no 'subject' (SysML.xtext:2049 SubjectMember, :2039 RequirementBodyItem; pilot validateSubjectMembershipOwningType). +package G62SubjectOutsideRequirementBody { + part def Vehicle; + part def System { + subject v : Vehicle; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g63-objective-outside-case-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g63-objective-outside-case-body.sysml new file mode 100644 index 0000000..907211e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g63-objective-outside-case-body.sysml @@ -0,0 +1,7 @@ +// Invalid: ObjectiveMember is a CaseBodyItem; a part def body admits no 'objective' (SysML.xtext:2198 ObjectiveMember, :2190 CaseBodyItem; pilot validateObjectiveMembershipOwningType). +package G63ObjectiveOutsideCaseBody { + requirement def Goal; + part def System { + objective o : Goal; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g64-stakeholder-outside-requirement-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g64-stakeholder-outside-requirement-body.sysml new file mode 100644 index 0000000..cdac7dc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g64-stakeholder-outside-requirement-body.sysml @@ -0,0 +1,7 @@ +// Invalid: StakeholderMember is a RequirementBodyItem; a part def body admits no 'stakeholder' (SysML.xtext:2098 StakeholderMember, :2039 RequirementBodyItem; pilot validateStakeholderMembershipOwningType). +package G64StakeholderOutsideRequirementBody { + part def Person; + part def System { + stakeholder owner : Person; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g65-entry-action-outside-state-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g65-entry-action-outside-state-body.sysml new file mode 100644 index 0000000..2465a16 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g65-entry-action-outside-state-body.sysml @@ -0,0 +1,6 @@ +// Invalid: EntryActionMember is a StateBodyItem; a part def body admits no 'entry action' (SysML.xtext:1772 EntryActionMember; pilot validateStateSubactionMembershioOwningType). +package G65EntryActionOutsideStateBody { + part def System { + entry action init; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g66-render-outside-view-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g66-render-outside-view-body.sysml new file mode 100644 index 0000000..63424f2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g66-render-outside-view-body.sysml @@ -0,0 +1,7 @@ +// Invalid: ViewRenderingMember is a ViewBodyItem; a part def body admits no 'render' (SysML.xtext:2335 ViewRenderingMember, :2359 ViewBodyItem; pilot validateViewRenderingMembershipOwningType). +package G66RenderOutsideViewBody { + rendering def Table; + part def System { + render rendering r : Table; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g67-expose-outside-view-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g67-expose-outside-view-body.sysml new file mode 100644 index 0000000..c9cae33 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g67-expose-outside-view-body.sysml @@ -0,0 +1,7 @@ +// Invalid: Expose is a ViewBodyItem; a part def body admits no 'expose' (SysML.xtext:2374 Expose, :2359 ViewBodyItem; pilot validateExposeOwningNamespace). +package G67ExposeOutsideViewBody { + part def Exposed; + part def System { + expose Exposed; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g68-definition-in-enumeration-body.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g68-definition-in-enumeration-body.sysml new file mode 100644 index 0000000..982ecd3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g68-definition-in-enumeration-body.sysml @@ -0,0 +1,8 @@ +// Invalid: an enumeration body admits only enumerated values and annotating elements, not a nested definition (SysML.xtext EnumerationBody). +package G61DefinitionInEnumerationBody { + enum def Level { + attribute def Nested; + low; + high; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g69-calc-body-second-result-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g69-calc-body-second-result-expression.sysml new file mode 100644 index 0000000..9bdae33 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g69-calc-body-second-result-expression.sysml @@ -0,0 +1,9 @@ +// Invalid: a calculation body ends in at most one result expression; a second bare expression is a second result expression (SysML.xtext:1951 CalculationBodyPart, KerML 8.3.4.8 Function::result). +package G69CalcBodySecondResultExpression { + private import ScalarValues::Real; + calc def Twice { + in x : Real; + x + 1.0 + x + 2.0 + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g70-name-before-usage-keyword.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g70-name-before-usage-keyword.sysml new file mode 100644 index 0000000..ff28365 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/g70-name-before-usage-keyword.sysml @@ -0,0 +1,7 @@ +// Invalid: a usage's name follows its kind keyword; a name written ahead of the keyword begins no body item (SysML.xtext:752 AttributeUsage, :598 UsageDeclaration, :516 DefinitionBodyItem). +package G70NameBeforeUsageKeyword { + attribute def A; + part def B { + foo attribute bar : A; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k01-specializes-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k01-specializes-without-target.kerml new file mode 100644 index 0000000..f94e80b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k01-specializes-without-target.kerml @@ -0,0 +1,4 @@ +// Invalid: OwnedSpecialization requires a general type after 'specializes' (KerML.xtext SpecializationPart). +package K01SpecializesWithoutTarget { + classifier C specializes ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k02-sysml-keyword-in-kerml.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k02-sysml-keyword-in-kerml.kerml new file mode 100644 index 0000000..7cdc193 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k02-sysml-keyword-in-kerml.kerml @@ -0,0 +1,4 @@ +// Invalid: 'part def' is a SysML production; the KerML grammar has no such keyword (KerML.xtext RootNamespace). +package K02SysMLKeywordInKerML { + part def P; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k03-feature-typing-without-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k03-feature-typing-without-type.kerml new file mode 100644 index 0000000..4cac1e2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k03-feature-typing-without-type.kerml @@ -0,0 +1,6 @@ +// Invalid: FeatureTyping requires a type after ':' (KerML.xtext TypedBy/OwnedFeatureTyping). +package K03FeatureTypingWithoutType { + class C { + feature f : ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k04-dangling-visibility.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k04-dangling-visibility.kerml new file mode 100644 index 0000000..66dfeb3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k04-dangling-visibility.kerml @@ -0,0 +1,4 @@ +// Invalid: MemberPrefix visibility must be followed by a member element (KerML.xtext NamespaceBodyElement). +package K04DanglingVisibility { + public +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k05-unclosed-body.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k05-unclosed-body.kerml new file mode 100644 index 0000000..baf7273 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k05-unclosed-body.kerml @@ -0,0 +1,3 @@ +// Invalid: a Type body requires a closing '}' (KerML.xtext TypeBody). +package K05UnclosedBody { + class C { diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k06-disjoining-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k06-disjoining-without-target.kerml new file mode 100644 index 0000000..ef7cbeb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k06-disjoining-without-target.kerml @@ -0,0 +1,4 @@ +// Invalid: A disjoining declaration requires a type after from (KerML.xtext:426 Disjoining). +class K06A; +class K06B; +disjoining d disjoint K06A from ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k07-conjugation-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k07-conjugation-without-target.kerml new file mode 100644 index 0000000..319c1f5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k07-conjugation-without-target.kerml @@ -0,0 +1,4 @@ +// Invalid: A conjugation declaration requires a conjugated type after ~ (KerML.xtext:408 Conjugation). +class K07A; +class K07B; +conjugation c conjugate K07A ~ ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k08-return-without-feature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k08-return-without-feature.kerml new file mode 100644 index 0000000..0988e9b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k08-return-without-feature.kerml @@ -0,0 +1,4 @@ +// Invalid: A return member requires a feature after the return keyword (KerML.xtext:943 ReturnFeatureMember). +function K08F { + return ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k09-inverting-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k09-inverting-without-target.kerml new file mode 100644 index 0000000..774171a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k09-inverting-without-target.kerml @@ -0,0 +1,5 @@ +// Invalid: A feature inverting requires an inverse feature after of (KerML.xtext:634 FeatureInverting). +class K09A { + feature f; +} +feature g inverse of ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k10-featuring-without-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k10-featuring-without-type.kerml new file mode 100644 index 0000000..91aaff1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k10-featuring-without-type.kerml @@ -0,0 +1,3 @@ +// Invalid: A type featuring requires a featuring type after featured by (KerML.xtext:652 TypeFeaturing). +class K10A; +feature f featured by ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k11-namespace-prefix-metadata-without-name.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k11-namespace-prefix-metadata-without-name.kerml new file mode 100644 index 0000000..b3120e5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k11-namespace-prefix-metadata-without-name.kerml @@ -0,0 +1,4 @@ +// Invalid: A prefix metadata annotation requires a metadata feature after # (KerML.xtext:1069 PrefixMetadataAnnotation). +# namespace K11N { + class K11A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k12-multiplicity-subset-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k12-multiplicity-subset-without-target.kerml new file mode 100644 index 0000000..83dd189 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k12-multiplicity-subset-without-target.kerml @@ -0,0 +1,4 @@ +// Invalid: A multiplicity subset requires a subsetted multiplicity after subsets (KerML.xtext:758 MultiplicitySubset). +class K12A { + multiplicity m subsets ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k13-step-without-declaration.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k13-step-without-declaration.kerml new file mode 100644 index 0000000..dafc358 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k13-step-without-declaration.kerml @@ -0,0 +1,4 @@ +// Invalid: A step is a feature and requires an identification or specialization (KerML.xtext:911 Step). +behavior K13B { + step : ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k14-flow-without-payload-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k14-flow-without-payload-target.kerml new file mode 100644 index 0000000..883bcf9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k14-flow-without-payload-target.kerml @@ -0,0 +1,6 @@ +// Invalid: A flow requires both of its ends (KerML.xtext:996 Flow). +class K14A { + feature a; + feature b; +} +flow f from K14A::a to ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k15-conjugation-without-original.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k15-conjugation-without-original.kerml new file mode 100644 index 0000000..ea678a7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k15-conjugation-without-original.kerml @@ -0,0 +1,3 @@ +// Invalid: Conjugation requires an original type after ~ (KerML.xtext:408 Conjugation). +class K15A { feature b; } +conjugation conjugate K15A.b ~ ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k16-redefinition-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k16-redefinition-without-target.kerml new file mode 100644 index 0000000..f0b7d5f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k16-redefinition-without-target.kerml @@ -0,0 +1,3 @@ +// Invalid: Redefinition requires a redefined feature after :>> (KerML.xtext:712 Redefinition). +class K16A { feature f; } +specialization redefinition K16A.f :>> ; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k17-unions-without-target.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k17-unions-without-target.kerml new file mode 100644 index 0000000..d90ade9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k17-unions-without-target.kerml @@ -0,0 +1,5 @@ +// Invalid: A unioning requires a type after unions (KerML.xtext:444 Unioning). +package K17UnionsWithoutTarget { + classifier A; + classifier C unions ; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k18-connector-end-without-reference.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k18-connector-end-without-reference.kerml new file mode 100644 index 0000000..a62fdd5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k18-connector-end-without-reference.kerml @@ -0,0 +1,8 @@ +// Invalid: A connector end requires a referenced feature (KerML.xtext:854 ConnectorEnd). +package K18ConnectorEndWithoutReference { + class C { + feature a : C; + feature b : C; + connector c from a to ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k19-metadata-typing-without-name.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k19-metadata-typing-without-name.kerml new file mode 100644 index 0000000..2f75c4d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k19-metadata-typing-without-name.kerml @@ -0,0 +1,6 @@ +// Invalid: A metadata feature requires a type after @ (KerML.xtext:1094 MetadataTyping). +package K19MetadataTypingWithoutName { + class C { + @ ; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k20-function-body-second-result-expression.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k20-function-body-second-result-expression.kerml new file mode 100644 index 0000000..3b2a232 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k20-function-body-second-result-expression.kerml @@ -0,0 +1,9 @@ +// Invalid: a function body ends in at most one result expression; a second bare expression is a second result expression (KerML.xtext:933 FunctionBodyPart, KerML 8.3.4.8 Function::result). +package K20FunctionBodySecondResultExpression { + private import ScalarValues::Real; + function twice { + in x : Real; + x + 1.0 + x + 2.0 + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k21-name-before-feature-keyword.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k21-name-before-feature-keyword.kerml new file mode 100644 index 0000000..0c43697 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/grammar/k21-name-before-feature-keyword.kerml @@ -0,0 +1,7 @@ +// Invalid: a feature's name follows its kind keyword; a name written ahead of the keyword begins no body element (KerML.xtext:538 Feature, :548 FeatureDeclaration, :364 TypeBody). +package K21NameBeforeFeatureKeyword { + class A; + class B { + foo feature bar : A; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn01-fork-two-incoming.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn01-fork-two-incoming.sysml new file mode 100644 index 0000000..e04ea7a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn01-fork-two-incoming.sysml @@ -0,0 +1,14 @@ +// Invalid: a fork node may have at most one incoming succession (SysML v2 8.3.17.8; pilot validateForkNodeIncomingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN01ForkTwoIncoming { + action def A { + action a; + action b; + fork f; + action c; + action d; + first a then f; + first b then f; + first f then c; + first f then d; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn02-join-two-outgoing.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn02-join-two-outgoing.sysml new file mode 100644 index 0000000..ef9f72c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn02-join-two-outgoing.sysml @@ -0,0 +1,14 @@ +// Invalid: a join node may have at most one outgoing succession (SysML v2 8.3.17.11; pilot validateJoinNodeOutgoingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN02JoinTwoOutgoing { + action def A { + action a; + action b; + join j; + action c; + action d; + first a then j; + first b then j; + first j then c; + first j then d; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn03-merge-two-outgoing.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn03-merge-two-outgoing.sysml new file mode 100644 index 0000000..757b032 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn03-merge-two-outgoing.sysml @@ -0,0 +1,14 @@ +// Invalid: a merge node may have at most one outgoing succession (SysML v2 8.3.17.13; pilot validateMergeNodeOutgoingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN03MergeTwoOutgoing { + action def A { + action a; + action b; + merge m; + action c; + action d; + first a then m; + first b then m; + first m then c; + first m then d; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn04-decide-two-incoming.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn04-decide-two-incoming.sysml new file mode 100644 index 0000000..608d1e9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn04-decide-two-incoming.sysml @@ -0,0 +1,16 @@ +// Invalid: a decision node may have at most one incoming succession (SysML v2 8.3.17.7; pilot validateDecisionNodeIncomingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN04DecideTwoIncoming { + private import ScalarValues::Boolean; + action def A { + in attribute go : Boolean; + action a; + action b; + decide d; + action c; + action e; + first a then d; + first b then d; + first d if go then c; + first d if not go then e; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn05-control-node-outside-action.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn05-control-node-outside-action.sysml new file mode 100644 index 0000000..dd5fe98 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn05-control-node-outside-action.sysml @@ -0,0 +1,11 @@ +// Invalid: a control node must be owned by an action definition or action usage (SysML v2 8.3.17.6; pilot validateControlNodeOwningType). +package CN05ControlNodeOutsideAction { + constraint def C { + fork f; + } + part def Q { + constraint c { + decide d; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn06-fork-incoming-target-multiplicity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn06-fork-incoming-target-multiplicity.sysml new file mode 100644 index 0000000..5bcb666 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn06-fork-incoming-target-multiplicity.sysml @@ -0,0 +1,12 @@ +// Invalid: every succession into a control node must have target multiplicity 1..1 (SysML v2 8.3.17.6; pilot validateControlNodeIncomingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN06ForkIncomingTargetMultiplicity { + action def A { + action a; + fork f; + action b; + action c; + succession first a then [0..1] f; + first f then b; + first f then c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn07-join-outgoing-source-multiplicity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn07-join-outgoing-source-multiplicity.sysml new file mode 100644 index 0000000..689df24 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn07-join-outgoing-source-multiplicity.sysml @@ -0,0 +1,12 @@ +// Invalid: every succession out of a control node must have source multiplicity 1..1 (SysML v2 8.3.17.6; pilot validateControlNodeOutgoingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN07JoinOutgoingSourceMultiplicity { + action def A { + action a; + action b; + join j; + action c; + first a then j; + first b then j; + succession first [0..1] j then c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn08-merge-incoming-source-multiplicity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn08-merge-incoming-source-multiplicity.sysml new file mode 100644 index 0000000..ab58057 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn08-merge-incoming-source-multiplicity.sysml @@ -0,0 +1,12 @@ +// Invalid: every succession into a merge node must have source multiplicity 0..1 (SysML v2 8.3.17.13; pilot validateMergeNodeIncomingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN08MergeIncomingSourceMultiplicity { + action def A { + action a; + action b; + merge m; + action c; + succession first [1] a then m; + first b then m; + first m then c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml new file mode 100644 index 0000000..4516d1c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml @@ -0,0 +1,12 @@ +// Invalid: every succession out of a decision node must have target multiplicity 0..1 (SysML v2 8.3.17.7; pilot validateDecisionNodeOutgoingSuccessions, unimplemented at the pin, so this case lands in ours-only-rejects). +package CN09DecideOutgoingTargetMultiplicity { + action def A { + action a; + decide d; + action b; + action c; + first a then d; + succession first d then [1] b; + succession first d then [0..1] c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k01-two-owned-multiplicities.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k01-two-owned-multiplicities.kerml new file mode 100644 index 0000000..03f259b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k01-two-owned-multiplicities.kerml @@ -0,0 +1,6 @@ +// Invalid: a type may own at most one multiplicity (KerML 8.3.3.1 validateTypeOwnedMultiplicity; pilot validateTypeOwnedMultiplicity). +package K01TwoOwnedMultiplicities { + class C [1] { + multiplicity m [2]; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k02-differences-one-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k02-differences-one-type.kerml new file mode 100644 index 0000000..3ae231d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k02-differences-one-type.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot difference exactly one type (KerML 8.3.3.1 validateTypeOwnedDifferencingNotOne; pilot validateOwnedDifferencingNotOne). +package K02DifferencesOneType { + class A; + class C differences A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k03-intersects-one-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k03-intersects-one-type.kerml new file mode 100644 index 0000000..bbe1e8d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k03-intersects-one-type.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot intersect exactly one type (KerML 8.3.3.1 validateTypeOwnedIntersectingNotOne; pilot validateOwnedIntersectingNotOne). +package K03IntersectsOneType { + class A; + class C intersects A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k04-unions-one-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k04-unions-one-type.kerml new file mode 100644 index 0000000..b214caf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k04-unions-one-type.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot union exactly one type (KerML 8.3.3.1 validateTypeOwnedUnioningNotOne; pilot validateOwnedUnioningNotOne). +package K04UnionsOneType { + class A; + class C unions A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k05-differences-self.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k05-differences-self.kerml new file mode 100644 index 0000000..e683670 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k05-differences-self.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot difference with itself (KerML 8.3.3.1 validateTypeDifferencingTypesNotSelf; pilot validateTypeDifferencingTypesNotSelf). +package K05DifferencesSelf { + class A; + class C differences C, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k06-intersects-self.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k06-intersects-self.kerml new file mode 100644 index 0000000..25d8bc6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k06-intersects-self.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot intersect with itself (KerML 8.3.3.1 validateTypeIntersectingTypesNotSelf; pilot validateTypeIntersectingTypesNotSelf). +package K06IntersectsSelf { + class A; + class C intersects C, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k07-unions-self.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k07-unions-self.kerml new file mode 100644 index 0000000..765b7cd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k07-unions-self.kerml @@ -0,0 +1,5 @@ +// Invalid: a type cannot union with itself (KerML 8.3.3.1 validateTypeUnioningTypesNotSelf; pilot validateTypeUnioningTypesNotSelf). +package K07UnionsSelf { + class A; + class C unions C, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k08-conjugated-type-specialized.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k08-conjugated-type-specialized.kerml new file mode 100644 index 0000000..885e5fa --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k08-conjugated-type-specialized.kerml @@ -0,0 +1,6 @@ +// Invalid: a conjugated type cannot be the specific type of a specialization (KerML 8.3.3.1 validateSpecializationSpecificNotConjugated; pilot validateSpecializationSpecificNotConjugated). +package K08ConjugatedTypeSpecialized { + class A; + class B ~ A; + specialization S subtype B specializes A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k09-two-reference-subsettings.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k09-two-reference-subsettings.kerml new file mode 100644 index 0000000..b0c94f2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k09-two-reference-subsettings.kerml @@ -0,0 +1,8 @@ +// Invalid: a feature may own at most one reference subsetting (KerML 8.3.3.3 validateFeatureOwnedReferenceSubsetting; pilot validateFeatureOwnedReferenceSubsetting). +package K09TwoReferenceSubsettings { + class C { + feature a : C; + feature b : C; + feature c references a references b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k10-portion-var-feature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k10-portion-var-feature.kerml new file mode 100644 index 0000000..dab5b54 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k10-portion-var-feature.kerml @@ -0,0 +1,6 @@ +// Invalid: a portion feature cannot be variable (KerML 8.3.3.3 validateFeaturePortionNotVariable; pilot validateFeaturePortionNotVariable). +package K10PortionVarFeature { + class C specializes Occurrences::Occurrence { + portion var feature p : C; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k11-initial-value-nonvariable.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k11-initial-value-nonvariable.kerml new file mode 100644 index 0000000..905db5b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k11-initial-value-nonvariable.kerml @@ -0,0 +1,6 @@ +// Invalid: only a variable feature can have an initial value (KerML 8.4.4.9 validateFeatureValueIsInitial; pilot validateFeatureValueIsInitial). +package K11InitialValueNonvariable { + class C { + feature x : C := null; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k12-chain-through-self.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k12-chain-through-self.kerml new file mode 100644 index 0000000..bffb546 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k12-chain-through-self.kerml @@ -0,0 +1,7 @@ +// Invalid: a feature cannot have itself in its feature chain (KerML 8.3.3.3 validateFeatureChainingFeaturesNotSelf; pilot validateFeatureChainingFeaturesNotSelf). +package K12ChainThroughSelf { + class C { + feature a : C; + feature b chains a.b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k13-subsets-inaccessible-feature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k13-subsets-inaccessible-feature.kerml new file mode 100644 index 0000000..19eafea --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k13-subsets-inaccessible-feature.kerml @@ -0,0 +1,9 @@ +// Invalid: a subsetted feature must be accessible from the subsetting feature (KerML 8.3.3.3 validateSubsettingFeaturingTypes; pilot validateSubsettingFeaturingTypes). +package K13SubsetsInaccessibleFeature { + class A { + feature a : A; + } + class B { + feature b : A subsets A::a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k14-variable-subsets-constant.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k14-variable-subsets-constant.kerml new file mode 100644 index 0000000..7703b13 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k14-variable-subsets-constant.kerml @@ -0,0 +1,7 @@ +// Invalid: a variable feature cannot subset a constant one unless it is constant (KerML 8.3.3.3 validateSubsettingConstantConformance; pilot validateSubsettingConstantConformance). +package K14VariableSubsetsConstant { + class C specializes Occurrences::Occurrence { + const feature a : C; + var feature b : C subsets a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k15-nonend-redefines-end.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k15-nonend-redefines-end.kerml new file mode 100644 index 0000000..62518d8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k15-nonend-redefines-end.kerml @@ -0,0 +1,12 @@ +// Invalid: a feature redefining an end feature within an association must be an end (KerML 8.3.3.3 validateRedefinitionEndConformance; pilot validateRedefinitionEndConformance). +package K15NonendRedefinesEnd { + class T; + assoc A { + end a : T; + end b : T; + } + abstract assoc B specializes A { + feature c : T redefines a; + end d : T redefines b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k16-crosses-from-nonend.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k16-crosses-from-nonend.kerml new file mode 100644 index 0000000..7eb1ebe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k16-crosses-from-nonend.kerml @@ -0,0 +1,7 @@ +// Invalid: a cross subsetting must be owned by an end feature of a type with two or more ends (KerML 8.3.3.3 validateCrossSubsettingCrossingFeature; pilot validateCrossSubsettingCrossingFeature). +package K16CrossesFromNonend { + class A { + feature p : A; + feature q : A crosses p; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k17-crosses-not-through-opposite-end.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k17-crosses-not-through-opposite-end.kerml new file mode 100644 index 0000000..36fb0d2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k17-crosses-not-through-opposite-end.kerml @@ -0,0 +1,8 @@ +// Invalid: a crossed feature must chain through the opposite end feature (KerML 8.3.3.3 validateCrossSubsettingCrossedFeature; pilot validateCrossSubsettingCrossedFeature). +package K17CrossesNotThroughOppositeEnd { + class A; + assoc S { + end a : A; + end b : A crosses a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k18-cross-feature-type-differs.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k18-cross-feature-type-differs.kerml new file mode 100644 index 0000000..56b00f1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k18-cross-feature-type-differs.kerml @@ -0,0 +1,11 @@ +// Invalid: a cross feature must have the same type as its end feature (KerML 8.3.3.3 validateFeatureCrossFeatureType; pilot validateFeatureCrossFeatureType). +package K18CrossFeatureTypeDiffers { + class A { + feature x : A; + } + class B; + assoc S { + end a : A; + end b : B crosses a.x; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k19-cross-feature-not-specializing.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k19-cross-feature-not-specializing.kerml new file mode 100644 index 0000000..7e5c0a1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k19-cross-feature-not-specializing.kerml @@ -0,0 +1,15 @@ +// Invalid: a cross feature must specialize the cross features of redefined ends (KerML 8.3.3.3 validateFeatureCrossFeatureSpecialization; pilot validateFeatureCrossFeatureSpecialization). +package K19CrossFeatureNotSpecializing { + class A { + feature x : A; + feature y : A; + } + assoc S { + end a : A; + end b : A crosses a.x; + } + assoc T specializes S { + end a2 : A redefines a; + end b2 : A redefines b crosses a2.y; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k20-datatype-specializes-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k20-datatype-specializes-class.kerml new file mode 100644 index 0000000..dd328a9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k20-datatype-specializes-class.kerml @@ -0,0 +1,5 @@ +// Invalid: a data type cannot specialize a class (KerML 8.3.3.4.1 validateDataTypeSpecialization; pilot validateDataTypeSpecialization). +package K20DatatypeSpecializesClass { + class A; + datatype D specializes A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k21-class-specializes-datatype.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k21-class-specializes-datatype.kerml new file mode 100644 index 0000000..22c67d1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k21-class-specializes-datatype.kerml @@ -0,0 +1,5 @@ +// Invalid: a class cannot specialize a data type (KerML 8.3.3.4.2 validateClassSpecialization; pilot validateClassSpecialization). +package K21ClassSpecializesDatatype { + datatype D; + class C specializes D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k22-struct-specializes-behavior.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k22-struct-specializes-behavior.kerml new file mode 100644 index 0000000..82a1309 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k22-struct-specializes-behavior.kerml @@ -0,0 +1,5 @@ +// Invalid: a structure cannot specialize a behavior (KerML 8.3.3.4.3 validateStructureSpecialization; pilot validateStructureSpecialization). +package K22StructSpecializesBehavior { + behavior B; + struct S specializes B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k23-behavior-specializes-struct.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k23-behavior-specializes-struct.kerml new file mode 100644 index 0000000..a5a421a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k23-behavior-specializes-struct.kerml @@ -0,0 +1,5 @@ +// Invalid: a behavior cannot specialize a structure (KerML 8.3.4.2 validateBehaviorSpecialization; pilot validateBehaviorSpecialization). +package K23BehaviorSpecializesStruct { + struct S; + behavior B specializes S; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k24-binary-assoc-three-ends.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k24-binary-assoc-three-ends.kerml new file mode 100644 index 0000000..a678025 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k24-binary-assoc-three-ends.kerml @@ -0,0 +1,9 @@ +// Invalid: an association specializing BinaryLink cannot have more than two ends (KerML 8.3.3.5 validateAssociationBinarySpecialization; pilot validateAssociationBinarySpecialization). +package K24BinaryAssocThreeEnds { + class T; + assoc A specializes Links::BinaryLink { + end a : T; + end b : T; + end c : T; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k25-assoc-one-end.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k25-assoc-one-end.kerml new file mode 100644 index 0000000..8e8f22d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k25-assoc-one-end.kerml @@ -0,0 +1,7 @@ +// Invalid: a concrete association must have at least two related types (KerML 8.3.3.5 validateAssociationRelatedTypes; pilot validateAssociationRelatedTypes). +package K25AssocOneEnd { + class T; + assoc A { + end a : T; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k26-binary-connector-three-ends.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k26-binary-connector-three-ends.kerml new file mode 100644 index 0000000..e45f28c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k26-binary-connector-three-ends.kerml @@ -0,0 +1,9 @@ +// Invalid: a connector typed by BinaryLink cannot have more than two ends (KerML 8.3.4.1 validateConnectorBinarySpecialization; pilot validateConnectorBinarySpecialization). +package K26BinaryConnectorThreeEnds { + class T { + feature x : T; + feature y : T; + feature z : T; + connector c : Links::BinaryLink (x, y, z); + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k27-connector-feature-outside-featuring-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k27-connector-feature-outside-featuring-type.kerml new file mode 100644 index 0000000..0d3921f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k27-connector-feature-outside-featuring-type.kerml @@ -0,0 +1,9 @@ +// Invalid: a connector's related features must be featured within its featuring types; here the implicit binding connector of a feature reference expression (KerML 8.3.4.1 validateConnectorTypeFeaturing; pilot validateConnectorTypeFeaturing). +package K27ConnectorFeatureOutsideFeaturingType { + class A { + feature x : A; + } + class B { + feature y : A = A::x; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k28-expr-two-return-parameters.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k28-expr-two-return-parameters.kerml new file mode 100644 index 0000000..c9ed0a5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k28-expr-two-return-parameters.kerml @@ -0,0 +1,8 @@ +// Invalid: an expression may own at most one return parameter (KerML 8.3.4.8 validateExpressionResultParameterMembership; pilot validateExpressionResultParameterMembership). +package K28ExprTwoReturnParameters { + class T; + expr e { + return a : T; + return b : T; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k29-function-inherits-second-result-expression.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k29-function-inherits-second-result-expression.kerml new file mode 100644 index 0000000..c3fd37b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k29-function-inherits-second-result-expression.kerml @@ -0,0 +1,8 @@ +// Invalid: a function may have only one owned or inherited result expression (KerML 8.3.4.8 validateFunctionResultExpressionMembership; pilot validateFunctionResultExpressionMembership). +package K29FunctionInheritsSecondResultExpression { + class T; + feature a : T; + feature b : T; + function F { a } + function G specializes F { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k30-expr-inherits-second-result-expression.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k30-expr-inherits-second-result-expression.kerml new file mode 100644 index 0000000..e3b24fe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k30-expr-inherits-second-result-expression.kerml @@ -0,0 +1,8 @@ +// Invalid: an expression may have only one owned or inherited result expression (KerML 8.3.4.8 validateExpressionResultExpressionMembership; pilot validateExpressionResultExpressionMembership). +package K30ExprInheritsSecondResultExpression { + class T; + feature a : T; + feature b : T; + expr e { a } + expr f subsets e { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k31-invoke-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k31-invoke-class.kerml new file mode 100644 index 0000000..c4a8949 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k31-invoke-class.kerml @@ -0,0 +1,5 @@ +// Invalid: an invocation expression must invoke a behavior or behavioral feature (KerML 8.3.4.8 validateInvocationExpressionInstantiatedType; pilot validateInvocationExpressionInstantiatedType). +package K31InvokeClass { + class C; + feature f : C = C(); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k32-too-many-arguments.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k32-too-many-arguments.kerml new file mode 100644 index 0000000..c57a894 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k32-too-many-arguments.kerml @@ -0,0 +1,7 @@ +// Invalid: every invocation argument must correspond to one input parameter of the invoked type (KerML 8.3.4.8 validateInvocationExpressionParameterRedefinition; pilot validateInvocationExpressionParameterRedefinition). +package K32TooManyArguments { + class T; + function F { in x : T; return r : T; } + feature t : T; + feature f : T = F(t, t); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k33-parameter-bound-twice.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k33-parameter-bound-twice.kerml new file mode 100644 index 0000000..785043e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k33-parameter-bound-twice.kerml @@ -0,0 +1,7 @@ +// Invalid: an invocation cannot bind the same parameter twice (KerML 8.3.4.8 validateInvocationExpressionNoDuplicateParameterRedefinition; pilot validateInvocationExpressionNoDuplicateParameterRedefinition). +package K33ParameterBoundTwice { + class T; + function F { in x : T; return r : T; } + feature t : T; + feature f : T = F(x = t, x = t); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k34-constructor-feature-bound-twice.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k34-constructor-feature-bound-twice.kerml new file mode 100644 index 0000000..7928c44 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k34-constructor-feature-bound-twice.kerml @@ -0,0 +1,7 @@ +// Invalid: a constructor expression cannot bind the same feature twice (KerML 8.3.4.8 validateConstructorExpressionNoDuplicateFeatureRedefinition; pilot validateConstructorExpressionNoDuplicateFeatureRedefinition). +package K34ConstructorFeatureBoundTwice { + class T; + class C { feature x : T; } + feature t : T; + feature c : C = new C(x = t, x = t); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k35-metadata-annotates-wrong-kind.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k35-metadata-annotates-wrong-kind.kerml new file mode 100644 index 0000000..866e115 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k35-metadata-annotates-wrong-kind.kerml @@ -0,0 +1,10 @@ +// Invalid: a metadata feature's annotated element must conform to its annotatedElement redefinition (KerML 8.3.4.11 validateMetadataFeatureAnnotatedElement; pilot validateMetadataFeatureAnnotatedElement). +package K35MetadataAnnotatesWrongKind { + metaclass M { + :>> annotatedElement : KerML::Class; + } + class C { + feature f : C; + } + @M about C::f; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k36-metadata-body-redefines-outside.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k36-metadata-body-redefines-outside.kerml new file mode 100644 index 0000000..e39b488 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k36-metadata-body-redefines-outside.kerml @@ -0,0 +1,9 @@ +// Invalid: a metadata body feature must redefine a feature of the metaclass (KerML 8.3.4.11 validateMetadataFeatureBody; pilot validateMetadataFeatureBody). +package K36MetadataBodyRedefinesOutside { + metaclass M; + class C; + feature g : C; + @M about C { + :>> g; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k37-multiplicity-bound-not-natural.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k37-multiplicity-bound-not-natural.kerml new file mode 100644 index 0000000..e4e197e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k37-multiplicity-bound-not-natural.kerml @@ -0,0 +1,7 @@ +// Invalid: a multiplicity bound must have a Natural value (KerML 8.3.3.6 validateMultiplicityRangeResultTypes; pilot validateMultiplicityRangeResultTypes). +package K37MultiplicityBoundNotNatural { + class C { + feature n : C; + feature f : C [n]; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k38-flow-end-without-dot-notation.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k38-flow-end-without-dot-notation.kerml new file mode 100644 index 0000000..f2ac01c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k38-flow-end-without-dot-notation.kerml @@ -0,0 +1,9 @@ +// Invalid: a flow end must subset an identifiable feature through dot notation (KerML 8.3.4.9 validateFlowEndSubsetting; pilot validateFlowEndSubsetting). +package K38FlowEndWithoutDotNotation { + class T; + class C { + feature x : T; + feature y : T; + flow from x to y; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k39-feature-reference-to-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k39-feature-reference-to-class.kerml new file mode 100644 index 0000000..4f669b1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k39-feature-reference-to-class.kerml @@ -0,0 +1,5 @@ +// Invalid: a feature reference expression must refer to a feature (KerML 8.3.4.8 validateFeatureReferenceExpressionReferentIsFeature; pilot validateFeatureReferenceExpressionReferentIsFeature). +package K39FeatureReferenceToClass { + class C; + feature f : C = C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k40-metadata-typed-by-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k40-metadata-typed-by-class.kerml new file mode 100644 index 0000000..0a44539 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k40-metadata-typed-by-class.kerml @@ -0,0 +1,6 @@ +// Invalid: a metadata feature must be typed by a metaclass, not an ordinary class (KerML 8.3.4.11 validateMetadataFeatureMetadata; pilot validateMetadataFeatureMetadataNotAbstract, because its grammar links `@M` only to a metaclass (KerML.xtext MetadataTyping), so the unlinked feature keeps only the implicit abstract Metaobject type). +package K40MetadataTypedByClass { + class M; + class C; + @M about C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k41-chain-expression-to-nested-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k41-chain-expression-to-nested-class.kerml new file mode 100644 index 0000000..d5ffb09 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k41-chain-expression-to-nested-class.kerml @@ -0,0 +1,8 @@ +// Invalid: the target of a feature chain expression must be a feature of the source's type (KerML 8.3.4.8 validateFeatureChainExpressionFeatureConformance; pilot validateFeatureChainExpressionFeatureConformance). +package K41ChainExpressionToNestedClass { + class A { + class N; + } + feature a : A; + feature f : A = a.N; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k42-two-cross-subsettings.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k42-two-cross-subsettings.kerml new file mode 100644 index 0000000..38ab3b8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k42-two-cross-subsettings.kerml @@ -0,0 +1,11 @@ +// Invalid: a feature may own at most one cross subsetting (KerML 8.3.3.3 validateFeatureOwnedCrossSubsetting; pilot validateFeatureOwnedCrossSubsetting). +package K42TwoCrossSubsettings { + class A { + feature x : A; + feature y : A; + } + assoc S { + end a : A; + end b : A crosses a.x crosses a.y; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml new file mode 100644 index 0000000..1bcd14e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml @@ -0,0 +1,8 @@ +// Invalid: an expression typed by a function that owns a result expression may not state a second (KerML 8.3.4.8 validateExpressionResultExpressionMembership; pilot validateExpressionResultExpressionMembership). +package K43ExprTypedByFunctionStatesSecondResultExpression { + class T; + feature a : T; + feature b : T; + function F { a } + expr e : F { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml new file mode 100644 index 0000000..1e94d85 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml @@ -0,0 +1,8 @@ +// Invalid: an expression reference-subsetting one that owns a result expression inherits it and may not state a second (KerML 8.3.4.8 validateExpressionResultExpressionMembership; pilot validateExpressionResultExpressionMembership). +package K44ExprReferencingExprStatesSecondResultExpression { + class T; + feature a : T; + feature b : T; + expr f { a } + expr e ::> f { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k45-conjugated-feature-without-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k45-conjugated-feature-without-type.kerml new file mode 100644 index 0000000..73683b1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k45-conjugated-feature-without-type.kerml @@ -0,0 +1,6 @@ +// Invalid: a feature must have at least one type, and a feature conjugating a class takes no type from it and owns no implicit subsetting to supply one (KerML 8.3.3.3.4 validateFeatureHasType; pilot validateFeatureHasType). +package K45ConjugatedFeatureWithoutType { + class D; + feature f ~ D; + class C { feature g ~ D; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k46-conjugated-structure-not-an-object.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k46-conjugated-structure-not-an-object.kerml new file mode 100644 index 0000000..66ba76a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k46-conjugated-structure-not-an-object.kerml @@ -0,0 +1,7 @@ +// Invalid: a classifier must directly or indirectly specialize its kind's default supertype, and a structure conjugating a plain class reaches Base::Anything but not Objects::Object (KerML 8.3.4.3.2 checkStructureSpecialization; pilot validateClassifierDefaultSupertype). +package K46ConjugatedStructureNotAnObject { + class D; + struct S ~ D; + behavior B; + function F ~ B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml new file mode 100644 index 0000000..3f02b84 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml @@ -0,0 +1,13 @@ +// Invalid: each chaining feature of a feature chain must be featured within the one before it, and an alias reaching another type's feature is not (KerML 8.3.3.3.4 validateFeatureChainingFeatureConformance; pilot validateFeatureChainingFeatureConformance). +package K47FeatureChainThroughAliasToAnotherType { + class B { feature y : B; } + class A { alias z for B::y; feature w : B; } + class K { + feature k : A; + feature q : B; + feature r1 references k.z; + feature r2 chains k.z; + feature r3 :> k.z; + connector c from k.z to q; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k48-annotating-element-annotates-itself.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k48-annotating-element-annotates-itself.kerml new file mode 100644 index 0000000..80446ee --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k48-annotating-element-annotates-itself.kerml @@ -0,0 +1,8 @@ +// Invalid: an annotation owned by its annotated element must own its annotating element, so an annotating element cannot annotate itself (KerML 8.3.2.3.3 validateAnnotationAnnotatedElementOwnership; pilot validateAnnotationAnnotatedElementOwnership). +package K43AnnotatingElementAnnotatesItself { + class A; + metaclass M; + comment C1 about C1 /* a comment annotating itself */ + comment C2 about A, C2 /* and one annotating itself beside another element */ + metadata m3 : M about m3; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k49-binding-connector-with-three-ends.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k49-binding-connector-with-three-ends.kerml new file mode 100644 index 0000000..af19854 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k49-binding-connector-with-three-ends.kerml @@ -0,0 +1,9 @@ +// Invalid: a binding connector is binary, so its ends must reference exactly two features (KerML 8.3.4.7.2 validateBindingConnectorIsBinary; pilot validateBindingConnectorIsBinary). +package K44BindingConnectorWithThreeEnds { + class A; + class C { + feature x : A; feature y : A; feature z : A; + binding b of x = y { end feature e references z; } + abstract binding b2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k50-inline-cross-feature-also-crosses.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k50-inline-cross-feature-also-crosses.kerml new file mode 100644 index 0000000..aa1c70c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k50-inline-cross-feature-also-crosses.kerml @@ -0,0 +1,13 @@ +// Invalid: an end that declares its cross feature inline (`end [m] ...`) cannot also cross another feature (KerML 8.3.3.3 Feature::crossFeature is single-valued; pilot checkFeatureCrossingSpecialization). +package K43InlineCrossFeatureAlsoCrosses { + class C1 { + feature a : C2; + } + class C2 { + feature b : C1; + } + assoc A1 { + end [1] feature x : C1 crosses y.b; + end feature y : C2 crosses x.a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k51-return-parameter-in-classifier.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k51-return-parameter-in-classifier.kerml new file mode 100644 index 0000000..3c119b3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k51-return-parameter-in-classifier.kerml @@ -0,0 +1,7 @@ +// Invalid: a return parameter membership must be owned by a function or expression (KerML 8.3.4.7 validateReturnParameterMembershipOwningType; pilot validateReturnParameterMembershipOwningType). +package K44ReturnParameterInClassifier { + datatype Count; + classifier Counter { + return total : Count; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k52-two-conjugators.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k52-two-conjugators.kerml new file mode 100644 index 0000000..c32dbc9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k52-two-conjugators.kerml @@ -0,0 +1,6 @@ +// Invalid: a type may have at most one conjugator (KerML 8.3.3.1 validateTypeAtMostOneConjugator; pilot validateTypeAtMostOneConjugator). +package K45TwoConjugators { + classifier A; + classifier B; + classifier C ~A ~B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k53-boolean-expression-subsets-datatype.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k53-boolean-expression-subsets-datatype.kerml new file mode 100644 index 0000000..9b546c2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k53-boolean-expression-subsets-datatype.kerml @@ -0,0 +1,5 @@ +// Invalid: a boolean expression is a feature, so what it subsets must be a feature, not a data type (KerML 8.3.3.3 Subsetting::subsettedFeature is typed Feature and 8.3.4.8 BooleanExpression is an Expression, hence a Step and a Feature; pilot fails to link the Subsetting — `Couldn't resolve reference to Feature 'D'` — because that position admits only Features, exactly as for `feature f :> D`). +package K53BooleanExpressionSubsetsDataType { + datatype D; + bool b :> D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml new file mode 100644 index 0000000..1a71197 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml @@ -0,0 +1,10 @@ +// Invalid: a cross feature declared ahead of its end's kind keyword must have the same type as the end, not a subtype of it (KerML 8.3.3.3 validateFeatureCrossFeatureType; pilot validateFeatureCrossFeatureType). +package K54CrossFeatureTypedNarrowerThanEnd { + class C1; class C2; + class Sub1 :> C1; + feature g : C1; + assoc A { + end x1 : Sub1 [0..1] :> g feature x : C1; + end y1 [0..1] feature y : C2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k55-subtype-specific-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k55-subtype-specific-is-package.kerml new file mode 100644 index 0000000..7d2b08b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k55-subtype-specific-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the specific of a keyword-first specialization must be a type, not a package (KerML 8.3.3.1 Specialization::specific is typed Type; pilot fails to link the Specialization — `Couldn't resolve reference to Type 'Q'` — because that position admits only Types). +package K55SubtypeSpecificIsPackage { + package Q; + class B; + specialization subtype Q :> B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k56-subtype-general-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k56-subtype-general-is-package.kerml new file mode 100644 index 0000000..05221a1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k56-subtype-general-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the general of a keyword-first specialization must be a type, not a package (KerML 8.3.3.1 Specialization::general is typed Type; pilot fails to link the Specialization — `Couldn't resolve reference to Type 'Q'`). +package K56SubtypeGeneralIsPackage { + package Q; + class B; + subtype B specializes Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k57-subclassifier-subclassifier-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k57-subclassifier-subclassifier-is-package.kerml new file mode 100644 index 0000000..750812e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k57-subclassifier-subclassifier-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the subclassifier of a keyword-first subclassification must be a classifier, not a package (KerML 8.3.3.2 Subclassification::subclassifier is typed Classifier; pilot fails to link the Subclassification — `Couldn't resolve reference to Classifier 'Q'`). +package K57SubclassifierIsPackage { + package Q; + class B; + subclassifier Q :> B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml new file mode 100644 index 0000000..8493dfe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml @@ -0,0 +1,6 @@ +// Invalid: the superclassifier of a keyword-first subclassification must be a classifier, not a feature (KerML 8.3.3.2 Subclassification::superclassifier is typed Classifier and 8.3.4 a Feature is not a Classifier; pilot fails to link the Subclassification — `Couldn't resolve reference to Classifier 'f'`). +package K58SuperclassifierIsFeature { + feature f; + class B; + specialization subclassifier B specializes f; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k59-typing-typed-feature-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k59-typing-typed-feature-is-package.kerml new file mode 100644 index 0000000..4a70af7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k59-typing-typed-feature-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the typed feature of a keyword-first feature typing must be a feature, not a package (KerML 8.3.4.4 FeatureTyping::typedFeature is typed Feature; pilot fails to link the FeatureTyping — `Couldn't resolve reference to Feature 'Q'`). +package K59TypedFeatureIsPackage { + package Q; + class B; + typing Q : B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k60-typing-typed-feature-is-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k60-typing-typed-feature-is-class.kerml new file mode 100644 index 0000000..cd9e9ca --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k60-typing-typed-feature-is-class.kerml @@ -0,0 +1,6 @@ +// Invalid: the typed feature of a keyword-first feature typing must be a feature, not a class (KerML 8.3.4.4 FeatureTyping::typedFeature is typed Feature; pilot fails to link the FeatureTyping — `Couldn't resolve reference to Feature 'C'`). +package K60TypedFeatureIsClass { + class C; + class B; + typing C typed by B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k61-typing-type-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k61-typing-type-is-package.kerml new file mode 100644 index 0000000..f5e0635 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k61-typing-type-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the type of a keyword-first feature typing must be a type, not a package (KerML 8.3.4.4 FeatureTyping::type is typed Type; pilot fails to link the FeatureTyping — `Couldn't resolve reference to Type 'Q'`). +package K61TypingTypeIsPackage { + package Q; + feature f; + specialization typing f : Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k62-subset-subsetting-feature-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k62-subset-subsetting-feature-is-package.kerml new file mode 100644 index 0000000..78d0c8a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k62-subset-subsetting-feature-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the subsetting feature of a keyword-first subsetting must be a feature, not a package (KerML 8.3.4.5 Subsetting::subsettingFeature is typed Feature; pilot fails to link the Subsetting — `Couldn't resolve reference to Feature 'Q'`). +package K62SubsettingFeatureIsPackage { + package Q; + feature f; + subset Q :> f; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k63-subset-subsetted-feature-is-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k63-subset-subsetted-feature-is-class.kerml new file mode 100644 index 0000000..4d25c9e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k63-subset-subsetted-feature-is-class.kerml @@ -0,0 +1,6 @@ +// Invalid: the subsetted feature of a keyword-first subsetting must be a feature, not a class (KerML 8.3.4.5 Subsetting::subsettedFeature is typed Feature; pilot fails to link the Subsetting — `Couldn't resolve reference to Feature 'C'`). +package K63SubsettedFeatureIsClass { + class C; + feature f; + specialization subset f subsets C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k64-redefinition-redefining-feature-is-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k64-redefinition-redefining-feature-is-class.kerml new file mode 100644 index 0000000..ef461c5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k64-redefinition-redefining-feature-is-class.kerml @@ -0,0 +1,6 @@ +// Invalid: the redefining feature of a keyword-first redefinition must be a feature, not a class (KerML 8.3.4.6 Redefinition::redefiningFeature is typed Feature; pilot fails to link the Redefinition — `Couldn't resolve reference to Feature 'C'`). +package K64RedefiningFeatureIsClass { + class C; + class A { feature f; } + redefinition C :>> A::f; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k65-redefinition-redefined-feature-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k65-redefinition-redefined-feature-is-package.kerml new file mode 100644 index 0000000..61ff25f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k65-redefinition-redefined-feature-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the redefined feature of a keyword-first redefinition must be a feature, not a package (KerML 8.3.4.6 Redefinition::redefinedFeature is typed Feature; pilot fails to link the Redefinition — `Couldn't resolve reference to Feature 'Q'`). +package K65RedefinedFeatureIsPackage { + package Q; + class A { feature f; } + specialization redefinition A::f redefines Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k66-conjugate-conjugated-type-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k66-conjugate-conjugated-type-is-package.kerml new file mode 100644 index 0000000..8994762 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k66-conjugate-conjugated-type-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the conjugated type of a keyword-first conjugation must be a type, not a package (KerML 8.3.3.4 Conjugation::conjugatedType is typed Type; pilot fails to link the Conjugation — `Couldn't resolve reference to Type 'Q'`). +package K66ConjugatedTypeIsPackage { + package Q; + class B; + conjugate Q ~ B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k67-conjugate-original-type-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k67-conjugate-original-type-is-package.kerml new file mode 100644 index 0000000..f6fd1cf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k67-conjugate-original-type-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the original type of a keyword-first conjugation must be a type, not a package (KerML 8.3.3.4 Conjugation::originalType is typed Type; pilot fails to link the Conjugation — `Couldn't resolve reference to Type 'Q'`). +package K67OriginalTypeIsPackage { + package Q; + class B; + conjugation conjugate B conjugates Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k68-inverse-feature-inverted-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k68-inverse-feature-inverted-is-package.kerml new file mode 100644 index 0000000..385525f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k68-inverse-feature-inverted-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the inverted feature of a keyword-first feature inverting must be a feature, not a package (KerML 8.3.4.8 FeatureInverting::featureInverted is typed Feature; pilot fails to link the FeatureInverting — `Couldn't resolve reference to Feature 'Q'`). +package K68FeatureInvertedIsPackage { + package Q; + feature f; + inverse Q of f; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k69-inverse-inverting-feature-is-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k69-inverse-inverting-feature-is-class.kerml new file mode 100644 index 0000000..ec178ae --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k69-inverse-inverting-feature-is-class.kerml @@ -0,0 +1,6 @@ +// Invalid: the inverting feature of a keyword-first feature inverting must be a feature, not a class (KerML 8.3.4.8 FeatureInverting::invertingFeature is typed Feature; pilot fails to link the FeatureInverting — `Couldn't resolve reference to Feature 'C'`). +package K69InvertingFeatureIsClass { + class C; + feature f; + inverting inverse f of C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k70-disjoint-type-disjoined-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k70-disjoint-type-disjoined-is-package.kerml new file mode 100644 index 0000000..ab78d97 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k70-disjoint-type-disjoined-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the disjoined type of a keyword-first disjoining must be a type, not a package (KerML 8.3.3.3 Disjoining::typeDisjoined is typed Type; pilot fails to link the Disjoining — `Couldn't resolve reference to Type 'Q'`). +package K70TypeDisjoinedIsPackage { + package Q; + class B; + disjoint Q from B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k71-disjoint-disjoining-type-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k71-disjoint-disjoining-type-is-package.kerml new file mode 100644 index 0000000..2be4670 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k71-disjoint-disjoining-type-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the disjoining type of a keyword-first disjoining must be a type, not a package (KerML 8.3.3.3 Disjoining::disjoiningType is typed Type; pilot fails to link the Disjoining — `Couldn't resolve reference to Type 'Q'`). +package K71DisjoiningTypeIsPackage { + package Q; + class B; + disjoining disjoint B from Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k72-featuring-feature-of-type-is-class.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k72-featuring-feature-of-type-is-class.kerml new file mode 100644 index 0000000..65fcded --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k72-featuring-feature-of-type-is-class.kerml @@ -0,0 +1,6 @@ +// Invalid: the featured feature of a type featuring must be a feature, not a class (KerML 8.3.4.3 TypeFeaturing::featureOfType is typed Feature; pilot fails to link the TypeFeaturing — `Couldn't resolve reference to Feature 'C'`). +package K72FeatureOfTypeIsClass { + class C; + class B; + featuring C by B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k73-featuring-featuring-type-is-package.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k73-featuring-featuring-type-is-package.kerml new file mode 100644 index 0000000..e0887fd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/k73-featuring-featuring-type-is-package.kerml @@ -0,0 +1,6 @@ +// Invalid: the featuring type of a type featuring must be a type, not a package (KerML 8.3.4.3 TypeFeaturing::featuringType is typed Type; pilot fails to link the TypeFeaturing — `Couldn't resolve reference to Type 'Q'`). +package K73FeaturingTypeIsPackage { + package Q; + feature f; + featuring f by Q; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s01-action-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s01-action-typed-by-part-def.sysml new file mode 100644 index 0000000..b71c020 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s01-action-typed-by-part-def.sysml @@ -0,0 +1,5 @@ +// Invalid: An action must be typed by action definitions (SysML 7.16 Actions; pilot validateActionUsageType). +package S01ActionTypedByPartDef { + part def PD; + action a : PD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s02-allocation-typed-by-connection-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s02-allocation-typed-by-connection-def.sysml new file mode 100644 index 0000000..0ad8c34 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s02-allocation-typed-by-connection-def.sysml @@ -0,0 +1,11 @@ +// Invalid: An allocation must be typed by allocation definitions (SysML 7.15 Allocations; pilot validateAllocationUsageType). +package S02AllocationTypedByConnectionDef { + part def P; + connection def CD { + end part x : P; + end part y : P; + } + part a : P; + part b : P; + allocation al : CD allocate a to b; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s03-analysis-typed-by-case-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s03-analysis-typed-by-case-def.sysml new file mode 100644 index 0000000..8d85c83 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s03-analysis-typed-by-case-def.sysml @@ -0,0 +1,5 @@ +// Invalid: An analysis case must be typed by one analysis case definition (SysML 7.22 Analysis Cases; pilot validateAnalysisCaseUsageType). +package S03AnalysisTypedByCaseDef { + case def CD; + analysis a : CD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s04-assert-references-non-constraint.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s04-assert-references-non-constraint.sysml new file mode 100644 index 0000000..5f30adf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s04-assert-references-non-constraint.sysml @@ -0,0 +1,8 @@ +// Invalid: An assert constraint usage must reference a constraint usage (SysML 7.19 Constraints; pilot validateAssertConstraintUsageReference). +package S04AssertReferencesNonConstraint { + constraint def C; + ref r : C; + part p { + assert r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s05-assign-to-package-level-attribute.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s05-assign-to-package-level-attribute.sysml new file mode 100644 index 0000000..3d60f34 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s05-assign-to-package-level-attribute.sysml @@ -0,0 +1,7 @@ +// Invalid: An assignment referent must be time varying (SysML 7.16 Actions; pilot validateAssignmentActionUsageReferentIsTimeVarying). +package S05AssignToPackageLevelAttribute { + attribute x : ScalarValues::Integer; + action a { + assign x := 1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s06-enum-attribute-two-types.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s06-enum-attribute-two-types.sysml new file mode 100644 index 0000000..629ced4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s06-enum-attribute-two-types.sysml @@ -0,0 +1,6 @@ +// Invalid: An enumeration attribute cannot have more than one type (SysML 7.8 Enumerations; pilot validateAttributeUsageEnumerationType). +package S06EnumAttributeTwoTypes { + enum def E { a; b; } + attribute def D; + attribute x : E, D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s07-calc-typed-by-action-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s07-calc-typed-by-action-def.sysml new file mode 100644 index 0000000..a508554 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s07-calc-typed-by-action-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A calculation must be typed by one calculation definition (SysML 7.18 Calculations; pilot validateCalculationUsageType). +package S07CalcTypedByActionDef { + action def AD; + calc c : AD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s08-case-def-two-objectives.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s08-case-def-two-objectives.sysml new file mode 100644 index 0000000..b21acdd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s08-case-def-two-objectives.sysml @@ -0,0 +1,8 @@ +// Invalid: A case definition may have at most one objective (SysML 7.21 Cases; pilot validateCaseDefinitionOnlyOneObjective). +package S08CaseDefTwoObjectives { + requirement def R; + case def CD { + objective o1 : R; + objective o2 : R; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s09-case-def-two-subjects.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s09-case-def-two-subjects.sysml new file mode 100644 index 0000000..c0f0711 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s09-case-def-two-subjects.sysml @@ -0,0 +1,8 @@ +// Invalid: A case definition may have at most one subject (SysML 7.21 Cases; pilot validateCaseDefinitionOnlyOneSubject). +package S09CaseDefTwoSubjects { + part def P; + case def CD { + subject s1 : P; + subject s2 : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s10-case-def-subject-not-first.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s10-case-def-subject-not-first.sysml new file mode 100644 index 0000000..5cec518 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s10-case-def-subject-not-first.sysml @@ -0,0 +1,8 @@ +// Invalid: The subject of a case definition must be its first parameter (SysML 7.21 Cases; pilot validateCaseDefinitionSubjectParameterPosition). +package S10CaseDefSubjectNotFirst { + part def P; + case def CD { + in x : P; + subject s : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s11-case-two-objectives.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s11-case-two-objectives.sysml new file mode 100644 index 0000000..010216b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s11-case-two-objectives.sysml @@ -0,0 +1,8 @@ +// Invalid: A case usage may have at most one objective (SysML 7.21 Cases; pilot validateCaseUsageOnlyOneObjective). +package S11CaseTwoObjectives { + requirement def R; + case c { + objective o1 : R; + objective o2 : R; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s12-case-two-subjects.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s12-case-two-subjects.sysml new file mode 100644 index 0000000..d80ebd2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s12-case-two-subjects.sysml @@ -0,0 +1,8 @@ +// Invalid: A case usage may have at most one subject (SysML 7.21 Cases; pilot validateCaseUsageOnlyOneSubject). +package S12CaseTwoSubjects { + part def P; + case c { + subject s1 : P; + subject s2 : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s13-case-subject-not-first.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s13-case-subject-not-first.sysml new file mode 100644 index 0000000..b224dc8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s13-case-subject-not-first.sysml @@ -0,0 +1,8 @@ +// Invalid: The subject of a case usage must be its first parameter (SysML 7.21 Cases; pilot validateCaseUsageSubjectParameterPosition). +package S13CaseSubjectNotFirst { + part def P; + case c { + in x : P; + subject s : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s14-case-typed-by-action-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s14-case-typed-by-action-def.sysml new file mode 100644 index 0000000..40cfaa1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s14-case-typed-by-action-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A case must be typed by one case definition (SysML 7.21 Cases; pilot validateCaseUsageType). +package S14CaseTypedByActionDef { + action def AD; + case c : AD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s15-connection-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s15-connection-typed-by-part-def.sysml new file mode 100644 index 0000000..36ac62e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s15-connection-typed-by-part-def.sysml @@ -0,0 +1,11 @@ +// Invalid: A connection must be typed by connection definitions (SysML 7.13 Connections; pilot validateConnectionUsageType). +package S15ConnectionTypedByPartDef { + part def P; + part def PD { + end part x : P; + end part y : P; + } + part a : P; + part b : P; + connection c : PD connect a to b; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s16-event-references-non-occurrence.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s16-event-references-non-occurrence.sysml new file mode 100644 index 0000000..a747cca --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s16-event-references-non-occurrence.sysml @@ -0,0 +1,8 @@ +// Invalid: An event occurrence usage must reference an occurrence usage (SysML 7.9 Occurrences; pilot validateEventOccurrenceUsageReferent). +package S16EventReferencesNonOccurrence { + part def P; + ref r : P; + part p { + event r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s17-exhibit-references-non-state.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s17-exhibit-references-non-state.sysml new file mode 100644 index 0000000..b47cfee --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s17-exhibit-references-non-state.sysml @@ -0,0 +1,8 @@ +// Invalid: An exhibit state usage must reference a state usage (SysML 7.17 States; pilot validateExhibitStateUsageReference). +package S17ExhibitReferencesNonState { + state def SD; + ref r : SD; + part p { + exhibit r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s18-flow-def-three-ends.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s18-flow-def-three-ends.sysml new file mode 100644 index 0000000..5293c34 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s18-flow-def-three-ends.sysml @@ -0,0 +1,9 @@ +// Invalid: A flow connection definition can have at most two ends (SysML 7.13 Connections; pilot validateFlowDefinitionConnectionEnds). +package S18FlowDefThreeEnds { + part def P; + flow def FD { + end part a : P; + end part b : P; + end part c : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s19-flow-typed-by-connection-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s19-flow-typed-by-connection-def.sysml new file mode 100644 index 0000000..d7690e7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s19-flow-typed-by-connection-def.sysml @@ -0,0 +1,17 @@ +// Invalid: A flow connection must be typed by flow connection definitions (SysML 7.13 Connections; pilot validateFlowUsageType). +package S19FlowTypedByConnectionDef { + item def I; + part def P { + out item x : I; + in item y : I; + } + connection def CD { + end part a : P; + end part b : P; + } + part s { + part p : P; + part q : P; + flow f : CD from p.x to q.y; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s20-include-references-non-use-case.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s20-include-references-non-use-case.sysml new file mode 100644 index 0000000..534e507 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s20-include-references-non-use-case.sysml @@ -0,0 +1,8 @@ +// Invalid: An include use case usage must reference a use case usage (SysML 7.24 Use Cases; pilot validateIncludeUseCaseUsageReference). +package S20IncludeReferencesNonUseCase { + use case def UC; + ref r : UC; + use case def UC2 { + include r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s21-interface-def-end-not-port.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s21-interface-def-end-not-port.sysml new file mode 100644 index 0000000..fb0ee69 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s21-interface-def-end-not-port.sysml @@ -0,0 +1,10 @@ +// Invalid: An interface definition end must be a port (SysML 7.14 Interfaces; pilot validateInterfaceDefinitionEnd). +package S21InterfaceDefEndNotPort { + part def P; + port def PT; + interface def ID { + end part a : P; + end port b : PT; + end port c : PT; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s22-interface-typed-by-connection-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s22-interface-typed-by-connection-def.sysml new file mode 100644 index 0000000..ec8e19c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s22-interface-typed-by-connection-def.sysml @@ -0,0 +1,13 @@ +// Invalid: An interface must be typed by interface definitions (SysML 7.14 Interfaces; pilot validateInterfaceUsageType). +package S22InterfaceTypedByConnectionDef { + port def PT; + connection def CD { + end port a : PT; + end port b : PT; + } + part p { + port p1 : PT; + port p2 : PT; + interface i : CD connect p1 to p2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s23-metadata-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s23-metadata-typed-by-part-def.sysml new file mode 100644 index 0000000..16d1d6f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s23-metadata-typed-by-part-def.sysml @@ -0,0 +1,7 @@ +// Invalid: A metadata usage must be typed by one metadata definition (SysML 7.26 Metadata; pilot validateMetadataUsageType). +package S23MetadataTypedByPartDef { + part def PD; + part p { + @PD; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s24-perform-references-non-action.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s24-perform-references-non-action.sysml new file mode 100644 index 0000000..24329de --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s24-perform-references-non-action.sysml @@ -0,0 +1,8 @@ +// Invalid: A perform action usage must reference an action usage (SysML 7.16 Actions; pilot validatePerformActionUsageReference). +package S24PerformReferencesNonAction { + action def AD; + ref r : AD; + part p { + perform r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s25-port-nested-composite-part.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s25-port-nested-composite-part.sysml new file mode 100644 index 0000000..167ce5e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s25-port-nested-composite-part.sysml @@ -0,0 +1,10 @@ +// Invalid: Nested usages in a port usage (other than ports) must be referential (SysML 7.12 Ports; pilot validatePortUsageNestedUsagesNotComposite). +package S25PortNestedCompositePart { + part def B; + port def PD; + part p { + port pt : PD { + part b : B; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s26-port-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s26-port-typed-by-part-def.sysml new file mode 100644 index 0000000..2dd47c3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s26-port-typed-by-part-def.sysml @@ -0,0 +1,7 @@ +// Invalid: A port must be typed by port definitions (SysML 7.12 Ports; pilot validatePortUsageType). +package S26PortTypedByPartDef { + part def PD; + part p { + port pt : PD; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s27-rendering-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s27-rendering-typed-by-part-def.sysml new file mode 100644 index 0000000..3a9b0e9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s27-rendering-typed-by-part-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A rendering must be typed by one rendering definition (SysML 7.25 Views and Viewpoints; pilot validateRenderingUsageType). +package S27RenderingTypedByPartDef { + part def PD; + rendering r : PD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s28-requirement-def-subject-not-first.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s28-requirement-def-subject-not-first.sysml new file mode 100644 index 0000000..1772b5f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s28-requirement-def-subject-not-first.sysml @@ -0,0 +1,8 @@ +// Invalid: The subject of a requirement definition must be its first parameter (SysML 7.20 Requirements; pilot validateRequirementDefinitionSubjectParameterPosition). +package S28RequirementDefSubjectNotFirst { + part def P; + requirement def R { + in x : P; + subject s : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s29-requirement-two-subjects.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s29-requirement-two-subjects.sysml new file mode 100644 index 0000000..2df28c8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s29-requirement-two-subjects.sysml @@ -0,0 +1,8 @@ +// Invalid: A requirement usage may have at most one subject (SysML 7.20 Requirements; pilot validateRequirementUsageOnlyOneSubject). +package S29RequirementTwoSubjects { + part def P; + requirement r { + subject s1 : P; + subject s2 : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s30-requirement-subject-not-first.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s30-requirement-subject-not-first.sysml new file mode 100644 index 0000000..ee0399b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s30-requirement-subject-not-first.sysml @@ -0,0 +1,8 @@ +// Invalid: The subject of a requirement usage must be its first parameter (SysML 7.20 Requirements; pilot validateRequirementUsageSubjectParameterPosition). +package S30RequirementSubjectNotFirst { + part def P; + requirement r { + in x : P; + subject s : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s31-requirement-typed-by-constraint-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s31-requirement-typed-by-constraint-def.sysml new file mode 100644 index 0000000..8d39685 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s31-requirement-typed-by-constraint-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A requirement must be typed by one requirement definition (SysML 7.20 Requirements; pilot validateRequirementUsageType). +package S31RequirementTypedByConstraintDef { + constraint def C; + requirement r : C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s32-satisfy-references-non-requirement.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s32-satisfy-references-non-requirement.sysml new file mode 100644 index 0000000..da2defe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s32-satisfy-references-non-requirement.sysml @@ -0,0 +1,7 @@ +// Invalid: A satisfy requirement usage must reference a requirement usage (SysML 7.20 Requirements; pilot validateSatisfyRequirementUsageReference). +package S32SatisfyReferencesNonRequirement { + constraint c; + part p { + satisfy c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s33-parallel-state-usage-with-succession.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s33-parallel-state-usage-with-succession.sysml new file mode 100644 index 0000000..596411e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s33-parallel-state-usage-with-succession.sysml @@ -0,0 +1,8 @@ +// Invalid: A parallel state usage cannot have successions or transitions (SysML 7.17 States; pilot validateStateUsageParallelSubactions). +package S33ParallelStateUsageWithSuccession { + state s parallel { + state s1; + state s2; + first s1 then s2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s34-state-usage-two-entry-actions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s34-state-usage-two-entry-actions.sysml new file mode 100644 index 0000000..7ecc744 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s34-state-usage-two-entry-actions.sysml @@ -0,0 +1,7 @@ +// Invalid: A state usage may have at most one entry action (SysML 7.17 States; pilot validateStateUsageSubactionKind). +package S34StateUsageTwoEntryActions { + state s { + entry action a1; + entry action a2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s35-state-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s35-state-typed-by-part-def.sysml new file mode 100644 index 0000000..4b3809b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s35-state-typed-by-part-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A state must be typed by state definitions (SysML 7.17 States; pilot validateStateUsageType). +package S35StateTypedByPartDef { + part def PD; + state s : PD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s36-usage-typed-by-feature.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s36-usage-typed-by-feature.sysml new file mode 100644 index 0000000..9adddfe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s36-usage-typed-by-feature.sysml @@ -0,0 +1,4 @@ +// Invalid: A usage must be typed by definitions (SysML 7.6 Definition and Usage; pilot validateUsageType). +package S36UsageTypedByFeature { + ref r : Base::things; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s37-variation-usage-member-not-variant.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s37-variation-usage-member-not-variant.sysml new file mode 100644 index 0000000..f4d3e27 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s37-variation-usage-member-not-variant.sysml @@ -0,0 +1,8 @@ +// Invalid: An owned usage of a variation usage must be a variant (SysML 7.6 Definition and Usage; pilot validateUsageVariationMembership). +package S37VariationUsageMemberNotVariant { + part def P; + variation part choices : P { + variant part a : P; + part b : P; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s38-use-case-typed-by-case-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s38-use-case-typed-by-case-def.sysml new file mode 100644 index 0000000..95cd030 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s38-use-case-typed-by-case-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A use case must be typed by one use case definition (SysML 7.24 Use Cases; pilot validateUseCaseUsageType). +package S38UseCaseTypedByCaseDef { + case def CD; + use case uc : CD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s39-verification-typed-by-case-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s39-verification-typed-by-case-def.sysml new file mode 100644 index 0000000..3a2d1ff --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s39-verification-typed-by-case-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A verification case must be typed by one verification case definition (SysML 7.23 Verification Cases; pilot validateVerificationCaseUsageType). +package S39VerificationTypedByCaseDef { + case def CD; + verification v : CD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s40-view-def-two-renderings.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s40-view-def-two-renderings.sysml new file mode 100644 index 0000000..3082d51 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s40-view-def-two-renderings.sysml @@ -0,0 +1,8 @@ +// Invalid: A view definition may have at most one view rendering (SysML 7.25 Views and Viewpoints; pilot validateViewDefinitionOnlyOnvViewRendering). +package S40ViewDefTwoRenderings { + rendering def RD; + view def V { + render rendering r1 : RD; + render rendering r2 : RD; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s41-view-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s41-view-typed-by-part-def.sysml new file mode 100644 index 0000000..acdc91b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s41-view-typed-by-part-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A view must be typed by one view definition (SysML 7.25 Views and Viewpoints; pilot validateViewUsageType). +package S41ViewTypedByPartDef { + part def PD; + view v : PD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml new file mode 100644 index 0000000..2f73d00 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml @@ -0,0 +1,5 @@ +// Invalid: A viewpoint must be typed by one viewpoint definition (SysML 7.25 Views and Viewpoints; pilot validateViewpointUsageType). +package S42ViewpointTypedByRequirementDef { + requirement def RD; + viewpoint vp : RD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s43-assign-to-non-feature.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s43-assign-to-non-feature.sysml new file mode 100644 index 0000000..1e5645a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s43-assign-to-non-feature.sysml @@ -0,0 +1,7 @@ +// Invalid: An assignment must have a feature as its referent (SysML 7.16 Actions; pilot validateAssignmentActionUsageReferent). +package S43AssignToNonFeature { + part def PD; + action a { + assign PD := 1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s44-transition-target-not-action.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s44-transition-target-not-action.sysml new file mode 100644 index 0000000..3961e9b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s44-transition-target-not-action.sysml @@ -0,0 +1,9 @@ +// Invalid: A transition must own a succession whose target is an action or state (SysML 7.17 States; pilot validateTransitionUsageSuccession). +package S44TransitionTargetNotAction { + part def PD; + state def S { + state s1; + part p : PD; + transition first s1 then p; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s45-snapshot-outside-occurrence.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s45-snapshot-outside-occurrence.sysml new file mode 100644 index 0000000..212e02a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s45-snapshot-outside-occurrence.sysml @@ -0,0 +1,5 @@ +// Invalid: A portion (snapshot/timeslice) usage must be owned by an occurrence definition or usage (SysML 7.10 Occurrences; pilot validateOccurrenceUsageIsPortion). +package S45SnapshotOutsideOccurrence { + part def PD; + snapshot part s : PD; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s46-feature-value-overriding.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s46-feature-value-overriding.sysml new file mode 100644 index 0000000..d926cf9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s46-feature-value-overriding.sysml @@ -0,0 +1,13 @@ +// Invalid: a feature bound with `=` may not be given another value by a redefining feature; only a `default =` value may be overridden (KerML 8.3.4.10.2; pilot validateFeatureValueOverriding). +package S46FeatureValueOverriding { + private import ScalarValues::Integer; + part def P { + attribute a : Integer = 1; + } + part p : P { + attribute :>> a = 2; + } + part def Q :> P { + attribute :>> a = 3; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s47-enumeration-specializes-enumeration.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s47-enumeration-specializes-enumeration.sysml new file mode 100644 index 0000000..4d93234 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s47-enumeration-specializes-enumeration.sysml @@ -0,0 +1,8 @@ +// Invalid: An enumeration definition is a variation and a variation must not specialize another variation (SysML v2 7.6.4 and 8.3.9 validateEnumerationDefinitionIsVariation, validateDefinitionVariationSpecialization; pilot validateDefinitionVariationSpecialization). +package S01EnumerationSpecializesEnumeration { + enum def E { + a; + b; + } + enum def F :> E; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s48-after-trigger-not-duration.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s48-after-trigger-not-duration.sysml new file mode 100644 index 0000000..89b4195 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s48-after-trigger-not-duration.sysml @@ -0,0 +1,8 @@ +// Invalid: The argument of an `after` trigger must be a DurationValue (SysML 7.16 TriggerInvocationExpression; pilot validateTriggerInvocationActionAfterArgument). +package S47AfterTriggerNotDuration { + state def S { + state a; + state b; + transition first a accept after 5 then b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s49-at-trigger-not-time-instant.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s49-at-trigger-not-time-instant.sysml new file mode 100644 index 0000000..39cf63c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s49-at-trigger-not-time-instant.sysml @@ -0,0 +1,11 @@ +// Invalid: The argument of an `at` trigger must be a TimeInstantValue (SysML 7.16 TriggerInvocationExpression; pilot validateTriggerInvocationActionAtArgument). +package S48AtTriggerNotTimeInstant { + private import ISQ::*; + private import SI::*; + state def S { + attribute delay : DurationValue; + state a; + state b; + transition first a accept at delay then b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s50-when-trigger-not-boolean.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s50-when-trigger-not-boolean.sysml new file mode 100644 index 0000000..1dc4be4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s50-when-trigger-not-boolean.sysml @@ -0,0 +1,10 @@ +// Invalid: The argument of a `when` trigger must be Boolean (SysML 7.16 TriggerInvocationExpression; pilot validateTriggerInvocationActionWhenArgument). +package S49WhenTriggerNotBoolean { + private import ScalarValues::*; + state def S { + attribute level : Integer; + state a; + state b; + transition first a accept when level then b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml new file mode 100644 index 0000000..daa8fe8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml @@ -0,0 +1,6 @@ +// Invalid: An enumeration must be typed by one enumeration definition — an expression body written as the value types the enumerated value by Evaluation, which the enumeration is not (SysML 7.7 validateEnumerationUsageType; pilot SysMLValidator checkOneType). +package S51EnumValueBodyTypedOutsideEnumeration { + enum def E { + a = { 1 + 2 }; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s52-variant-port-composite.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s52-variant-port-composite.sysml new file mode 100644 index 0000000..8fb72c2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s52-variant-port-composite.sysml @@ -0,0 +1,16 @@ +// Invalid: A port usage whose owning type is not a port definition or port usage must be referential, and a variant has no owning type (SysML 7.12 Ports; pilot validatePortUsageIsReference). +package S52VariantPortComposite { + port def PD; + port def Q { + variation port vp : PD { + variant port a : PD; + } + } + part holder { + port q : Q { + variation port vq : ~PD { + variant port b : ~PD; + } + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s80-constant-attribute-not-variable.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s80-constant-attribute-not-variable.sysml new file mode 100644 index 0000000..8acf112 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s80-constant-attribute-not-variable.sysml @@ -0,0 +1,7 @@ +// Invalid: only a variable feature can be constant, and an attribute of a data type is not variable (KerML 8.3.3.3 validateFeatureConstantIsVariable; pilot validateFeatureConstantIsVariable). +package S80ConstantAttributeNotVariable { + attribute def A; + attribute def B { + constant attribute x : A; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s81-guarded-succession-guard-not-boolean.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s81-guarded-succession-guard-not-boolean.sysml new file mode 100644 index 0000000..9b1aec6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s81-guarded-succession-guard-not-boolean.sysml @@ -0,0 +1,8 @@ +// Invalid: the guard of a guarded succession in an action body must be a Boolean expression (SysML v2 8.3.18.8; pilot validateTransitionFeatureMembershipGuardExpression, vacuous at the pin once the library types the guard, so this case lands in ours-only-rejects). +package S81GuardedSuccessionGuardNotBoolean { + action def A { + action a; + action b; + first a if "go" then b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml new file mode 100644 index 0000000..8236d42 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml @@ -0,0 +1,6 @@ +// Invalid: a constraint definition specializing one that owns a result expression may not state a second (KerML 8.3.4.8 validateFunctionResultExpressionMembership; pilot validateFunctionResultExpressionMembership). +package S52ConstraintSpecializationStatesSecondResultExpression { + private import ScalarValues::Real; + constraint def Base { in x : Real; x > 0.0 } + constraint def Sub :> Base { x > 1.0 } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml new file mode 100644 index 0000000..f093a80 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml @@ -0,0 +1,11 @@ +// Invalid: a redefining constraint usage inherits the redefined constraint's result expression and may not state a second (KerML 8.3.4.8 validateExpressionResultExpressionMembership; pilot validateExpressionResultExpressionMembership). +package S53RedefinedConstraintUsageStatesSecondResultExpression { + private import ScalarValues::Real; + requirement def Margin { + attribute x : Real; + require constraint enough { x > 0.0 } + } + requirement def Tight :> Margin { + require constraint :>> enough { x > 1.0 } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml new file mode 100644 index 0000000..c066a29 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml @@ -0,0 +1,7 @@ +// Invalid: a constraint usage reference-subsetting one that owns a result expression inherits it and may not state a second (KerML 8.3.4.8 validateExpressionResultExpressionMembership; pilot validateExpressionResultExpressionMembership). +package S54ReferencingConstraintUsageStatesSecondResultExpression { + private import ScalarValues::Real; + attribute x : Real; + constraint c { x > 0.0 } + constraint d ::> c { x > 1.0 } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml new file mode 100644 index 0000000..f5111d6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml @@ -0,0 +1,8 @@ +// Invalid: a viewpoint is a requirement and so a constraint, and may not inherit result expressions from two generals (KerML 8.3.4.8 validateFunctionResultExpressionMembership; pilot validateFunctionResultExpressionMembership). +package S55ViewpointInheritsSecondResultExpression { + private import ScalarValues::Real; + attribute x : Real; + constraint def A { x > 0.0 } + constraint def B { x < 9.0 } + viewpoint def V :> A, B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s86-end-with-direction.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s86-end-with-direction.sysml new file mode 100644 index 0000000..7289def --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s86-end-with-direction.sysml @@ -0,0 +1,7 @@ +// Invalid: an end feature cannot have a direction (KerML 8.3.3.3.4 validateFeatureEndNoDirection; pilot validateFeatureEndNoDirection). +package S52EndWithDirection { + part def A; + connection def K1 { end in a : A; end b : A; } + connection def K2 { end out a : A; end b : A; } + part def G { end inout a : A; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s87-end-derived-or-abstract.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s87-end-derived-or-abstract.sysml new file mode 100644 index 0000000..9c75f77 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s87-end-derived-or-abstract.sysml @@ -0,0 +1,7 @@ +// Invalid: an end feature cannot be derived, abstract, composite or portion (KerML 8.3.3.3.4 validateFeatureEndNotDerivedAbstractCompositeOrPortion; pilot validateFeatureEndNotDerivedAbstractCompositeOrPortion). +package S53EndDerivedOrAbstract { + part def A; + connection def K1 { end derived a : A; end b : A; } + connection def K2 { end abstract a : A; end b : A; } + connection def K3 { end variation a : A; end b : A; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml new file mode 100644 index 0000000..8354e5d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml @@ -0,0 +1,10 @@ +// Invalid: a cross feature declared ahead of its end's kind keyword must have the same type as the end, not a subtype of it (KerML 8.3.3.3 validateFeatureCrossFeatureType; pilot validateFeatureCrossFeatureType). +package S88CrossFeatureTypedNarrowerThanEnd { + part def A; part def B; + part def Sub1 :> A; + item g : A; + connection def Conn { + end x1 : Sub1 [0..1] :> g item x : A; + end y1 [0..1] item y : B; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s89-case-def-inherits-two-objectives.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s89-case-def-inherits-two-objectives.sysml new file mode 100644 index 0000000..b41367c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s89-case-def-inherits-two-objectives.sysml @@ -0,0 +1,7 @@ +// Invalid: A case definition inheriting an objective from each of two generals has two objectives (SysML 7.21 Cases; pilot validateCaseDefinitionOnlyOneObjective). +package S89CaseDefInheritsTwoObjectives { + requirement def R; + case def A { objective a : R; } + case def B { objective b : R; } + case def C :> A, B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s90-requirement-def-inherits-two-subjects.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s90-requirement-def-inherits-two-subjects.sysml new file mode 100644 index 0000000..28e9de3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s90-requirement-def-inherits-two-subjects.sysml @@ -0,0 +1,6 @@ +// Invalid: A requirement definition inheriting a subject from each of two generals has two subjects (SysML 7.20 Requirements; pilot validateRequirementDefinitionOnlyOneSubject). +package S90RequirementDefInheritsTwoSubjects { + requirement def A { subject a; } + requirement def B { subject b; } + requirement def C :> A, B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s91-case-references-second-objective.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s91-case-references-second-objective.sysml new file mode 100644 index 0000000..01b7bbf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s91-case-references-second-objective.sysml @@ -0,0 +1,7 @@ +// Invalid: A case usage inherits an objective from its definition and another from the case it reference-subsets, so it has two (SysML 7.21 Cases; pilot validateCaseUsageOnlyOneObjective). +package S91CaseReferencesSecondObjective { + requirement def R; + case def A { objective a : R; } + case b { objective b : R; } + case c : A ::> b; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s92-requirement-references-second-subject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s92-requirement-references-second-subject.sysml new file mode 100644 index 0000000..9bb30dc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s92-requirement-references-second-subject.sysml @@ -0,0 +1,6 @@ +// Invalid: A requirement usage inherits a subject from its definition and another from the requirement it reference-subsets, so it has two (SysML 7.20 Requirements; pilot validateRequirementUsageOnlyOneSubject). +package S92RequirementReferencesSecondSubject { + requirement def A { subject a; } + requirement b { subject b; } + requirement c : A ::> b; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml new file mode 100644 index 0000000..d16cdf3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml @@ -0,0 +1,14 @@ +// Invalid: An unnamed assertion derives no member name from the feature it references, so a qualified reference through its owner still reaches the referenced non-constraint (KerML 7.3.4.5 Feature names; SysML 7.19 Constraints; pilot validateAssertConstraintUsageReference). +package S93AssertThroughOwnerOfUnnamedAssertion { + part def H { + part q; + constraint c; + } + part h : H { + assert q; + } + part ctx { + assert h.q; + assert h.c; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-constructor-non-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-constructor-non-type.sysml new file mode 100644 index 0000000..a5d54ec --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-constructor-non-type.sysml @@ -0,0 +1,11 @@ +// Invalid: a constructor must instantiate a type, not a package (KerML 8.3.4.8 InstantiationExpression validateInstantiationExpressionInstantiatedType; pilot validateInstantiationExpressionInstantiatedType). +package SendConstructorNonType { + package Signals { + item def Sig; + } + part def Receiver; + action def A { + part target : Receiver; + action s send new Signals() to target; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-payload-non-behavior.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-payload-non-behavior.sysml new file mode 100644 index 0000000..8af50ed --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-payload-non-behavior.sysml @@ -0,0 +1,9 @@ +// Invalid: a send payload that is an invocation must invoke a behavior or a behavioral feature (KerML 8.3.4.8 InvocationExpression validateInvocationExpressionInstantiatedType; pilot validateInvocationExpressionInstantiatedType). +package SendPayloadNonBehavior { + attribute def Sig; + part def Receiver; + action def A { + part target : Receiver; + action s send Sig() to target; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-subaction-no-payload.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-subaction-no-payload.sysml new file mode 100644 index 0000000..af78bad --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/semantic/send-subaction-no-payload.sysml @@ -0,0 +1,11 @@ +// Invalid: a send that is a state subaction or a transition effect must have a payload (SysML v2 8.3.16 SendActionUsage validateSendActionUsagePayloadArgument; pilot validateSendActionUsagePayloadArgument, which its grammar enforces first: SysML.xtext:1511 SendNodeDeclaration requires the payload). +package SendSubactionNoPayload { + part def Receiver; + state def M { + part target : Receiver; + state a; + state b; + entry send to target; + transition first a do send to target then b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p01-public-root-import.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p01-public-root-import.kerml new file mode 100644 index 0000000..949e550 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p01-public-root-import.kerml @@ -0,0 +1,5 @@ +// Invalid: a root-namespace import must be private (KerML 8.2.3.5.2 validateImportTopLevelVisibility; pilot Import_RootNamspace_invalid.kerml.xt). +public import Base::Anything; +package P01PublicRootImport { + class C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p02-association-end-two-types.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p02-association-end-two-types.kerml new file mode 100644 index 0000000..6b4b738 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p02-association-end-two-types.kerml @@ -0,0 +1,9 @@ +// Invalid: an association end must have exactly one type (KerML 8.2.4.6.2 checkAssociationEndTypes; pilot validateAssociationEndTypes, AssociationTest_EndTypes_invalid.kerml.xt). +package P02AssociationEndTwoTypes { + class C1; + class C2; + assoc A { + end x : C1; + end y : C1, C2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p03-variable-in-datatype.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p03-variable-in-datatype.kerml new file mode 100644 index 0000000..2377333 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p03-variable-in-datatype.kerml @@ -0,0 +1,6 @@ +// Invalid: a variable feature must be owned by an occurrence type (KerML 8.3.3.3 validateFeatureOwnedVariable; pilot validateFeatureIsVariable, Feature_variable_invalid.kerml.xt). +package P03VariableInDatatype { + datatype D { + var feature z; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p04-nonunique-subsets-unique.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p04-nonunique-subsets-unique.kerml new file mode 100644 index 0000000..c3805da --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p04-nonunique-subsets-unique.kerml @@ -0,0 +1,7 @@ +// Invalid: a nonunique feature cannot subset a unique one (KerML 8.3.3.3 validateSubsettingUniquenessConformance; pilot Feature_nonunique_invalid.kerml.xt). +package P04NonuniqueSubsetsUnique { + class C { + feature a : C [*]; + feature b : C [*] nonunique subsets a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p05-single-chaining-feature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p05-single-chaining-feature.kerml new file mode 100644 index 0000000..87a6b14 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p05-single-chaining-feature.kerml @@ -0,0 +1,7 @@ +// Invalid: a feature chain needs at least two chaining features (KerML 8.3.3.3 validateFeatureChainingFeaturesNotOne; pilot validateFeatureChainingFeatureNotOne, FeatureChain_invalid.kerml.xt). +package P05SingleChainingFeature { + class C { + feature a : C; + } + feature c chains C::a; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p06-private-member-reference.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p06-private-member-reference.kerml new file mode 100644 index 0000000..f968efd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p06-private-member-reference.kerml @@ -0,0 +1,7 @@ +// Invalid: a private member is not visible outside its namespace (KerML 8.2.3.5 name resolution; pilot Import_All.kerml.xt). +package P06PrivateMemberReference { + package A { + private class X; + } + class Y specializes A::X; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p07-extraneous-closing-brace.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p07-extraneous-closing-brace.kerml new file mode 100644 index 0000000..7da4776 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p07-extraneous-closing-brace.kerml @@ -0,0 +1,5 @@ +// Invalid: a stray '}' after the root member is extraneous input (KerML.xtext RootNamespace; pilot ParsingTests_Import_Visibility.kerml.xt). +package P07ExtraneousClosingBrace { + class C; +} +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p08-variant-outside-variation.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p08-variant-outside-variation.sysml new file mode 100644 index 0000000..bc22cb9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p08-variant-outside-variation.sysml @@ -0,0 +1,8 @@ +// Invalid: A variant must be an owned member of a variation (SysML 7.9 validateVariationMembershipOwningNamespace; pilot Variability_invalid.sysml.xt:55). +package P08VariantOutsideVariation { + part def B; + part b1 : B; + part def PartChoices :> B { + variant b1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p09-variation-member-not-variant.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p09-variation-member-not-variant.sysml new file mode 100644 index 0000000..ac0ff14 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p09-variation-member-not-variant.sysml @@ -0,0 +1,7 @@ +// Invalid: An owned usage of a variation must be a variant (SysML 7.9 validateDefinitionVariationMembership; pilot Variability_invalid.sysml.xt:46). +package P09VariationMemberNotVariant { + variation attribute def AttributeChoices { + variant attribute a1; + attribute a2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p10-variation-specializes-variation.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p10-variation-specializes-variation.sysml new file mode 100644 index 0000000..c33a851 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p10-variation-specializes-variation.sysml @@ -0,0 +1,7 @@ +// Invalid: A variation must not specialize another variation (SysML 7.9 validateVariationSpecialization; pilot Variability_invalid.sysml.xt:50). +package P10VariationSpecializesVariation { + variation attribute def AttributeChoices { + variant attribute a1; + } + variation attribute def AttributeChoices1 :> AttributeChoices; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p11-metadata-body-not-evaluable.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p11-metadata-body-not-evaluable.sysml new file mode 100644 index 0000000..1afabe6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p11-metadata-body-not-evaluable.sysml @@ -0,0 +1,11 @@ +// Invalid: A metadata body feature value must be model-level evaluable (SysML 7.24 checkMetadataBodyFeature; pilot MetadataUsage_Invalid.sysml.xt:82). +package P11MetadataBodyNotEvaluable { + metadata def A { + attribute x; + } + attribute a { + @A { + x = ~3; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p12-filter-integer-condition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p12-filter-integer-condition.sysml new file mode 100644 index 0000000..3818ae3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p12-filter-integer-condition.sysml @@ -0,0 +1,4 @@ +// Invalid: An element filter condition must have a Boolean result (KerML 8.2.3.2 validateElementFilterMembershipIsBoolean; pilot expressions filter rows). +package P12FilterWithoutBooleanResult { + filter 1 + 2 * 3; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p13-state-two-entry-actions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p13-state-two-entry-actions.sysml new file mode 100644 index 0000000..deb8810 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p13-state-two-entry-actions.sysml @@ -0,0 +1,7 @@ +// Invalid: A state may have at most one entry action (SysML 7.16 validateStateDefinitionSubactionKind; pilot StateSubactions_invalid.sysml.xt). +package P13StateTwoEntryActions { + state def S { + entry action a1; + entry action a2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p14-requirement-two-subjects.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p14-requirement-two-subjects.sysml new file mode 100644 index 0000000..7395cfa --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p14-requirement-two-subjects.sysml @@ -0,0 +1,8 @@ +// Invalid: Only one subject is allowed (SysML 7.20 validateRequirementDefinitionOnlyOneSubject; pilot RequirementSubject_Invalid.sysml.xt). +package P14RequirementTwoSubjects { + part def B; + requirement def R { + subject s1 : B; + subject s2 : B; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p15-attribute-typed-by-part-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p15-attribute-typed-by-part-def.sysml new file mode 100644 index 0000000..889ef9c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p15-attribute-typed-by-part-def.sysml @@ -0,0 +1,5 @@ +// Invalid: An attribute must be typed by attribute definitions (SysML 7.6 validateAttributeUsageType; pilot AttributeUsage_invalid.sysml.xt). +package P15AttributeTypedByPartDef { + part def A; + attribute a : A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p16-part-typed-by-attribute-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p16-part-typed-by-attribute-def.sysml new file mode 100644 index 0000000..6d3e01f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p16-part-typed-by-attribute-def.sysml @@ -0,0 +1,5 @@ +// Invalid: An occurrence, item or part must be typed by occurrence definitions (SysML 7.9 validateOccurrenceUsageType; pilot PartUsage_invalid.sysml.xt). +package P16PartTypedByAttributeDef { + attribute def AttDef; + part p1 : AttDef; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p17-calc-two-return-parameters.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p17-calc-two-return-parameters.sysml new file mode 100644 index 0000000..ece82df --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p17-calc-two-return-parameters.sysml @@ -0,0 +1,8 @@ +// Invalid: Only one return parameter is allowed (SysML 7.15 validateReturnParameterMembership; pilot validateFunctionResultParameterMembership, CalculationUsage_Invalid1.sysml.xt). +package P17CalcTwoReturnParameters { + attribute def T; + calc def C { + return r1 : T; + return r2 : T; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-two-types.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-two-types.sysml new file mode 100644 index 0000000..880e64f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-two-types.sysml @@ -0,0 +1,6 @@ +// Invalid: An enumeration must be typed by one enumeration definition (SysML 7.7 validateEnumerationUsageType; pilot EnumerationUsage_invalid.sysml.xt). +package P18EnumTwoTypes { + enum def E { e1; } + enum def EE { ee1; } + enum e3 : E, EE; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-value-typed-outside-enumeration.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-value-typed-outside-enumeration.sysml new file mode 100644 index 0000000..8aae037 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p18-enum-value-typed-outside-enumeration.sysml @@ -0,0 +1,8 @@ +// Invalid: An enumeration must be typed by one enumeration definition — a literal value types the enumerated value by Integer, which the enumeration is not (SysML 7.7 validateEnumerationUsageType; pilot SysMLValidator checkOneType). +package P18EnumValueTypedOutsideEnumeration { + private import ScalarValues::Real; + enum def E :> Real { + a = 4.0; + b = 3; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p19-parallel-state-with-transition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p19-parallel-state-with-transition.sysml new file mode 100644 index 0000000..7c3220f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p19-parallel-state-with-transition.sysml @@ -0,0 +1,8 @@ +// Invalid: A parallel state cannot have successions or transitions (SysML 7.16 validateStateDefinitionParallelSubactions; pilot StateUsage_invalid.sysml.xt). +package P19ParallelStateWithTransition { + state def S parallel { + state s1; + state s2; + first s1 then s2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p20-connection-with-one-end.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p20-connection-with-one-end.sysml new file mode 100644 index 0000000..ac8ac6d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p20-connection-with-one-end.sysml @@ -0,0 +1,8 @@ +// Invalid: A connector must have at least two related elements (KerML 8.3.3.1 validateConnectorRelatedElements; pilot validateConnectorRelatedFeatures, Connector_Invalid.sysml.xt). +package P20ConnectionWithOneEnd { + part def B; + part b0 : B; + part p { + connection { end ::> b0; } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p21-filter-constructor-condition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p21-filter-constructor-condition.sysml new file mode 100644 index 0000000..8697c18 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p21-filter-constructor-condition.sysml @@ -0,0 +1,7 @@ +// Invalid: A filter condition must have a Boolean result (SysML 7.24 checkPackageFilterCondition; pilot validateElementFilterMembershipIsBoolean, MetadataUsage_Invalid.sysml.xt:74). +package P21FilterWithoutBooleanResult { + metadata def A { + attribute x : ScalarValues::Integer; + } + filter new A(null, 1); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p22-filter-not-model-level-evaluable.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p22-filter-not-model-level-evaluable.sysml new file mode 100644 index 0000000..55b1f6d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p22-filter-not-model-level-evaluable.sysml @@ -0,0 +1,8 @@ +// Invalid: A filter condition must be model-level evaluable (SysML 7.24 checkPackageFilterCondition; pilot validateElementFilterMembershipIsModelLevelEvaluable, MetadataUsage_Invalid.sysml.xt:68). +package P22FilterNotModelLevelEvaluable { + metadata def A { + attribute z : ScalarValues::Boolean; + } + calc def f { in x : ScalarValues::Boolean; return : ScalarValues::Boolean; } + filter f((as A).z); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p23-metadata-body-feature-not-redefining.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p23-metadata-body-feature-not-redefining.sysml new file mode 100644 index 0000000..b604547 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p23-metadata-body-feature-not-redefining.sysml @@ -0,0 +1,12 @@ +// Invalid: A metadata body feature must redefine an owning-type feature (SysML 7.24 checkMetadataFeatureRedefinition; pilot MetadataUsage_Invalid.sysml.xt:93). +package P23MetadataBodyFeatureNotRedefining { + metadata def A { + attribute x : ScalarValues::Integer; + } + attribute bad; + attribute a { + @A { + bad; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p24-metadata-abstract-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p24-metadata-abstract-type.sysml new file mode 100644 index 0000000..cf20aea --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p24-metadata-abstract-type.sysml @@ -0,0 +1,6 @@ +// Invalid: A metadata usage must have a concrete type (SysML 7.24 checkMetadataUsageConcreteType; pilot validateMetadataFeatureMetadataNotAbstract, MetadataUsage_Invalid.sysml.xt:104). +package P24MetadataAbstractType { + item p { + @Metaobjects::Metaobject; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p25-two-individual-definitions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p25-two-individual-definitions.sysml new file mode 100644 index 0000000..8d7be01 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p25-two-individual-definitions.sysml @@ -0,0 +1,8 @@ +// Invalid: At most one individual definition is allowed (SysML 7.9 validateOccurrenceUsageIndividualDefinition; pilot IndividualUsage_Invalid.sysml.xt:36). +package P25TwoIndividualDefinitions { + part def A; + part def B; + individual def A_1 :> A; + individual def B_1 :> B; + individual two_types : A_1, B_1; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p26-port-def-nonreferential-usage.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p26-port-def-nonreferential-usage.sysml new file mode 100644 index 0000000..f7c3dfb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p26-port-def-nonreferential-usage.sysml @@ -0,0 +1,7 @@ +// Invalid: Owned usages of a port definition (other than ports) must be referential (SysML 7.13 validatePortDefinitionOwnedUsagesNotComposite; pilot PortUsage_Invalid.sysml.xt:33). +package P26PortDefNonReferentialUsage { + part def B; + port def pd1 { + part b2 : B; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p27-interface-end-not-port.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p27-interface-end-not-port.sysml new file mode 100644 index 0000000..506e1dd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p27-interface-end-not-port.sysml @@ -0,0 +1,13 @@ +// Invalid: An interface end must be a port (SysML 7.13 validateInterfaceUsageEnd; pilot InterfaceUsage_Invalid.sysml.xt:63). +package P27InterfaceEndNotPort { + part def Fuel; + port def FuelInPort; + part vehicle { + part fuel : Fuel; + port inPort : FuelInPort; + interface bad { + end part ::> fuel; + end port ::> inPort; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p28-package-level-feature-redefined.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p28-package-level-feature-redefined.sysml new file mode 100644 index 0000000..be9f7e2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p28-package-level-feature-redefined.sysml @@ -0,0 +1,6 @@ +// Invalid: A package-level feature cannot be redefined (KerML 7.4.7 validateRedefinitionFeaturingTypes; pilot Redefinition_OwningType_Invalid.sysml.xt:28). +package P28PackageLevelFeatureRedefined { + part def Wheel; + part wheel : Wheel; + part wheel1 redefines wheel; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p29-verify-outside-objective.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p29-verify-outside-objective.sysml new file mode 100644 index 0000000..4d85ac7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p29-verify-outside-objective.sysml @@ -0,0 +1,8 @@ +// Invalid: A requirement verification must be in the objective of a verification case (SysML 7.21 validateRequirementVerificationMembershipOwningType; pilot Verification_invalid.sysml.xt:30). +package P29VerifyOutsideObjective { + requirement def R; + requirement r : R; + requirement def R2 { + verify r; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p30-two-view-renderings.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p30-two-view-renderings.sysml new file mode 100644 index 0000000..68316fc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p30-two-view-renderings.sysml @@ -0,0 +1,8 @@ +// Invalid: A view may have at most one view rendering (SysML 7.23 validateViewUsageOnlyOneRendering; pilot ViewRendering_invalid.sysml.xt:31). +package P30TwoViewRenderings { + rendering r; + view v { + render rendering r4; + render rendering r5; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p31-redefinition-incompatible-direction.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p31-redefinition-incompatible-direction.sysml new file mode 100644 index 0000000..46a4cc3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p31-redefinition-incompatible-direction.sysml @@ -0,0 +1,11 @@ +// Invalid: A redefining feature must have a compatible direction (KerML 7.4.7 validateRedefinitionDirection; pilot validateRedefinitionDirectionConformance, PortUsage_Invalid.sysml.xt:57). +package P31RedefinitionIncompatibleDirection { + port def OutPort { + out ref anout; + } + part p { + port aport : OutPort { + in ref redefines anout; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p32-redefinition-same-featuring-type.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p32-redefinition-same-featuring-type.sysml new file mode 100644 index 0000000..e0db81b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p32-redefinition-same-featuring-type.sysml @@ -0,0 +1,11 @@ +// Invalid: Featuring types of redefining feature and redefined feature cannot be the same (KerML 7.4.7 validateRedefinitionFeaturingTypes; pilot Redefinition_OwningType_Invalid.sysml.xt:38). +package P32RedefinitionSameFeaturingType { + part def Engine; + part def B { + alias eng1 for Vehicle::eng; + } + part def Vehicle specializes B { + part eng : Engine; + part smallEng : Engine redefines eng1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p33-individual-typed-by-plain-def.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p33-individual-typed-by-plain-def.sysml new file mode 100644 index 0000000..8b0c54c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p33-individual-typed-by-plain-def.sysml @@ -0,0 +1,5 @@ +// Invalid: An individual must be typed by one individual definition (SysML 7.9 validateOccurrenceUsageIndividualUsage; pilot IndividualUsage_Invalid.sysml.xt:39). +package P33IndividualTypedByPlainDef { + part def B; + individual b_1_1 : B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p34-accepter-source-not-state.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p34-accepter-source-not-state.sysml new file mode 100644 index 0000000..7dbf709 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/negative/xpect/p34-accepter-source-not-state.sysml @@ -0,0 +1,9 @@ +// Invalid: A transition with an accepter must have a state as its source (SysML 7.16 States; pilot validateTransitionUsageTriggerActions, TransitionUsage_invalid.sysml.xt:54). +package P34AccepterSourceNotState { + item def A; + state def S { + entry action init; + transition init accept A then s1; + state s1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActionUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActionUsageType.sysml new file mode 100644 index 0000000..75c5413 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActionUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateActionUsageType +// Expect: error: An action must be typed by action definitions. +package P { part def D; action a : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActorMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActorMembershipOwningType.sysml new file mode 100644 index 0000000..3a86a57 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateActorMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateActorMembershipOwningType +// Expect: error: 'actor' declares an actor of a requirement or case and is only allowed in a requirement or case body +package P { part def D; part def Q { actor a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAllocationUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAllocationUsageType.sysml new file mode 100644 index 0000000..29aa241 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAllocationUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateAllocationUsageType +// Expect: error: An allocation must be typed by allocation definitions. +package P { part def D; part def E { part a : D; part b : D; allocation al : D allocate a to b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnalysisCaseUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnalysisCaseUsageType.sysml new file mode 100644 index 0000000..696af26 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnalysisCaseUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateAnalysisCaseUsageType +// Expect: error: An analysis case must be typed by one analysis case definition. +package P { analysis def A1; analysis def A2; analysis a : A1, A2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnnotationAnnotatedElementOwnership.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnnotationAnnotatedElementOwnership.kerml new file mode 100644 index 0000000..35a8dac --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAnnotationAnnotatedElementOwnership.kerml @@ -0,0 +1,6 @@ +// Census: validateAnnotationAnnotatedElementOwnership +// Expect: error: Must own its annotating element +package P { + class A; + comment C about A, C /* an annotating element cannot annotate itself */ +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssertConstraintUsageReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssertConstraintUsageReference.sysml new file mode 100644 index 0000000..4c48ed3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssertConstraintUsageReference.sysml @@ -0,0 +1,3 @@ +// Census: validateAssertConstraintUsageReference +// Expect: error: assert target must be a constraint usage +package P { part def D { part x : D; assert x; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferent.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferent.sysml new file mode 100644 index 0000000..e1b2004 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferent.sysml @@ -0,0 +1,3 @@ +// Census: validateAssignmentActionUsageReferent +// Expect: error: An assignment must have a referent. +package P { part def D; action def A { assign D := 1; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml new file mode 100644 index 0000000..6c9e923 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml @@ -0,0 +1,3 @@ +// Census: validateAssignmentActionUsageReferentIsTimeVarying +// Expect: error: Referent must be time varying. +package P { attribute def K { attribute x : ScalarValues::Integer; } action def A { in k : K; assign k.x := 1; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationBinarySpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationBinarySpecialization.kerml new file mode 100644 index 0000000..c491cab --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationBinarySpecialization.kerml @@ -0,0 +1,6 @@ +// Census: validateAssociationBinarySpecialization +// Expect: error: has 3 ends but specializes a binary link +package P { + class A; class B; class C; + assoc Bin specializes Links::BinaryLink { end a : A; end b : B; end c : C; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationEndTypes.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationEndTypes.kerml new file mode 100644 index 0000000..a018874 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationEndTypes.kerml @@ -0,0 +1,6 @@ +// Census: validateAssociationEndTypes +// Expect: error: An association end must have exactly one type +package P { + class A; class B; + assoc L { end a : A, B; end b : B; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationRelatedTypes.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationRelatedTypes.kerml new file mode 100644 index 0000000..feb7e7f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAssociationRelatedTypes.kerml @@ -0,0 +1,6 @@ +// Census: validateAssociationRelatedTypes +// Expect: error: Must have at least two related elements +package P { + class T; + assoc A { end a : T; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageEnumerationType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageEnumerationType.sysml new file mode 100644 index 0000000..510e8dd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageEnumerationType.sysml @@ -0,0 +1,3 @@ +// Census: validateAttributeUsageEnumerationType +// Expect: error: An enumeration must be typed by one enumeration definition. +package P { enum def E { e1; } enum def F { f1; } enum x : E, F; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageType.sysml new file mode 100644 index 0000000..f362af5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateAttributeUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateAttributeUsageType +// Expect: error: An attribute must be typed by attribute definitions. +package P { part def D; attribute a : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBehaviorSpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBehaviorSpecialization.kerml new file mode 100644 index 0000000..05c2746 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBehaviorSpecialization.kerml @@ -0,0 +1,6 @@ +// Census: validateBehaviorSpecialization +// Expect: error: Cannot specialize structure +package P { + struct S; + behavior B specializes S; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorIsBinary.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorIsBinary.kerml new file mode 100644 index 0000000..6c91134 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorIsBinary.kerml @@ -0,0 +1,9 @@ +// Census: validateBindingConnectorIsBinary +// Expect: error: Binding connector must be binary +package P { + class A; + class C { + feature x : A; feature y : A; feature z : A; + binding b of x = y { end feature e references z; } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.kerml new file mode 100644 index 0000000..cd6d2ea --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.kerml @@ -0,0 +1,5 @@ +// Census: validateBindingConnectorTypeConformance +// Expect: warning: Bound features should have conforming types +package P { + class C { feature x : ScalarValues::String; feature y : ScalarValues::Integer; binding x = y; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.result.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.result.kerml new file mode 100644 index 0000000..6b4912c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.result.kerml @@ -0,0 +1,7 @@ +// Census: validateBindingConnectorTypeConformance +// Expect: warning: Bound features should have conforming types +package P { + datatype C; datatype D; + feature c : C; + function F { return r : D; c } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.satisfy.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.satisfy.sysml new file mode 100644 index 0000000..2c66c09 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.satisfy.sysml @@ -0,0 +1,9 @@ +// Census: validateBindingConnectorTypeConformance +// Expect: warning: Bound features should have conforming types +package P { + part def PD; item def ID; + item i : ID; + requirement def R { subject s : PD; } + requirement r : R; + satisfy r by i; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.subject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.subject.sysml new file mode 100644 index 0000000..a68cf10 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateBindingConnectorTypeConformance.subject.sysml @@ -0,0 +1,6 @@ +// Census: validateBindingConnectorTypeConformance +// Expect: warning: Bound features should have conforming types +package P { + part def PD; item def ID; + requirement def R { subject s : PD; requirement nested { subject n : ID; } } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCalculationUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCalculationUsageType.sysml new file mode 100644 index 0000000..988107b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCalculationUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateCalculationUsageType +// Expect: error: A calculation must be typed by one calculation definition. +package P { calc def C1 { return : ScalarValues::Integer; 1 } calc def C2 { return : ScalarValues::Integer; 2 } calc c : C1, C2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneObjective.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneObjective.sysml new file mode 100644 index 0000000..56a9fd4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneObjective.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseDefinitionOnlyOneObjective +// Expect: error: Only one objective is allowed. +package P { case def C { objective o1; objective o2; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneSubject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneSubject.sysml new file mode 100644 index 0000000..66a13f7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionOnlyOneSubject.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseDefinitionOnlyOneSubject +// Expect: error: Only one subject is allowed. +package P { part def D; case def C { subject a : D; subject b : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionSubjectParameterPosition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionSubjectParameterPosition.sysml new file mode 100644 index 0000000..3dced9a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseDefinitionSubjectParameterPosition.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseDefinitionSubjectParameterPosition +// Expect: error: Subject must be first parameter. +package P { part def D; case def C { in x : D; subject a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneObjective.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneObjective.sysml new file mode 100644 index 0000000..ff7d6f6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneObjective.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseUsageOnlyOneObjective +// Expect: error: Only one objective is allowed. +package P { case def C; case c : C { objective o1; objective o2; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneSubject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneSubject.sysml new file mode 100644 index 0000000..de6dc4a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageOnlyOneSubject.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseUsageOnlyOneSubject +// Expect: error: Only one subject is allowed. +package P { part def D; case def C; case c : C { subject a : D; subject b : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageSubjectParameterPosition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageSubjectParameterPosition.sysml new file mode 100644 index 0000000..2d0b1a5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageSubjectParameterPosition.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseUsageSubjectParameterPosition +// Expect: error: Subject must be first parameter. +package P { part def D; case def C; case c : C { in x : D; subject a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageType.sysml new file mode 100644 index 0000000..ccd31f1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCaseUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateCaseUsageType +// Expect: error: A case must be typed by one case definition. +package P { case def C1; case def C2; case c : C1, C2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.connection.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.connection.sysml new file mode 100644 index 0000000..b8f64c3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.connection.sysml @@ -0,0 +1,6 @@ +// Census: validateClassSpecialization +// Expect: error: Cannot specialize attribute definition +package P { + part def X; attribute def A; + connection def C :> A { end x1 : X; end x2 : X; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.kerml new file mode 100644 index 0000000..096c9b1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.kerml @@ -0,0 +1,6 @@ +// Census: validateClassSpecialization +// Expect: error: Cannot specialize data type or association +package P { + datatype D; + class C specializes D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.subsets.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.subsets.kerml new file mode 100644 index 0000000..e5489e7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.subsets.kerml @@ -0,0 +1,7 @@ +// Census: validateClassSpecialization +// Expect: error: Cannot specialize data type or association +package P { + class X; + assoc A { end feature a : X; end feature b : X; } + class C :> A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.sysml new file mode 100644 index 0000000..3e407e3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassSpecialization.sysml @@ -0,0 +1,3 @@ +// Census: validateClassSpecialization +// Expect: error: Cannot specialize attribute definition +package P { attribute def A; item def I :> A; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassifierDefaultSupertype.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassifierDefaultSupertype.kerml new file mode 100644 index 0000000..a9f216e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateClassifierDefaultSupertype.kerml @@ -0,0 +1,6 @@ +// Census: validateClassifierDefaultSupertype +// Expect: error: Must directly or indirectly specialize Objects::Object +package P { + class D; + struct S ~ D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectionUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectionUsageType.sysml new file mode 100644 index 0000000..f8b2598 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectionUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateConnectionUsageType +// Expect: error: A connection must be typed by connection definitions. +package P { part def D; part def E { part a : D; part b : D; connection c : D connect a to b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorBinarySpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorBinarySpecialization.kerml new file mode 100644 index 0000000..496fee6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorBinarySpecialization.kerml @@ -0,0 +1,8 @@ +// Census: validateConnectorBinarySpecialization +// Expect: error: has 3 ends but specializes a binary link +package P { + class T { + feature x : T; feature y : T; feature z : T; + connector c : Links::BinaryLink (x, y, z); + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorRelatedFeatures.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorRelatedFeatures.sysml new file mode 100644 index 0000000..fec3ab4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorRelatedFeatures.sysml @@ -0,0 +1,9 @@ +// Census: validateConnectorRelatedFeatures +// Expect: error: Must have at least two related elements +package P { + part def B; + part b0 : B; + part p { + connection { end ::> b0; } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorTypeFeaturing.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorTypeFeaturing.kerml new file mode 100644 index 0000000..834a42f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConnectorTypeFeaturing.kerml @@ -0,0 +1,6 @@ +// Census: validateConnectorTypeFeaturing +// Expect: error: Must be an accessible feature (use dot notation for nesting) +package P { + class A { feature x; } + class B { feature y; connector k from A::x to y; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml new file mode 100644 index 0000000..4008e86 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml @@ -0,0 +1,3 @@ +// Census: validateConstructorExpressionNoDuplicateFeatureRedefinition +// Expect: error: x of C is already bound by an earlier argument +package P { class T; class C { feature x : T; } feature t : T; feature c : C = new C(x = t, x = t); } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeIncomingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeIncomingSuccessions.sysml new file mode 100644 index 0000000..58f6154 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeIncomingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateControlNodeIncomingSuccessions +// Expect: error: succession into fork f has target multiplicity [0..1] +package P { action def A { action a; fork f; action b; action c; succession first a then [0..1] f; first f then b; first f then c; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOutgoingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOutgoingSuccessions.sysml new file mode 100644 index 0000000..6608a0f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOutgoingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateControlNodeOutgoingSuccessions +// Expect: error: succession out of join j has source multiplicity [0..1] +package P { action def A { action a; action b; join j; action c; first a then j; first b then j; succession first [0..1] j then c; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOwningType.sysml new file mode 100644 index 0000000..9d7c78a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateControlNodeOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateControlNodeOwningType +// Expect: error: fork f is declared in constraint def C, which is not an action +package P { constraint def C { fork f; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossedFeature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossedFeature.kerml new file mode 100644 index 0000000..07c94bd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossedFeature.kerml @@ -0,0 +1,7 @@ +// Census: validateCrossSubsettingCrossedFeature +// Expect: error: Cross subsetting must chain through an opposite end feature +package P { + class A { feature ax : A; } + class B { feature bx : A; } + assoc L { end a : A crosses a.ax; end b : B; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossingFeature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossingFeature.kerml new file mode 100644 index 0000000..f0716a5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateCrossSubsettingCrossingFeature.kerml @@ -0,0 +1,5 @@ +// Census: validateCrossSubsettingCrossingFeature +// Expect: error: Cross subsetting must be owned by one of two or more end features +package P { + class A { feature p : A; feature q : A crosses p; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.kerml new file mode 100644 index 0000000..3d984df --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.kerml @@ -0,0 +1,6 @@ +// Census: validateDataTypeSpecialization +// Expect: error: Cannot specialize class or association +package P { + class C; + datatype D specializes C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.subsets.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.subsets.kerml new file mode 100644 index 0000000..a932977 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.subsets.kerml @@ -0,0 +1,7 @@ +// Census: validateDataTypeSpecialization +// Expect: error: Cannot specialize class or association +package P { + class X; + assoc A { end feature a : X; end feature b : X; } + datatype D :> A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.sysml new file mode 100644 index 0000000..80c763c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDataTypeSpecialization.sysml @@ -0,0 +1,3 @@ +// Census: validateDataTypeSpecialization +// Expect: error: Cannot specialize item definition +package P { item def I; attribute def A :> I; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeIncomingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeIncomingSuccessions.sysml new file mode 100644 index 0000000..bd50a12 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeIncomingSuccessions.sysml @@ -0,0 +1,6 @@ +// Census: validateDecisionNodeIncomingSuccessions +// Expect: error: decide d has 2 incoming successions +package P { + private import ScalarValues::Boolean; + action def A { in attribute go : Boolean; action a; action b; decide d; action c; action e; first a then d; first b then d; first d if go then c; first d if not go then e; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeOutgoingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeOutgoingSuccessions.sysml new file mode 100644 index 0000000..6daa6c2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDecisionNodeOutgoingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateDecisionNodeOutgoingSuccessions +// Expect: error: succession out of decide d has target multiplicity [1] +package P { action def A { action a; decide d; action b; action c; first a then d; succession first d then [1] b; succession first d then [0..1] c; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationMembership.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationMembership.sysml new file mode 100644 index 0000000..2ba0f6d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationMembership.sysml @@ -0,0 +1,3 @@ +// Census: validateDefinitionVariationMembership +// Expect: error: An owned usage of a variation must be a variant. +package P { abstract variation part def V { part a; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationSpecialization.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationSpecialization.sysml new file mode 100644 index 0000000..122a8d3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateDefinitionVariationSpecialization.sysml @@ -0,0 +1,3 @@ +// Census: validateDefinitionVariationSpecialization +// Expect: error: A variation must not specialize another variation. +package P { abstract variation part def V1; abstract variation part def V2 :> V1; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsBoolean.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsBoolean.kerml new file mode 100644 index 0000000..45aad01 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsBoolean.kerml @@ -0,0 +1,5 @@ +// Census: validateElementFilterMembershipIsBoolean +// Expect: error: Must have a Boolean result +package P { + package Q { filter 1; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml new file mode 100644 index 0000000..054f129 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml @@ -0,0 +1,6 @@ +// Census: validateElementFilterMembershipIsModelLevelEvaluable +// Expect: error: Must be model-level evaluable +package P { + calc def Sum { in a : ScalarValues::Integer; return : ScalarValues::Integer = a; } + package Q { filter Sum(1) == 1; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEnumerationUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEnumerationUsageType.sysml new file mode 100644 index 0000000..576868b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEnumerationUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateEnumerationUsageType +// Expect: error: An enumeration must be typed by one enumeration definition. +package P { enum def E { e1; } attribute def A; enum x : A; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEventOccurrenceUsageReferent.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEventOccurrenceUsageReferent.sysml new file mode 100644 index 0000000..140dde4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateEventOccurrenceUsageReferent.sysml @@ -0,0 +1,3 @@ +// Census: validateEventOccurrenceUsageReferent +// Expect: error: Must reference an occurrence. +package P { part def D { attribute a : ScalarValues::Real; event a; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExhibitStateUsageReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExhibitStateUsageReference.sysml new file mode 100644 index 0000000..856f31d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExhibitStateUsageReference.sysml @@ -0,0 +1,3 @@ +// Census: validateExhibitStateUsageReference +// Expect: error: Must reference a state. +package P { action def Act; part def D { action a : Act; exhibit a; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExposeOwningNamespace.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExposeOwningNamespace.sysml new file mode 100644 index 0000000..a770019 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExposeOwningNamespace.sysml @@ -0,0 +1,3 @@ +// Census: validateExposeOwningNamespace +// Expect: error: expose is only allowed in a view usage body +package P { part def D; part def E { expose D::*; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.kerml new file mode 100644 index 0000000..68a50ba --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.kerml @@ -0,0 +1,7 @@ +// Census: validateExpressionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + function F1 { 1 } + function F2 { 2 } + expr e : F1, F2; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.sysml new file mode 100644 index 0000000..aa28915 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.sysml @@ -0,0 +1,12 @@ +// Census: validateExpressionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + private import ScalarValues::Real; + requirement def Margin { + attribute x : Real; + require constraint enough { x > 0.0 } + } + requirement def Tight :> Margin { + require constraint :>> enough { x > 1.0 } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.typed.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.typed.kerml new file mode 100644 index 0000000..d24ad84 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultExpressionMembership.typed.kerml @@ -0,0 +1,9 @@ +// Census: validateExpressionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + class T; + feature a : T; + feature b : T; + function F { a } + expr e : F { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultParameterMembership.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultParameterMembership.kerml new file mode 100644 index 0000000..3d301fa --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateExpressionResultParameterMembership.kerml @@ -0,0 +1,5 @@ +// Census: validateExpressionResultParameterMembership +// Expect: error: Only one return parameter is allowed +package P { + expr e { return r1 : ScalarValues::Integer; return r2 : ScalarValues::Integer; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainExpressionFeatureConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainExpressionFeatureConformance.kerml new file mode 100644 index 0000000..54c6eb8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainExpressionFeatureConformance.kerml @@ -0,0 +1,9 @@ +// Census: validateFeatureChainExpressionFeatureConformance +// Expect: error: Must be a valid feature +package K41ChainExpressionToNestedClass { + class A { + class N; + } + feature a : A; + feature f : A = a.N; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureConformance.kerml new file mode 100644 index 0000000..1e21196 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureConformance.kerml @@ -0,0 +1,10 @@ +// Census: validateFeatureChainingFeatureConformance +// Expect: error: Must be a valid feature +package P { + class B { feature y : B; } + class A { alias z for B::y; } + class K { + feature k : A; + feature r references k.z; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureNotOne.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureNotOne.kerml new file mode 100644 index 0000000..a01a291 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeatureNotOne.kerml @@ -0,0 +1,7 @@ +// Census: validateFeatureChainingFeatureNotOne +// Expect: error: Cannot have only one chaining feature +package P { + class A { feature b; } + feature a : A; + feature c chains a; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeaturesNotSelf.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeaturesNotSelf.kerml new file mode 100644 index 0000000..85f6fce --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureChainingFeaturesNotSelf.kerml @@ -0,0 +1,8 @@ +// Census: validateFeatureChainingFeaturesNotSelf +// Expect: error: Feature cannot have itself in a feature chain +package K12ChainThroughSelf { + class C { + feature a : C; + feature b chains a.b; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureConstantIsVariable.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureConstantIsVariable.sysml new file mode 100644 index 0000000..acbe069 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureConstantIsVariable.sysml @@ -0,0 +1,6 @@ +// Census: validateFeatureConstantIsVariable +// Expect: error: Only a variable feature can be constant +package P { + private import ScalarValues::*; + attribute def A { constant attribute x : Integer; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureSpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureSpecialization.kerml new file mode 100644 index 0000000..2b9afce --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureSpecialization.kerml @@ -0,0 +1,14 @@ +// Census: validateFeatureCrossFeatureSpecialization +// Expect: error: Cross feature must specialized redefined-end cross features +package AssociationTest { + class C1 { feature a : C2; } + class C2 { feature b : C1; feature c subsets b; } + assoc A1 { + end x : C1 crosses y.b; + end y : C2 crosses y.b; + } + assoc A2 specializes A1 { + end x : C1 crosses y.c; + end y : C2 crosses x.a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureType.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureType.kerml new file mode 100644 index 0000000..3c7bc60 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureCrossFeatureType.kerml @@ -0,0 +1,8 @@ +// Census: validateFeatureCrossFeatureType +// Expect: error: Cross feature must have same type as feature +package P { + class X; + class A { feature ax : A; } + class B { feature bx : X; } + assoc L { end a : A crosses b.bx; end b : B crosses a.ax; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndFeatureMultiplicity.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndFeatureMultiplicity.kerml new file mode 100644 index 0000000..b3f802d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndFeatureMultiplicity.kerml @@ -0,0 +1,6 @@ +// Census: validateFeatureEndFeatureMultiplicity +// Expect: warning: End feature must have multiplicity 1 +package P { + class A; class B; + assoc L { end feature a : A [0..*]; end feature b : B [1]; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNoDirection.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNoDirection.sysml new file mode 100644 index 0000000..4de1ec9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNoDirection.sysml @@ -0,0 +1,6 @@ +// Census: validateFeatureEndNoDirection +// Expect: error: End feature cannot have direction +package P { + part def A; + connection def K { end in a : A; end b : A; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml new file mode 100644 index 0000000..2b26143 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml @@ -0,0 +1,6 @@ +// Census: validateFeatureEndNotDerivedAbstractCompositeOrPortion +// Expect: error: End feature cannot be derived, abstract, composite or portion +package P { + part def A; + connection def K { end derived a : A; end b : A; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureHasType.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureHasType.kerml new file mode 100644 index 0000000..0368a28 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureHasType.kerml @@ -0,0 +1,6 @@ +// Census: validateFeatureHasType +// Expect: error: Features must have at least one type +package P { + class D; + feature f ~ D; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureIsVariable.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureIsVariable.kerml new file mode 100644 index 0000000..6a75bab --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureIsVariable.kerml @@ -0,0 +1,5 @@ +// Census: validateFeatureIsVariable +// Expect: error: Must be owned by an occurrence type +package P { + datatype D { var feature x : ScalarValues::Integer; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedCrossSubsetting.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedCrossSubsetting.kerml new file mode 100644 index 0000000..24894a4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedCrossSubsetting.kerml @@ -0,0 +1,6 @@ +// Census: validateFeatureOwnedCrossSubsetting +// Expect: error: At most one cross subsetting is allowed +package P { + class A { feature x : A; feature y : A; } + assoc S { end a : A; end b : A crosses a.x crosses a.y; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedReferenceSubsetting.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedReferenceSubsetting.kerml new file mode 100644 index 0000000..0b2dc68 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureOwnedReferenceSubsetting.kerml @@ -0,0 +1,5 @@ +// Census: validateFeatureOwnedReferenceSubsetting +// Expect: error: At most one reference subsetting is allowed +package P { + class C { feature a; feature b; feature c references a references b; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeaturePortionNotVariable.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeaturePortionNotVariable.kerml new file mode 100644 index 0000000..a3e64d9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeaturePortionNotVariable.kerml @@ -0,0 +1,5 @@ +// Census: validateFeaturePortionNotVariable +// Expect: error: A portion cannot be variable +package P { + class C { portion var feature p : C; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureReferenceExpressionReferentIsFeature.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureReferenceExpressionReferentIsFeature.kerml new file mode 100644 index 0000000..136387f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureReferenceExpressionReferentIsFeature.kerml @@ -0,0 +1,6 @@ +// Census: validateFeatureReferenceExpressionReferentIsFeature +// Expect: error: Must be a valid feature +package P { + class A; + feature f : ScalarValues::Boolean = A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueIsInitial.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueIsInitial.kerml new file mode 100644 index 0000000..02b91d6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueIsInitial.kerml @@ -0,0 +1,6 @@ +// Census: validateFeatureValueIsInitial +// Expect: error: Initialized feature must be variable +package P { + datatype D; + class C { feature f : D := null; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.kerml new file mode 100644 index 0000000..48cb49a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.kerml @@ -0,0 +1,11 @@ +// Census: validateFeatureValueOverriding +// Expect: error: cannot override the binding value +package P { + private import ScalarValues::Integer; + class C { + feature a : Integer = 1; + } + class D specializes C { + feature :>> a = 2; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.sysml new file mode 100644 index 0000000..c81c911 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFeatureValueOverriding.sysml @@ -0,0 +1,3 @@ +// Census: validateFeatureValueOverriding +// Expect: error: cannot override the binding value of P::D::a +package P { private import ScalarValues::Integer; part def D { attribute a : Integer = 1; } part def E :> D { attribute :>> a = 2; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowDefinitionConnectionEnds.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowDefinitionConnectionEnds.sysml new file mode 100644 index 0000000..1bd0bcb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowDefinitionConnectionEnds.sysml @@ -0,0 +1,3 @@ +// Census: validateFlowDefinitionConnectionEnds +// Expect: error: A flow connection definition can have at most two ends. +package P { part def D; flow def F { end a : D; end b : D; end c : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.kerml new file mode 100644 index 0000000..1d2e924 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.kerml @@ -0,0 +1,9 @@ +// Census: validateFlowEndImplicitSubsetting +// Expect: error: Must be an accessible feature (use dot notation for nesting) +package P { + class C { + feature a { out feature o : ScalarValues::Integer; } + feature b { in feature i : ScalarValues::Integer; } + flow f from a::o to b::i; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.sysml new file mode 100644 index 0000000..b454278 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndImplicitSubsetting.sysml @@ -0,0 +1,9 @@ +// Census: validateFlowEndImplicitSubsetting +// Expect: error: Must be an accessible feature (use dot notation for nesting) +package P { + part def C { + part a { out attribute o : ScalarValues::Integer; } + part b { in attribute i : ScalarValues::Integer; } + flow f from a::o to b::i; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndSubsetting.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndSubsetting.kerml new file mode 100644 index 0000000..fe3f261 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowEndSubsetting.kerml @@ -0,0 +1,7 @@ +// Census: validateFlowEndSubsetting +// Expect: error: Cannot identify flow end (use dot notation) +package P { + class A { out feature o : ScalarValues::Integer; } + class B { in feature i : ScalarValues::Integer; } + class C { feature a : A; feature b : B; flow from A::o to B::i; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowUsageType.sysml new file mode 100644 index 0000000..afc1c47 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFlowUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateFlowUsageType +// Expect: error: A flow connection must be typed by flow connection definitions. +package P { part def D; part def E { part a : D; part b : D; flow f : D from a to b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateForkNodeIncomingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateForkNodeIncomingSuccessions.sysml new file mode 100644 index 0000000..3380105 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateForkNodeIncomingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateForkNodeIncomingSuccessions +// Expect: error: fork f has 2 incoming successions +package P { action def A { action a; action b; fork f; action c; action d; first a then f; first b then f; first f then c; first f then d; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.kerml new file mode 100644 index 0000000..4fa0fb6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.kerml @@ -0,0 +1,7 @@ +// Census: validateFunctionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + function F1 { 1 } + function F2 { 2 } + function F3 specializes F1, F2; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.specialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.specialization.kerml new file mode 100644 index 0000000..4104c04 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.specialization.kerml @@ -0,0 +1,9 @@ +// Census: validateFunctionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + class T; + feature a : T; + feature b : T; + function F { a } + function G specializes F { b } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.sysml new file mode 100644 index 0000000..6d88860 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultExpressionMembership.sysml @@ -0,0 +1,7 @@ +// Census: validateFunctionResultExpressionMembership +// Expect: error: Only one (owned or inherited) result expression is allowed +package P { + private import ScalarValues::Real; + constraint def Base { in x : Real; x > 0.0 } + constraint def Sub :> Base { x > 1.0 } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultParameterMembership.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultParameterMembership.kerml new file mode 100644 index 0000000..1032c83 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateFunctionResultParameterMembership.kerml @@ -0,0 +1,5 @@ +// Census: validateFunctionResultParameterMembership +// Expect: error: Only one return parameter is allowed +package P { + function F { return r1 : ScalarValues::Integer; return r2 : ScalarValues::Integer; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateImportTopLevelVisibility.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateImportTopLevelVisibility.kerml new file mode 100644 index 0000000..d4b86eb --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateImportTopLevelVisibility.kerml @@ -0,0 +1,4 @@ +// Census: validateImportTopLevelVisibility +// Expect: error: Top level import must be private +public import ScalarValues::*; +package P; diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateIncludeUseCaseUsageReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateIncludeUseCaseUsageReference.sysml new file mode 100644 index 0000000..e9fd832 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateIncludeUseCaseUsageReference.sysml @@ -0,0 +1,3 @@ +// Census: validateIncludeUseCaseUsageReference +// Expect: error: Must reference a use case. +package P { part def D; use case def U { part d : D; include d; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInstantiationExpressionInstantiatedType.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInstantiationExpressionInstantiatedType.kerml new file mode 100644 index 0000000..3efdca3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInstantiationExpressionInstantiatedType.kerml @@ -0,0 +1,3 @@ +// Census: validateInstantiationExpressionInstantiatedType +// Expect: error: Must have an invoked/instantiated type +package Q; package P { feature c = new Q(); } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceDefinitionEnd.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceDefinitionEnd.sysml new file mode 100644 index 0000000..81bd7d8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceDefinitionEnd.sysml @@ -0,0 +1,3 @@ +// Census: validateInterfaceDefinitionEnd +// Expect: error: An interface definition end must be a port. +package P { part def D; interface def I { end part a : D; end part b : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageEnd.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageEnd.sysml new file mode 100644 index 0000000..ce998d3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageEnd.sysml @@ -0,0 +1,14 @@ +// Census: validateInterfaceUsageEnd +// Expect: error: An interface end must be a port. +package P { + part def Fuel; + port def FuelInPort; + part vehicle { + part fuel : Fuel; + port inPort : FuelInPort; + interface bad { + end part ::> fuel; + end port ::> inPort; + } + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageType.sysml new file mode 100644 index 0000000..772bb42 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInterfaceUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateInterfaceUsageType +// Expect: error: An interface must be typed by interface definitions. +package P { port def Q; part def D; part def E { port a : Q; port b : Q; interface i : D connect a to b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionInstantiatedType.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionInstantiatedType.kerml new file mode 100644 index 0000000..c8f9892 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionInstantiatedType.kerml @@ -0,0 +1,6 @@ +// Census: validateInvocationExpressionInstantiatedType +// Expect: error: Must invoke a behavior or a behavioral feature +package P { + class A; + feature f = A(); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml new file mode 100644 index 0000000..6853626 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml @@ -0,0 +1,8 @@ +// Census: validateInvocationExpressionNoDuplicateParameterRedefinition +// Expect: error: F binds parameter "x" twice +package P { + class T; + function F { in x : T; return r : T; } + feature t : T; + feature f : T = F(x = t, x = t); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionParameterRedefinition.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionParameterRedefinition.kerml new file mode 100644 index 0000000..239389c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateInvocationExpressionParameterRedefinition.kerml @@ -0,0 +1,6 @@ +// Census: validateInvocationExpressionParameterRedefinition +// Expect: error: Must correspond to one input parameter of the invoked type +package P { + function F { in x : ScalarValues::Integer; return : ScalarValues::Integer; x } + feature r : ScalarValues::Integer = F(y = 1); +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateJoinNodeOutgoingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateJoinNodeOutgoingSuccessions.sysml new file mode 100644 index 0000000..3c62f88 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateJoinNodeOutgoingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateJoinNodeOutgoingSuccessions +// Expect: error: join j has 2 outgoing successions +package P { action def A { action a; action b; join j; action c; action d; first a then j; first b then j; first j then c; first j then d; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateLibraryPackageNotStandard.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateLibraryPackageNotStandard.kerml new file mode 100644 index 0000000..29a09fe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateLibraryPackageNotStandard.kerml @@ -0,0 +1,5 @@ +// Census: validateLibraryPackageNotStandard +// Expect: warning: User library packages should not be marked as standard +standard library package L { + class A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeIncomingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeIncomingSuccessions.sysml new file mode 100644 index 0000000..2f5a2d3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeIncomingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateMergeNodeIncomingSuccessions +// Expect: error: succession into merge m has source multiplicity [1] +package P { action def A { action a; action b; merge m; action c; succession first [1] a then m; first b then m; first m then c; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeOutgoingSuccessions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeOutgoingSuccessions.sysml new file mode 100644 index 0000000..5f1e1d5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMergeNodeOutgoingSuccessions.sysml @@ -0,0 +1,3 @@ +// Census: validateMergeNodeOutgoingSuccessions +// Expect: error: merge m has 2 outgoing successions +package P { action def A { action a; action b; merge m; action c; action d; first a then m; first b then m; first m then c; first m then d; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureAnnotatedElement.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureAnnotatedElement.kerml new file mode 100644 index 0000000..49df3e4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureAnnotatedElement.kerml @@ -0,0 +1,6 @@ +// Census: validateMetadataFeatureAnnotatedElement +// Expect: error: Cannot annotate +package P { + metaclass M specializes Metaobjects::Metaobject { feature redefines annotatedElement : KerML::Feature; } + #M class C; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureBody.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureBody.kerml new file mode 100644 index 0000000..30d0f46 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureBody.kerml @@ -0,0 +1,7 @@ +// Census: validateMetadataFeatureBody +// Expect: error: Must redefine an owning-type feature +package P { + metaclass M { feature x : ScalarValues::Integer; } + feature y : ScalarValues::Integer; + class C { @M { z = 1; } } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadata.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadata.kerml new file mode 100644 index 0000000..192bd2a --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadata.kerml @@ -0,0 +1,6 @@ +// Census: validateMetadataFeatureMetadata +// Expect: error: Must have exactly one metaclass +package P { + class NotAMetaclass; + class C { @NotAMetaclass; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadataNotAbstract.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadataNotAbstract.kerml new file mode 100644 index 0000000..6f53877 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataFeatureMetadataNotAbstract.kerml @@ -0,0 +1,6 @@ +// Census: validateMetadataFeatureMetadataNotAbstract +// Expect: error: Must have a concrete type +package P { + abstract metaclass M; + class C { @M; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataUsageType.sysml new file mode 100644 index 0000000..e76ffd3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMetadataUsageType.sysml @@ -0,0 +1,6 @@ +// Census: validateMetadataUsageType +// Expect: error: A metadata usage must be typed by one metadata definition. +package P { + part def NotMetadata; + part c { metadata m : NotMetadata; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMultiplicityRangeResultTypes.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMultiplicityRangeResultTypes.kerml new file mode 100644 index 0000000..c02e028 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateMultiplicityRangeResultTypes.kerml @@ -0,0 +1,5 @@ +// Census: validateMultiplicityRangeResultTypes +// Expect: error: Must have a Natural value +package P { + class C { feature f ["two"]; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateNamespaceDistinguishablity.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateNamespaceDistinguishablity.kerml new file mode 100644 index 0000000..41c64dc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateNamespaceDistinguishablity.kerml @@ -0,0 +1,6 @@ +// Census: validateNamespaceDistinguishablity +// Expect: warning: Duplicate of other owned member name +package P { + class A; + class A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateObjectiveMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateObjectiveMembershipOwningType.sysml new file mode 100644 index 0000000..d2c7855 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateObjectiveMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateObjectiveMembershipOwningType +// Expect: error: 'objective' declares the objective of a case and is only allowed in a case body +package P { part def D; part def Q { objective o; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualDefinition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualDefinition.sysml new file mode 100644 index 0000000..4ae6680 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualDefinition.sysml @@ -0,0 +1,3 @@ +// Census: validateOccurrenceUsageIndividualDefinition +// Expect: error: At most one individual definition is allowed. +package P { individual part def I1; individual part def I2; individual part i : I1, I2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualUsage.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualUsage.sysml new file mode 100644 index 0000000..5ddbda5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIndividualUsage.sysml @@ -0,0 +1,3 @@ +// Census: validateOccurrenceUsageIndividualUsage +// Expect: error: An individual must be typed by one individual definition. +package P { part def D; individual part i : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIsPortion.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIsPortion.sysml new file mode 100644 index 0000000..15397f3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageIsPortion.sysml @@ -0,0 +1,3 @@ +// Census: validateOccurrenceUsageIsPortion +// Expect: error: Must be owned by an occurrence definition or usage. +package P { part def D; snapshot part s : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageType.sysml new file mode 100644 index 0000000..bb9b7f8 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOccurrenceUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateOccurrenceUsageType +// Expect: error: An occurrence, item or part must be typed by occurrence definitions. +package P { attribute def A; occurrence o : A; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionBracketOperator.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionBracketOperator.kerml new file mode 100644 index 0000000..d59a04b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionBracketOperator.kerml @@ -0,0 +1,6 @@ +// Census: validateOperatorExpressionBracketOperator +// Expect: warning: is not an index in KerML +package P { + feature xs : ScalarValues::Integer[0..*] ordered; + feature firstElem = xs[1]; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionCastConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionCastConformance.kerml new file mode 100644 index 0000000..1eee1fe --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionCastConformance.kerml @@ -0,0 +1,6 @@ +// Census: validateOperatorExpressionCastConformance +// Expect: warning: cast argument is typed by String, unrelated to the target Integer +package P { + feature s : ScalarValues::String; + feature n = s as ScalarValues::Integer; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionQuantity.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionQuantity.sysml new file mode 100644 index 0000000..9a93c4c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOperatorExpressionQuantity.sysml @@ -0,0 +1,5 @@ +// Census: validateOperatorExpressionQuantity +// Expect: warning: the unit of a quantity must be a measurement reference, found Natural +package P { + attribute length = 10 [3]; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedDifferencingNotOne.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedDifferencingNotOne.kerml new file mode 100644 index 0000000..7855f5b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedDifferencingNotOne.kerml @@ -0,0 +1,6 @@ +// Census: validateOwnedDifferencingNotOne +// Expect: error: Cannot have only one differencing +package P { + class A; + class D differences A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedIntersectingNotOne.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedIntersectingNotOne.kerml new file mode 100644 index 0000000..dae7928 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedIntersectingNotOne.kerml @@ -0,0 +1,6 @@ +// Census: validateOwnedIntersectingNotOne +// Expect: error: Cannot have only one intersecting +package P { + class A; + class D intersects A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedUnioningNotOne.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedUnioningNotOne.kerml new file mode 100644 index 0000000..59c5af9 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateOwnedUnioningNotOne.kerml @@ -0,0 +1,6 @@ +// Census: validateOwnedUnioningNotOne +// Expect: error: Cannot have only one unioning +package P { + class A; + class D unions A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePerformActionUsageReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePerformActionUsageReference.sysml new file mode 100644 index 0000000..614320b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePerformActionUsageReference.sysml @@ -0,0 +1,3 @@ +// Census: validatePerformActionUsageReference +// Expect: error: Must reference an action. +package P { part def D; part def E { part d : D; perform d; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortDefinitionOwnedUsagesNotComposite.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortDefinitionOwnedUsagesNotComposite.sysml new file mode 100644 index 0000000..25baed1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortDefinitionOwnedUsagesNotComposite.sysml @@ -0,0 +1,3 @@ +// Census: validatePortDefinitionOwnedUsagesNotComposite +// Expect: error: Owned usages of a port definition (other than ports) must be referential. +package P { part def D; port def Q { part p : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageIsReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageIsReference.sysml new file mode 100644 index 0000000..175a87e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageIsReference.sysml @@ -0,0 +1,3 @@ +// Census: validatePortUsageIsReference +// Expect: error: A port usage must be referential. +package P { port def PD; port def Q { variation port vp : PD { variant port a : PD; } } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageNestedUsagesNotComposite.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageNestedUsagesNotComposite.sysml new file mode 100644 index 0000000..f1451da --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageNestedUsagesNotComposite.sysml @@ -0,0 +1,3 @@ +// Census: validatePortUsageNestedUsagesNotComposite +// Expect: error: Nested usages in a port usage (other than ports) must be referential. +package P { part def D; port def Q; part def E { port p : Q { part x : D; } } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageType.sysml new file mode 100644 index 0000000..2ad11f1 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validatePortUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validatePortUsageType +// Expect: error: A port must be typed by port definitions. +package P { part def D; port p : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionDirectionConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionDirectionConformance.kerml new file mode 100644 index 0000000..d67ee4b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionDirectionConformance.kerml @@ -0,0 +1,6 @@ +// Census: validateRedefinitionDirectionConformance +// Expect: error: Redefining feature must have a compatible direction +package P { + class A { in feature x; } + class B specializes A { out feature y redefines x; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionEndConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionEndConformance.kerml new file mode 100644 index 0000000..15c2196 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionEndConformance.kerml @@ -0,0 +1,7 @@ +// Census: validateRedefinitionEndConformance +// Expect: error: Redefining feature must be an end feature +package P { + class A; class B; + assoc L { end a : A; end b : B; } + assoc M specializes L { feature c redefines a; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionFeaturingTypes.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionFeaturingTypes.kerml new file mode 100644 index 0000000..364eb6d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionFeaturingTypes.kerml @@ -0,0 +1,6 @@ +// Census: validateRedefinitionFeaturingTypes +// Expect: error: A package-level feature cannot be redefined +package P { + feature x; + feature y redefines x; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionMultiplicityConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionMultiplicityConformance.kerml new file mode 100644 index 0000000..e8a9e91 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRedefinitionMultiplicityConformance.kerml @@ -0,0 +1,6 @@ +// Census: validateRedefinitionMultiplicityConformance +// Expect: warning: Redefining feature should not have smaller multiplicity lower bound +package P { + class A { feature x [1..2]; } + class B specializes A { feature y [0..2] redefines x; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRenderingUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRenderingUsageType.sysml new file mode 100644 index 0000000..f8bd66e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRenderingUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateRenderingUsageType +// Expect: error: A rendering must be typed by one rendering definition. +package P { rendering def R1; rendering def R2; rendering r : R1, R2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementConstraintMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementConstraintMembershipOwningType.sysml new file mode 100644 index 0000000..11d1cfc --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementConstraintMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementConstraintMembershipOwningType +// Expect: warning: outside a requirement body is an OpenSysML extension +package P { constraint def K; part def D { require constraint k : K; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionOnlyOneSubject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionOnlyOneSubject.sysml new file mode 100644 index 0000000..eb0c502 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionOnlyOneSubject.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementDefinitionOnlyOneSubject +// Expect: error: Only one subject is allowed. +package P { part def D; requirement def R { subject a : D; subject b : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionSubjectParameterPosition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionSubjectParameterPosition.sysml new file mode 100644 index 0000000..be1fc1e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementDefinitionSubjectParameterPosition.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementDefinitionSubjectParameterPosition +// Expect: error: Subject must be first parameter. +package P { part def D; requirement def R { in x : D; subject a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageOnlyOneSubject.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageOnlyOneSubject.sysml new file mode 100644 index 0000000..fdd2218 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageOnlyOneSubject.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementUsageOnlyOneSubject +// Expect: error: Only one subject is allowed. +package P { part def D; requirement def R; requirement r : R { subject a : D; subject b : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageSubjectParameterPosition.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageSubjectParameterPosition.sysml new file mode 100644 index 0000000..4a71f56 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageSubjectParameterPosition.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementUsageSubjectParameterPosition +// Expect: error: Subject must be first parameter. +package P { part def D; requirement def R; requirement r : R { in x : D; subject a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageType.sysml new file mode 100644 index 0000000..71e02f4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementUsageType +// Expect: error: A requirement must be typed by one requirement definition. +package P { requirement def R1; requirement def R2; requirement r : R1, R2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementVerificationMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementVerificationMembershipOwningType.sysml new file mode 100644 index 0000000..eb8a8bf --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateRequirementVerificationMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateRequirementVerificationMembershipOwningType +// Expect: error: A requirement verification must be in the objective of a verification case. +package P { requirement def R; requirement def Q { verify requirement r : R; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateReturnParameterMembershipOwningType.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateReturnParameterMembershipOwningType.kerml new file mode 100644 index 0000000..f395466 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateReturnParameterMembershipOwningType.kerml @@ -0,0 +1,6 @@ +// Census: validateReturnParameterMembershipOwningType +// Expect: error: Return parameter membership not allowed +package P { + datatype Count; + classifier Counter { return total : Count; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSatisfyRequirementUsageReference.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSatisfyRequirementUsageReference.sysml new file mode 100644 index 0000000..f1c6a97 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSatisfyRequirementUsageReference.sysml @@ -0,0 +1,3 @@ +// Census: validateSatisfyRequirementUsageReference +// Expect: error: satisfy target must be a requirement usage +package P { part def D { part x : D; satisfy x by x; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsagePayloadArgument.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsagePayloadArgument.sysml new file mode 100644 index 0000000..5c65c4c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsagePayloadArgument.sysml @@ -0,0 +1,3 @@ +// Census: validateSendActionUsagePayloadArgument +// Expect: error: a send action written as a state subaction or a transition effect must have a payload +package P { item def D; state def S { state a { entry send to d; } item d : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsageReceiver.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsageReceiver.sysml new file mode 100644 index 0000000..c1ef8a4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSendActionUsageReceiver.sysml @@ -0,0 +1,3 @@ +// Census: validateSendActionUsageReceiver +// Expect: warning: sending to the port p should use 'via' rather than 'to' +package P { item def Sig; port def Pt; part def Q { port p : Pt; action a { send new Sig() to p; } } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.kerml new file mode 100644 index 0000000..dba9f0d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.kerml @@ -0,0 +1,6 @@ +// Census: validateSpecializationSpecificNotConjugated +// Expect: error: Conjugated type cannot be a specialized type +package P { + class A; class B ~ A; + specialization subtype B specializes A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.subset.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.subset.kerml new file mode 100644 index 0000000..39e491f --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSpecializationSpecificNotConjugated.subset.kerml @@ -0,0 +1,7 @@ +// Census: validateSpecializationSpecificNotConjugated +// Expect: error: Conjugated type cannot be a specialized type +package P { + class A; + feature f : A; feature g ~ f; feature h : A; + specialization subset g subsets h; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStakeholderMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStakeholderMembershipOwningType.sysml new file mode 100644 index 0000000..6274d61 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStakeholderMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateStakeholderMembershipOwningType +// Expect: error: 'stakeholder' declares a stakeholder of a requirement and is only allowed in a requirement body +package P { part def D; part def Q { stakeholder k : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionParallelSubactions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionParallelSubactions.sysml new file mode 100644 index 0000000..c03d6f3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionParallelSubactions.sysml @@ -0,0 +1,3 @@ +// Census: validateStateDefinitionParallelSubactions +// Expect: error: A parallel state cannot have successions or transitions. +package P { state def S parallel { state a; state b; transition first a then b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionSubactionKind.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionSubactionKind.sysml new file mode 100644 index 0000000..14f4e1c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateDefinitionSubactionKind.sysml @@ -0,0 +1,3 @@ +// Census: validateStateDefinitionSubactionKind +// Expect: error: A state may have at most one entry action. +package P { state def S { entry; do; exit; entry; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateSubactionMembershioOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateSubactionMembershioOwningType.sysml new file mode 100644 index 0000000..02438f2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateSubactionMembershioOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateStateSubactionMembershioOwningType +// Expect: error: 'entry' declares the entry action of a state and is only allowed in a state body +package P { part def D; part def Q { entry action init; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageParallelSubactions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageParallelSubactions.sysml new file mode 100644 index 0000000..ce69306 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageParallelSubactions.sysml @@ -0,0 +1,3 @@ +// Census: validateStateUsageParallelSubactions +// Expect: error: A parallel state cannot have successions or transitions. +package P { state def S { state x parallel { state a; state b; transition first a then b; } } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageSubactionKind.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageSubactionKind.sysml new file mode 100644 index 0000000..e48dfe7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageSubactionKind.sysml @@ -0,0 +1,3 @@ +// Census: validateStateUsageSubactionKind +// Expect: error: A state may have at most one entry action. +package P { state def S { state x { entry; entry; } } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageType.sysml new file mode 100644 index 0000000..3bb5bea --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStateUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateStateUsageType +// Expect: error: A state must be typed by state definitions. +package P { part def D; state s : D; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStructureSpecialization.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStructureSpecialization.kerml new file mode 100644 index 0000000..7a41f93 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateStructureSpecialization.kerml @@ -0,0 +1,6 @@ +// Census: validateStructureSpecialization +// Expect: error: Cannot specialize behavior +package P { + behavior B; + struct S specializes B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubjectMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubjectMembershipOwningType.sysml new file mode 100644 index 0000000..53fbb77 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubjectMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateSubjectMembershipOwningType +// Expect: error: 'subject' declares the subject of a requirement or case and is only allowed in a requirement or case body +package P { part def D; part def Q { subject s : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingConstantConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingConstantConformance.kerml new file mode 100644 index 0000000..26a3508 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingConstantConformance.kerml @@ -0,0 +1,8 @@ +// Census: validateSubsettingConstantConformance +// Expect: error: Subsetting/redefining feature must be constant if subsetted/redefined feature is constant +package K14VariableSubsetsConstant { + class C specializes Occurrences::Occurrence { + const feature a : C; + var feature b : C subsets a; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingFeaturingTypes.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingFeaturingTypes.kerml new file mode 100644 index 0000000..a4d0e91 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingFeaturingTypes.kerml @@ -0,0 +1,6 @@ +// Census: validateSubsettingFeaturingTypes +// Expect: error: Must be an accessible feature (use dot notation for nesting) +package P { + class A { feature x; } + class B { feature y subsets A::x; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingMultiplicityConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingMultiplicityConformance.kerml new file mode 100644 index 0000000..81c61ef --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingMultiplicityConformance.kerml @@ -0,0 +1,6 @@ +// Census: validateSubsettingMultiplicityConformance +// Expect: warning: Subsetting/redefining feature should not have larger multiplicity upper bound +package P { + class A { feature x [0..2]; } + class B specializes A { feature y [0..5] subsets x; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingUniquenessConformance.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingUniquenessConformance.kerml new file mode 100644 index 0000000..b41df16 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateSubsettingUniquenessConformance.kerml @@ -0,0 +1,6 @@ +// Census: validateSubsettingUniquenessConformance +// Expect: error: Subsetting/redefining feature cannot be nonunique if subsetted/redefined feature is unique +package P { + class A { feature x [*]; } + class B specializes A { feature y [*] nonunique subsets x; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionFeatureMembershipGuardExpression.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionFeatureMembershipGuardExpression.sysml new file mode 100644 index 0000000..9690e46 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionFeatureMembershipGuardExpression.sysml @@ -0,0 +1,6 @@ +// Census: validateTransitionFeatureMembershipGuardExpression +// Expect: error: transition guard must be Boolean +package P { + state def S { state a; state b; transition first a if "yes" then b; } + action def A { action a; action b; first a if 1 then b; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageSuccession.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageSuccession.sysml new file mode 100644 index 0000000..88c3fc2 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageSuccession.sysml @@ -0,0 +1,10 @@ +// Census: validateTransitionUsageSuccession +// Expect: error: is not a state or pseudostate +package S44TransitionTargetNotAction { + part def PD; + state def S { + state s1; + part p : PD; + transition first s1 then p; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageTriggerActions.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageTriggerActions.sysml new file mode 100644 index 0000000..726236c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTransitionUsageTriggerActions.sysml @@ -0,0 +1,10 @@ +// Census: validateTransitionUsageTriggerActions +// Expect: error: A transition with an accepter must have a state as its source. +package P { + item def A; + state def S { + entry action init; + transition init accept A then s1; + state s1; + } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAfterArgument.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAfterArgument.sysml new file mode 100644 index 0000000..7f53ce4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAfterArgument.sysml @@ -0,0 +1,3 @@ +// Census: validateTriggerInvocationActionAfterArgument +// Expect: error: an 'after' trigger's delay must be a DurationValue, found Natural: write it with a duration unit (`after 5 [s]`) or name a feature typed by DurationValue +package P { state def S { state a; state b; transition first a accept after 5 then b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAtArgument.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAtArgument.sysml new file mode 100644 index 0000000..d8c4123 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionAtArgument.sysml @@ -0,0 +1,3 @@ +// Census: validateTriggerInvocationActionAtArgument +// Expect: error: an 'at' trigger's time must be a TimeInstantValue, found DurationValue: name a feature typed by TimeInstantValue or a clock reading such as `TimeOf(this)` +package P { private import ISQ::*; state def S { attribute delay : DurationValue; state a; state b; transition first a accept at delay then b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionWhenArgument.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionWhenArgument.sysml new file mode 100644 index 0000000..cecc38d --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTriggerInvocationActionWhenArgument.sysml @@ -0,0 +1,3 @@ +// Census: validateTriggerInvocationActionWhenArgument +// Expect: error: a 'when' trigger's condition must be Boolean, found Integer: compare the value (`when x > 3`) or name a feature typed by Boolean +package P { private import ScalarValues::*; state def S { attribute level : Integer; state a; state b; transition first a accept when level then b; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeAtMostOneConjugator.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeAtMostOneConjugator.kerml new file mode 100644 index 0000000..4c1114e --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeAtMostOneConjugator.kerml @@ -0,0 +1,6 @@ +// Census: validateTypeAtMostOneConjugator +// Expect: error: Cannot have more than one conjugator +package P { + classifier A; classifier B; + classifier C ~A ~B; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeDifferencingTypesNotSelf.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeDifferencingTypesNotSelf.kerml new file mode 100644 index 0000000..e96a9aa --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeDifferencingTypesNotSelf.kerml @@ -0,0 +1,6 @@ +// Census: validateTypeDifferencingTypesNotSelf +// Expect: error: Type cannot difference with itself +package P { + class A; + class D differences D, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeIntersectingTypesNotSelf.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeIntersectingTypesNotSelf.kerml new file mode 100644 index 0000000..576977b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeIntersectingTypesNotSelf.kerml @@ -0,0 +1,6 @@ +// Census: validateTypeIntersectingTypesNotSelf +// Expect: error: Type cannot intersect with itself +package P { + class A; + class D intersects D, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeOwnedMultiplicity.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeOwnedMultiplicity.kerml new file mode 100644 index 0000000..208bf68 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeOwnedMultiplicity.kerml @@ -0,0 +1,5 @@ +// Census: validateTypeOwnedMultiplicity +// Expect: error: Only one multiplicity is allowed +package P { + class C { multiplicity m1 [1]; multiplicity m2 [2]; } +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeUnioningTypesNotSelf.kerml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeUnioningTypesNotSelf.kerml new file mode 100644 index 0000000..a2ae9c6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateTypeUnioningTypesNotSelf.kerml @@ -0,0 +1,6 @@ +// Census: validateTypeUnioningTypesNotSelf +// Expect: error: Type cannot union with itself +package P { + class A; + class D unions D, A; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageType.sysml new file mode 100644 index 0000000..3300500 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageType.sysml @@ -0,0 +1,5 @@ +// Census: validateUsageType +// Expect: error: A usage must be typed by definitions. +package S36UsageTypedByFeature { + ref r : Base::things; +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationMembership.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationMembership.sysml new file mode 100644 index 0000000..7caa33c --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationMembership.sysml @@ -0,0 +1,3 @@ +// Census: validateUsageVariationMembership +// Expect: error: An owned usage of a variation must be a variant. +package P { part def D; abstract variation part v : D { part a : D; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationSpecialization.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationSpecialization.sysml new file mode 100644 index 0000000..bd05974 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUsageVariationSpecialization.sysml @@ -0,0 +1,3 @@ +// Census: validateUsageVariationSpecialization +// Expect: error: A variation must not specialize another variation. +package P { part def D; abstract variation part v1 : D; abstract variation part v2 :> v1; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUseCaseUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUseCaseUsageType.sysml new file mode 100644 index 0000000..301d6e0 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateUseCaseUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateUseCaseUsageType +// Expect: error: A use case must be typed by one use case definition. +package P { use case def U1; use case def U2; use case u : U1, U2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVariationMembershipOwningNamespace.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVariationMembershipOwningNamespace.sysml new file mode 100644 index 0000000..ef3a4e3 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVariationMembershipOwningNamespace.sysml @@ -0,0 +1,3 @@ +// Census: validateVariationMembershipOwningNamespace +// Expect: error: A variant must be an owned member of a variation. +package P { part def D { variant part a; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVerificationCaseUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVerificationCaseUsageType.sysml new file mode 100644 index 0000000..ecf4bed --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateVerificationCaseUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateVerificationCaseUsageType +// Expect: error: A verification case must be typed by one verification case definition. +package P { verification def V1; verification def V2; verification v : V1, V2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewDefinitionOnlyOnvViewRendering.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewDefinitionOnlyOnvViewRendering.sysml new file mode 100644 index 0000000..3b244b4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewDefinitionOnlyOnvViewRendering.sysml @@ -0,0 +1,3 @@ +// Census: validateViewDefinitionOnlyOnvViewRendering +// Expect: error: A view definition may have at most one view rendering. +package P { rendering def R; view def V { render rendering r1 : R; render rendering r2 : R; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewRenderingMembershipOwningType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewRenderingMembershipOwningType.sysml new file mode 100644 index 0000000..cf26719 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewRenderingMembershipOwningType.sysml @@ -0,0 +1,3 @@ +// Census: validateViewRenderingMembershipOwningType +// Expect: error: 'render' declares the rendering of a view and is only allowed in a view body +package P { part def D; part def Q { render asTable; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageOnlyOneRendering.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageOnlyOneRendering.sysml new file mode 100644 index 0000000..6b36c48 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageOnlyOneRendering.sysml @@ -0,0 +1,3 @@ +// Census: validateViewUsageOnlyOneRendering +// Expect: error: A view may have at most one view rendering. +package P { rendering def R; view def V; view v : V { render rendering r1 : R; render rendering r2 : R; } } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageType.sysml new file mode 100644 index 0000000..16279f6 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateViewUsageType +// Expect: error: A view must be typed by one view definition. +package P { view def V1; view def V2; view v : V1, V2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewpointUsageType.sysml b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewpointUsageType.sysml new file mode 100644 index 0000000..0c53acd --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/probes/validateViewpointUsageType.sysml @@ -0,0 +1,3 @@ +// Census: validateViewpointUsageType +// Expect: error: A viewpoint must be typed by one viewpoint definition. +package P { viewpoint def V1; viewpoint def V2; viewpoint v : V1, V2; } diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/provenance.json b/crates/sysmlv2-parser/tests/fixtures/opensysml/provenance.json new file mode 100644 index 0000000..e86de6b --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/provenance.json @@ -0,0 +1,2316 @@ +{ + "repository": "https://github.com/Open-MBEE/OpenSysML", + "revision": "d7d432ff410e60f9146c38bfe51b4db749a924b1", + "files": [ + { + "file": "probes/validateActionUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateActionUsageType.sysml", + "sha256": "c5144381f81dbb2aa2c4506245a56457510e90fe98cde2fc2e869ccde6c37180" + }, + { + "file": "probes/validateActorMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateActorMembershipOwningType.sysml", + "sha256": "3c1bf3ffc3dea9911c7024edc38f2432a58c0f20f1e67f0718644f08be4c45ce" + }, + { + "file": "probes/validateAllocationUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateAllocationUsageType.sysml", + "sha256": "7a6a2958a2ee681d0d3a935b6f821a86e7278ed17e5152b977ff4df4ee4ab9e7" + }, + { + "file": "probes/validateAnalysisCaseUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateAnalysisCaseUsageType.sysml", + "sha256": "47560a0f14e196fccdc6f40611375d20a95acb114fc9c17d2132d20ac926b27d" + }, + { + "file": "probes/validateAnnotationAnnotatedElementOwnership.kerml", + "source": "cmd/validation-census/testdata/probes/validateAnnotationAnnotatedElementOwnership.kerml", + "sha256": "1c58bd2a80e9cbbb41eec68c15221df96f3333d27a3c03c2358e24a7f9014063" + }, + { + "file": "probes/validateAssertConstraintUsageReference.sysml", + "source": "cmd/validation-census/testdata/probes/validateAssertConstraintUsageReference.sysml", + "sha256": "7f2ddd00307b3bb51edc65d053f4a091066ac579d80e62e70901a52308d2e3c3" + }, + { + "file": "probes/validateAssignmentActionUsageReferent.sysml", + "source": "cmd/validation-census/testdata/probes/validateAssignmentActionUsageReferent.sysml", + "sha256": "4fbb097f45f56fb37d00be250946e11a1e9ba0a37282e8413acd19469ded219e" + }, + { + "file": "probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml", + "source": "cmd/validation-census/testdata/probes/validateAssignmentActionUsageReferentIsTimeVarying.sysml", + "sha256": "18471668c09340bde6428b1dd664b81614ef36b9195e39e6bc7eecd17f04eda3" + }, + { + "file": "probes/validateAssociationBinarySpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateAssociationBinarySpecialization.kerml", + "sha256": "e175112d8e5826c0e38189b014cfa2ebe77cb17a5f6390a48c64901ca4028c34" + }, + { + "file": "probes/validateAssociationEndTypes.kerml", + "source": "cmd/validation-census/testdata/probes/validateAssociationEndTypes.kerml", + "sha256": "287e1d71ddd5f2f2f2887e5addfae825503649b99af9558fb2da8311a8aca1a4" + }, + { + "file": "probes/validateAssociationRelatedTypes.kerml", + "source": "cmd/validation-census/testdata/probes/validateAssociationRelatedTypes.kerml", + "sha256": "b2aaf19cf8755921d562e001c167fd1e74815a15b2d4f6d469da14b91a44c6b2" + }, + { + "file": "probes/validateAttributeUsageEnumerationType.sysml", + "source": "cmd/validation-census/testdata/probes/validateAttributeUsageEnumerationType.sysml", + "sha256": "95e36d99bae36feb7e0dceb5c0c1d89b8abd10ae8d117aff379813c200f8e2a5" + }, + { + "file": "probes/validateAttributeUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateAttributeUsageType.sysml", + "sha256": "723fbbe3a772f35f93e64291c4bedd766d703e07dd04aea3361a1530af13e37f" + }, + { + "file": "probes/validateBehaviorSpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateBehaviorSpecialization.kerml", + "sha256": "c04aedc6f54ef51b74733a64311805d97ddb8cd0b34c3d4bfbc420a75bcc03ae" + }, + { + "file": "probes/validateBindingConnectorIsBinary.kerml", + "source": "cmd/validation-census/testdata/probes/validateBindingConnectorIsBinary.kerml", + "sha256": "2a423e3b7efa2a2ada1943db67f6d427d05008198d34cc2ee4b64bf05f4c682c" + }, + { + "file": "probes/validateBindingConnectorTypeConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateBindingConnectorTypeConformance.kerml", + "sha256": "cc0414e28af6906a6160eb620f86ad91123eb68a2700a71e0c568b47dbecf121" + }, + { + "file": "probes/validateBindingConnectorTypeConformance.result.kerml", + "source": "cmd/validation-census/testdata/probes/validateBindingConnectorTypeConformance.result.kerml", + "sha256": "499a3cfc9dd4a268d1e0ae8c47c4f4d1897aab19f9f545c85f50d04b3db90664" + }, + { + "file": "probes/validateBindingConnectorTypeConformance.satisfy.sysml", + "source": "cmd/validation-census/testdata/probes/validateBindingConnectorTypeConformance.satisfy.sysml", + "sha256": "cefe261e6c0e7dfd823b99f56a0efc9466cf2e4d8025e5ee431ea4fb3c03ca22" + }, + { + "file": "probes/validateBindingConnectorTypeConformance.subject.sysml", + "source": "cmd/validation-census/testdata/probes/validateBindingConnectorTypeConformance.subject.sysml", + "sha256": "97b04c1712720861557f57c75f03d0650e81919722d8df976122b2bc298aaedb" + }, + { + "file": "probes/validateCalculationUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateCalculationUsageType.sysml", + "sha256": "2b85880bee51305d3743464f4d28713b7b10bd55745a8ca29369b0fc9dc53973" + }, + { + "file": "probes/validateCaseDefinitionOnlyOneObjective.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseDefinitionOnlyOneObjective.sysml", + "sha256": "72f27d72bca72e3e12952ecab7ed5a00225b8d54b20d5eed55d66b41f855614f" + }, + { + "file": "probes/validateCaseDefinitionOnlyOneSubject.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseDefinitionOnlyOneSubject.sysml", + "sha256": "7f35837969d823949f974bd2df5e60ad323a959016d6eb69c2b0e5d0f605c548" + }, + { + "file": "probes/validateCaseDefinitionSubjectParameterPosition.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseDefinitionSubjectParameterPosition.sysml", + "sha256": "51ca4d140be70e0062f584ddb4bd471174762e8ec4370e858cfecb9d419361ba" + }, + { + "file": "probes/validateCaseUsageOnlyOneObjective.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseUsageOnlyOneObjective.sysml", + "sha256": "117f21b3a063eb9f9e7673d3af3fd790a5c386ffacd127f70a84496a41b29ae4" + }, + { + "file": "probes/validateCaseUsageOnlyOneSubject.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseUsageOnlyOneSubject.sysml", + "sha256": "4d7ae36349e1a239489ba43ad23935f7cb39917dfdc72962068b21563d011b4d" + }, + { + "file": "probes/validateCaseUsageSubjectParameterPosition.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseUsageSubjectParameterPosition.sysml", + "sha256": "3f95d8a6f4eaf0be86a67bae73092f42a7dd6967dfaa2b8f13383a05d7ffb272" + }, + { + "file": "probes/validateCaseUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateCaseUsageType.sysml", + "sha256": "aa4a2965a5fa8c06a0432a1fd5733da4fe6d4ad17ac4914ef4f1b170bda67a3e" + }, + { + "file": "probes/validateClassSpecialization.connection.sysml", + "source": "cmd/validation-census/testdata/probes/validateClassSpecialization.connection.sysml", + "sha256": "a3d596ea3422dad989271f1d860c1a53f11a6fc97f4da000675b782389dc9462" + }, + { + "file": "probes/validateClassSpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateClassSpecialization.kerml", + "sha256": "c19d6bde3b7c94c65d69452fe879e10a80309ccb2b576124419939ccd5c0509e" + }, + { + "file": "probes/validateClassSpecialization.subsets.kerml", + "source": "cmd/validation-census/testdata/probes/validateClassSpecialization.subsets.kerml", + "sha256": "3e496c3af6ecd1245de47685feb2ed6e0827cc11c62a37e60b14fdf04e59e97d" + }, + { + "file": "probes/validateClassSpecialization.sysml", + "source": "cmd/validation-census/testdata/probes/validateClassSpecialization.sysml", + "sha256": "49fcb126ee83e2ab192d8cd9a85e6a19e5112b06a233b7c7af5e4dc41d4ecd0a" + }, + { + "file": "probes/validateClassifierDefaultSupertype.kerml", + "source": "cmd/validation-census/testdata/probes/validateClassifierDefaultSupertype.kerml", + "sha256": "fd9b54496c840eeffaa9e60057ff1cf838dc78a3c11efc1d110bf551fa29b7ef" + }, + { + "file": "probes/validateConnectionUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateConnectionUsageType.sysml", + "sha256": "4f22f676ed0cffa436a6022bdc282932805eab153905b964fc92aa82405407be" + }, + { + "file": "probes/validateConnectorBinarySpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateConnectorBinarySpecialization.kerml", + "sha256": "7de855409959a61a7c7746d13a5e6502ad0a602f90a1054b18fc708b6f4b6e09" + }, + { + "file": "probes/validateConnectorRelatedFeatures.sysml", + "source": "cmd/validation-census/testdata/probes/validateConnectorRelatedFeatures.sysml", + "sha256": "42588e832e78550584f2d1ea3bc07ae445be25000fe08a0943b4803a0956a0a2" + }, + { + "file": "probes/validateConnectorTypeFeaturing.kerml", + "source": "cmd/validation-census/testdata/probes/validateConnectorTypeFeaturing.kerml", + "sha256": "4515e42d7710ba592ddd19f426eba0319af68dc697b3dee6a661985e830fa6fe" + }, + { + "file": "probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml", + "source": "cmd/validation-census/testdata/probes/validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml", + "sha256": "77aac50b6193ad9105823807b8ba87e08a91ebfbb5699097c98a70bd976cbaa9" + }, + { + "file": "probes/validateControlNodeIncomingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateControlNodeIncomingSuccessions.sysml", + "sha256": "fe13fe4886ff9f0f1fe201c86d04bb66923a8b7f1a1c17d1fdd5406da3fa63d5" + }, + { + "file": "probes/validateControlNodeOutgoingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateControlNodeOutgoingSuccessions.sysml", + "sha256": "3e5e4b3abe5a9afc2eb725d608da4a11277cd4083dae1970bcb390c127d1afa0" + }, + { + "file": "probes/validateControlNodeOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateControlNodeOwningType.sysml", + "sha256": "831b476c7617a29ab656f5078936db30ecb51eed44caa6a75c9348de424ab0b4" + }, + { + "file": "probes/validateCrossSubsettingCrossedFeature.kerml", + "source": "cmd/validation-census/testdata/probes/validateCrossSubsettingCrossedFeature.kerml", + "sha256": "a082f967336025c1c389e46af5c660d639fdb1f93d47d6bcf8fef54c4a2fa7a4" + }, + { + "file": "probes/validateCrossSubsettingCrossingFeature.kerml", + "source": "cmd/validation-census/testdata/probes/validateCrossSubsettingCrossingFeature.kerml", + "sha256": "ca5a8a648692e8fd4c7064c6a86482292f2d22a3a5cac9e588bc7797236a80a0" + }, + { + "file": "probes/validateDataTypeSpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateDataTypeSpecialization.kerml", + "sha256": "4818829546399aaa977e12607905ad76f61c6d4db868408f4e5b383188414c98" + }, + { + "file": "probes/validateDataTypeSpecialization.subsets.kerml", + "source": "cmd/validation-census/testdata/probes/validateDataTypeSpecialization.subsets.kerml", + "sha256": "107dc0090e2ac3a576f92cd8e482f0002b78a617a2a7ab41715113baa70b4a49" + }, + { + "file": "probes/validateDataTypeSpecialization.sysml", + "source": "cmd/validation-census/testdata/probes/validateDataTypeSpecialization.sysml", + "sha256": "9bf46fc9db3efe741ac50af6bb07732219ed267bc9eb4e1544df30f9f95eb544" + }, + { + "file": "probes/validateDecisionNodeIncomingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateDecisionNodeIncomingSuccessions.sysml", + "sha256": "66b09f076bd62ecc48e528179550fe381fca0bf3f8df687580631429d3a29e86" + }, + { + "file": "probes/validateDecisionNodeOutgoingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateDecisionNodeOutgoingSuccessions.sysml", + "sha256": "aa7f90625cb866fec1886a415480eac5b90b155060dfdedacae45739b78df945" + }, + { + "file": "probes/validateDefinitionVariationMembership.sysml", + "source": "cmd/validation-census/testdata/probes/validateDefinitionVariationMembership.sysml", + "sha256": "7a0596b3f72f90c7008c3462f71e91a3350310bb4278cbd71a681d8e2808ef25" + }, + { + "file": "probes/validateDefinitionVariationSpecialization.sysml", + "source": "cmd/validation-census/testdata/probes/validateDefinitionVariationSpecialization.sysml", + "sha256": "526f9f46bf9c2781e1c081cb0e55fc5487ab323e0f1334209570b87154ef96eb" + }, + { + "file": "probes/validateElementFilterMembershipIsBoolean.kerml", + "source": "cmd/validation-census/testdata/probes/validateElementFilterMembershipIsBoolean.kerml", + "sha256": "d3ebeaa8a1898b283bae2c5f3f671ccb7fcd64a85b800e76d36a350cb7ad809c" + }, + { + "file": "probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml", + "source": "cmd/validation-census/testdata/probes/validateElementFilterMembershipIsModelLevelEvaluable.sysml", + "sha256": "06a3bb1c800e4a04f91233916ec0e6925bc8280713c1d08863c3713f09d2f3bb" + }, + { + "file": "probes/validateEnumerationUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateEnumerationUsageType.sysml", + "sha256": "1655ea5cdbee74465679f7022393ce6c67da366f7cd6340ad3c70cef656121b2" + }, + { + "file": "probes/validateEventOccurrenceUsageReferent.sysml", + "source": "cmd/validation-census/testdata/probes/validateEventOccurrenceUsageReferent.sysml", + "sha256": "a0aabbb39fa5c5686eab8d375ed5bc6feb5605b23ee59b3127274390b5b78c2d" + }, + { + "file": "probes/validateExhibitStateUsageReference.sysml", + "source": "cmd/validation-census/testdata/probes/validateExhibitStateUsageReference.sysml", + "sha256": "5a687df5c996bbb4284e2dd181cc283874e69a9d7a614dd8b81cd0a39fd27cfa" + }, + { + "file": "probes/validateExposeOwningNamespace.sysml", + "source": "cmd/validation-census/testdata/probes/validateExposeOwningNamespace.sysml", + "sha256": "60886b071cc4ff5b608c320dd219822ec0b33638a61760d0d880fac6b3554c80" + }, + { + "file": "probes/validateExpressionResultExpressionMembership.kerml", + "source": "cmd/validation-census/testdata/probes/validateExpressionResultExpressionMembership.kerml", + "sha256": "14d2d06e9b7648cef86d281ecbb37240209f7f63da2ecccf39bb2945f7ba2dd2" + }, + { + "file": "probes/validateExpressionResultExpressionMembership.sysml", + "source": "cmd/validation-census/testdata/probes/validateExpressionResultExpressionMembership.sysml", + "sha256": "ab76f87ce4bfb9d9614b0c1ba709e61944c241f4db99ebc499a7dd2ecc33d364" + }, + { + "file": "probes/validateExpressionResultExpressionMembership.typed.kerml", + "source": "cmd/validation-census/testdata/probes/validateExpressionResultExpressionMembership.typed.kerml", + "sha256": "152830408edcc5c5873296320ad3c6b4418400af52207984d28f5f568599f62b" + }, + { + "file": "probes/validateExpressionResultParameterMembership.kerml", + "source": "cmd/validation-census/testdata/probes/validateExpressionResultParameterMembership.kerml", + "sha256": "99c7488c9a0980c2b5d353b4dc71794a9a08b790f6af91e3ecdfc0c0b89e3f68" + }, + { + "file": "probes/validateFeatureChainExpressionFeatureConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureChainExpressionFeatureConformance.kerml", + "sha256": "6defa056f0a926e6283304abf219a2476fbbda4617ddd34fd06d6b3cfa0cde9d" + }, + { + "file": "probes/validateFeatureChainingFeatureConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureChainingFeatureConformance.kerml", + "sha256": "dd17ab1378f427f4e70920a12d1c53ea8a08762887c53f2d489f727f60093efe" + }, + { + "file": "probes/validateFeatureChainingFeatureNotOne.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureChainingFeatureNotOne.kerml", + "sha256": "9af9ec21c0cae4714fbf4aa7f07cb3e19ea2b6d6844cf338d23ff66a7d4aca0a" + }, + { + "file": "probes/validateFeatureChainingFeaturesNotSelf.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureChainingFeaturesNotSelf.kerml", + "sha256": "1c2fe811403005b8e1803555cb8e68dd8562d7ae83725f273f0a14756c311129" + }, + { + "file": "probes/validateFeatureConstantIsVariable.sysml", + "source": "cmd/validation-census/testdata/probes/validateFeatureConstantIsVariable.sysml", + "sha256": "c8801ee28c22bb1b36e5e62879544d239e1d0fd2e2d73fb1dbf5c5e16778d6e5" + }, + { + "file": "probes/validateFeatureCrossFeatureSpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureCrossFeatureSpecialization.kerml", + "sha256": "b9921a730ad8b4757cf6a2b08de5e2de3fcbe9f2f95721ebcc8d02b9ecf3f9bf" + }, + { + "file": "probes/validateFeatureCrossFeatureType.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureCrossFeatureType.kerml", + "sha256": "c5f7c0a0859ab32cd2cb5cce8be4a2c85e65024146fbf7e60f9d98fac281118b" + }, + { + "file": "probes/validateFeatureEndFeatureMultiplicity.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureEndFeatureMultiplicity.kerml", + "sha256": "c2c87866147c7322771d9e81bfc4eac2ba5eac080970959893030e23d9fbf9f8" + }, + { + "file": "probes/validateFeatureEndNoDirection.sysml", + "source": "cmd/validation-census/testdata/probes/validateFeatureEndNoDirection.sysml", + "sha256": "cc7aeff1ba9b1bf8773dd7ec9644a416deb862c8dfb411dcbf4ec4a9d731ef67" + }, + { + "file": "probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml", + "source": "cmd/validation-census/testdata/probes/validateFeatureEndNotDerivedAbstractCompositeOrPortion.sysml", + "sha256": "1c2e4736fedee61f061c0aeb0c71aa751dbab017edd8a9d9c59cc68897e8be63" + }, + { + "file": "probes/validateFeatureHasType.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureHasType.kerml", + "sha256": "2923608f93d0ebeaf31c0b5e13584814f795943d270c855055cbc132cc465991" + }, + { + "file": "probes/validateFeatureIsVariable.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureIsVariable.kerml", + "sha256": "7746dceee24421c41c7e8abbff7fc000c11ee7f5732ff83eabc8a2775177b1a8" + }, + { + "file": "probes/validateFeatureOwnedCrossSubsetting.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureOwnedCrossSubsetting.kerml", + "sha256": "59f5f9efaab072db156a72f67b61e43536e4a98a0ddeb285d945e0f56e6c30ca" + }, + { + "file": "probes/validateFeatureOwnedReferenceSubsetting.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureOwnedReferenceSubsetting.kerml", + "sha256": "ad0bb0e8ccbdf27467f76cf23427037469c8ae5153116cc6429c0637ce2a0d1c" + }, + { + "file": "probes/validateFeaturePortionNotVariable.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeaturePortionNotVariable.kerml", + "sha256": "049c09930d020f077760225fafb572540b53cc3cdf19526630d652d1906014ae" + }, + { + "file": "probes/validateFeatureReferenceExpressionReferentIsFeature.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureReferenceExpressionReferentIsFeature.kerml", + "sha256": "2778519f39ef0bd9e40dbe1a98dbd0bf40086e357b064a00fc120964885f549a" + }, + { + "file": "probes/validateFeatureValueIsInitial.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureValueIsInitial.kerml", + "sha256": "f6875ba84cdf1cc1463a428d5442367a18e10a5d0e938ebc6ffcedf8aa2d5a46" + }, + { + "file": "probes/validateFeatureValueOverriding.kerml", + "source": "cmd/validation-census/testdata/probes/validateFeatureValueOverriding.kerml", + "sha256": "72d5a77626a1692e25ef6aca9e21f21f2f52ec7ced982979a7090d0493263b5c" + }, + { + "file": "probes/validateFeatureValueOverriding.sysml", + "source": "cmd/validation-census/testdata/probes/validateFeatureValueOverriding.sysml", + "sha256": "f0ade12fc328eec2e6f5825dae7a3ae259647dfb5e9b5eae07e5fa85f1570315" + }, + { + "file": "probes/validateFlowDefinitionConnectionEnds.sysml", + "source": "cmd/validation-census/testdata/probes/validateFlowDefinitionConnectionEnds.sysml", + "sha256": "8e8d46c70f3408e2f003339f33e4ec2d83e855c2e715860f25c974237b49d77d" + }, + { + "file": "probes/validateFlowEndImplicitSubsetting.kerml", + "source": "cmd/validation-census/testdata/probes/validateFlowEndImplicitSubsetting.kerml", + "sha256": "0e66a44f13806fdad6ea1fe4f204bea87e75480bf32b0d6cbe87e7c174a8bf50" + }, + { + "file": "probes/validateFlowEndImplicitSubsetting.sysml", + "source": "cmd/validation-census/testdata/probes/validateFlowEndImplicitSubsetting.sysml", + "sha256": "bd082fb5806c439215a06e5b6291bf20b7243eeefe6b995443947cfc4c2ac6c9" + }, + { + "file": "probes/validateFlowEndSubsetting.kerml", + "source": "cmd/validation-census/testdata/probes/validateFlowEndSubsetting.kerml", + "sha256": "0c00eedca39dbeebb4e0eb5c92ed9b30f9f6c12a529986231a19ff2a7250de1a" + }, + { + "file": "probes/validateFlowUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateFlowUsageType.sysml", + "sha256": "b6f6bf259b3fa0c9d948b70b468a5fadac27c5973e4c86fe02ee7e1a95bc187d" + }, + { + "file": "probes/validateForkNodeIncomingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateForkNodeIncomingSuccessions.sysml", + "sha256": "43ae8e99ead862b7e5075d5e82ef114a836b5c018ef78e9351bae1aff6eaf6a5" + }, + { + "file": "probes/validateFunctionResultExpressionMembership.kerml", + "source": "cmd/validation-census/testdata/probes/validateFunctionResultExpressionMembership.kerml", + "sha256": "80e97209ffe97e690beae488a2cd713b2707f17b236c224c6179cc570fcd5969" + }, + { + "file": "probes/validateFunctionResultExpressionMembership.specialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateFunctionResultExpressionMembership.specialization.kerml", + "sha256": "79ad6bdcf88c090ad95baab1c571d8897e6c2ac05f985a603416f9b1d8d5ec82" + }, + { + "file": "probes/validateFunctionResultExpressionMembership.sysml", + "source": "cmd/validation-census/testdata/probes/validateFunctionResultExpressionMembership.sysml", + "sha256": "52724d7f3d60d70207fc6e7f2e666aabdc522506e837c6c21c82fbfef288195a" + }, + { + "file": "probes/validateFunctionResultParameterMembership.kerml", + "source": "cmd/validation-census/testdata/probes/validateFunctionResultParameterMembership.kerml", + "sha256": "cf2c478f2e3cbdeee86ede3ed517a425f0e1a2d081e5377806425d4c8b7af522" + }, + { + "file": "probes/validateImportTopLevelVisibility.kerml", + "source": "cmd/validation-census/testdata/probes/validateImportTopLevelVisibility.kerml", + "sha256": "146fbb7574e7eae56417683800d70de9b24238dd290330f21e4ff2d5a0cb0223" + }, + { + "file": "probes/validateIncludeUseCaseUsageReference.sysml", + "source": "cmd/validation-census/testdata/probes/validateIncludeUseCaseUsageReference.sysml", + "sha256": "7bd55601f895f10df0dae595ce1061ffcadb8a00f54fa37b6875c1bf03e67513" + }, + { + "file": "probes/validateInstantiationExpressionInstantiatedType.kerml", + "source": "cmd/validation-census/testdata/probes/validateInstantiationExpressionInstantiatedType.kerml", + "sha256": "cec4ee784e423dc8c04fa66af4a349e2e65478343889a00dac3a402f42ee218d" + }, + { + "file": "probes/validateInterfaceDefinitionEnd.sysml", + "source": "cmd/validation-census/testdata/probes/validateInterfaceDefinitionEnd.sysml", + "sha256": "2b8c31a04c6498f4c5bbd2ae2a7b1c95fb860f63b0f13326e2af2c29a90924c4" + }, + { + "file": "probes/validateInterfaceUsageEnd.sysml", + "source": "cmd/validation-census/testdata/probes/validateInterfaceUsageEnd.sysml", + "sha256": "ce009bc0069ac1c861eb6638a214ef45795030b154361db5a1271c65ba7928bb" + }, + { + "file": "probes/validateInterfaceUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateInterfaceUsageType.sysml", + "sha256": "b119d7d929f10b8686782d66839ed3912da8b109b9e14d9619830bad0866d507" + }, + { + "file": "probes/validateInvocationExpressionInstantiatedType.kerml", + "source": "cmd/validation-census/testdata/probes/validateInvocationExpressionInstantiatedType.kerml", + "sha256": "11ffb85e44afb0fdca19ad21b6bbaac156647ca87ec14f1873967ea5b00b59d5" + }, + { + "file": "probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml", + "source": "cmd/validation-census/testdata/probes/validateInvocationExpressionNoDuplicateParameterRedefinition.kerml", + "sha256": "a2d93dd6e30de080d4da3f86ce242dbe1feadba54b26bd28c44f08ad5e36d3e2" + }, + { + "file": "probes/validateInvocationExpressionParameterRedefinition.kerml", + "source": "cmd/validation-census/testdata/probes/validateInvocationExpressionParameterRedefinition.kerml", + "sha256": "6ee5d2ec562ef76bb68594e59b7f014fdc10dede96517a12608b280c2a78beb4" + }, + { + "file": "probes/validateJoinNodeOutgoingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateJoinNodeOutgoingSuccessions.sysml", + "sha256": "2ab6ebe7519892157dbd69068f005ed12771eaf9ee445794991fa54a5f59e7bb" + }, + { + "file": "probes/validateLibraryPackageNotStandard.kerml", + "source": "cmd/validation-census/testdata/probes/validateLibraryPackageNotStandard.kerml", + "sha256": "0937fa7683a19b7c8cc80f36c769c3256cfd8fc827bf06b415274d91b877c5bc" + }, + { + "file": "probes/validateMergeNodeIncomingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateMergeNodeIncomingSuccessions.sysml", + "sha256": "203872be3ba250f4952d28d387141579b4cf394b82fe3c1dcc8779fb3695e153" + }, + { + "file": "probes/validateMergeNodeOutgoingSuccessions.sysml", + "source": "cmd/validation-census/testdata/probes/validateMergeNodeOutgoingSuccessions.sysml", + "sha256": "2162957070ce889c4d7f5622d06c7b91ec0aab7205a6de253512fef67ecc5007" + }, + { + "file": "probes/validateMetadataFeatureAnnotatedElement.kerml", + "source": "cmd/validation-census/testdata/probes/validateMetadataFeatureAnnotatedElement.kerml", + "sha256": "c3bda00fdc8c42e51369b6c5bb1384bdeb3af69293354300e03ec5ff39ef6fe5" + }, + { + "file": "probes/validateMetadataFeatureBody.kerml", + "source": "cmd/validation-census/testdata/probes/validateMetadataFeatureBody.kerml", + "sha256": "897470bf9a6e9f7f36824fe573c9e6c814e75d5e2e7dea741843903db7bd2eab" + }, + { + "file": "probes/validateMetadataFeatureMetadata.kerml", + "source": "cmd/validation-census/testdata/probes/validateMetadataFeatureMetadata.kerml", + "sha256": "94e7450209e727b13688fa7bd0d429ece1c9997abf164aafc2deb1d168b76ca4" + }, + { + "file": "probes/validateMetadataFeatureMetadataNotAbstract.kerml", + "source": "cmd/validation-census/testdata/probes/validateMetadataFeatureMetadataNotAbstract.kerml", + "sha256": "a08d7d0e76ff1013911615afbfcf74f99a1833933d6ea7368958594407d09418" + }, + { + "file": "probes/validateMetadataUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateMetadataUsageType.sysml", + "sha256": "554d83c2cd978fe4e7158c7c130530e5c16be619692d99574aad55ac6ffc7a57" + }, + { + "file": "probes/validateMultiplicityRangeResultTypes.kerml", + "source": "cmd/validation-census/testdata/probes/validateMultiplicityRangeResultTypes.kerml", + "sha256": "1af3a3fe44e228bef91bea58259998ada3bbd90c332dd23b63d80c85cdc7b1ff" + }, + { + "file": "probes/validateNamespaceDistinguishablity.kerml", + "source": "cmd/validation-census/testdata/probes/validateNamespaceDistinguishablity.kerml", + "sha256": "c5046b88f962dc1c4127e4c2c56f4fd6e3dd2d5410e372e68cbee8e360a6ae7f" + }, + { + "file": "probes/validateObjectiveMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateObjectiveMembershipOwningType.sysml", + "sha256": "0f4c676d77707a05eea12b7c93dffde71f65ec5df1852772e2589b9537473e9b" + }, + { + "file": "probes/validateOccurrenceUsageIndividualDefinition.sysml", + "source": "cmd/validation-census/testdata/probes/validateOccurrenceUsageIndividualDefinition.sysml", + "sha256": "b0a844055ea3ab13820b5f02aecd9d1f09ce5029d323e12397d95920f09b9189" + }, + { + "file": "probes/validateOccurrenceUsageIndividualUsage.sysml", + "source": "cmd/validation-census/testdata/probes/validateOccurrenceUsageIndividualUsage.sysml", + "sha256": "8e7ca8491bc4f150ef8fa00eb3cd67a0917269e327fe0f83fb88a7facb040ca2" + }, + { + "file": "probes/validateOccurrenceUsageIsPortion.sysml", + "source": "cmd/validation-census/testdata/probes/validateOccurrenceUsageIsPortion.sysml", + "sha256": "600c3cfcc30f0a13f5d3d08be109398231aa003399ea0fe0ff2c3882c7ef05a7" + }, + { + "file": "probes/validateOccurrenceUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateOccurrenceUsageType.sysml", + "sha256": "5628a55e2dea4e61cd520dab9c5246990fbf54393a105f57260320a50c75cd57" + }, + { + "file": "probes/validateOperatorExpressionBracketOperator.kerml", + "source": "cmd/validation-census/testdata/probes/validateOperatorExpressionBracketOperator.kerml", + "sha256": "a2f09eaef1cf5931fbfc2d7858cb4d89512ef2f46eda61d094b62b6bb0157687" + }, + { + "file": "probes/validateOperatorExpressionCastConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateOperatorExpressionCastConformance.kerml", + "sha256": "365175d9400a8cd731e282c77faa52a0630f546670e47bba6fb3488b41a369c9" + }, + { + "file": "probes/validateOperatorExpressionQuantity.sysml", + "source": "cmd/validation-census/testdata/probes/validateOperatorExpressionQuantity.sysml", + "sha256": "5b9945428003848bb64fe270806a6d6314970f10136556b90f0d94ff4b62ffd3" + }, + { + "file": "probes/validateOwnedDifferencingNotOne.kerml", + "source": "cmd/validation-census/testdata/probes/validateOwnedDifferencingNotOne.kerml", + "sha256": "12a4172ece60492a43fc2a55ce7d067d7932cef439e155a4f676812f7d52ad5a" + }, + { + "file": "probes/validateOwnedIntersectingNotOne.kerml", + "source": "cmd/validation-census/testdata/probes/validateOwnedIntersectingNotOne.kerml", + "sha256": "bbf9fe7ee59d7c9bf601ea088fe7596765a4d42910972e09afd477ee7c2f260e" + }, + { + "file": "probes/validateOwnedUnioningNotOne.kerml", + "source": "cmd/validation-census/testdata/probes/validateOwnedUnioningNotOne.kerml", + "sha256": "6af898ebfe772cf80f9ee3e3f47169fbdff573132048ba79831eef727f986fd4" + }, + { + "file": "probes/validatePerformActionUsageReference.sysml", + "source": "cmd/validation-census/testdata/probes/validatePerformActionUsageReference.sysml", + "sha256": "67656c8054900033faa15f9db34603e484f92febd4bd1cefbc2f86f4455a3ba6" + }, + { + "file": "probes/validatePortDefinitionOwnedUsagesNotComposite.sysml", + "source": "cmd/validation-census/testdata/probes/validatePortDefinitionOwnedUsagesNotComposite.sysml", + "sha256": "722d70f5a0a1b8822e60148a20ade0d10155802d2d68976815290a8a7c18d906" + }, + { + "file": "probes/validatePortUsageIsReference.sysml", + "source": "cmd/validation-census/testdata/probes/validatePortUsageIsReference.sysml", + "sha256": "abee375893983e92c208447bb9c6bcda5c6343b10505f0fca869a21c87c37ad1" + }, + { + "file": "probes/validatePortUsageNestedUsagesNotComposite.sysml", + "source": "cmd/validation-census/testdata/probes/validatePortUsageNestedUsagesNotComposite.sysml", + "sha256": "5f5f9a7d33a86903bcdd2f587888054bd13ff90a0fefc49d29d903dfedcfe828" + }, + { + "file": "probes/validatePortUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validatePortUsageType.sysml", + "sha256": "973f15ada1f48538d770bfb3b290a4a563a6259360995528a07dd29304cf0831" + }, + { + "file": "probes/validateRedefinitionDirectionConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateRedefinitionDirectionConformance.kerml", + "sha256": "2d86964740412e5e888daedf73506d5035d9670f6c6b0645a248c2fe14030215" + }, + { + "file": "probes/validateRedefinitionEndConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateRedefinitionEndConformance.kerml", + "sha256": "4e294bdff639a02dc0eaf235f4f48f2b60a02d8d9b2094c37c0df9b55bb46437" + }, + { + "file": "probes/validateRedefinitionFeaturingTypes.kerml", + "source": "cmd/validation-census/testdata/probes/validateRedefinitionFeaturingTypes.kerml", + "sha256": "8f496ebd1c47d381a3b9e27c48c9981d565b48c9f260c440f6175f33d314a9a4" + }, + { + "file": "probes/validateRedefinitionMultiplicityConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateRedefinitionMultiplicityConformance.kerml", + "sha256": "895d5ee55c6a7cb45658c29d31009d459a99cbe8f060ceb0107e83a191881d15" + }, + { + "file": "probes/validateRenderingUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateRenderingUsageType.sysml", + "sha256": "cd84fd85726b3f295e9c6223da4314cb49ab858884dd43c781a2f35c1abac41e" + }, + { + "file": "probes/validateRequirementConstraintMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementConstraintMembershipOwningType.sysml", + "sha256": "58fd45f1529e66ffbc50b1a365864ee8f9a286bcff4a3140e545f65312f8c5f2" + }, + { + "file": "probes/validateRequirementDefinitionOnlyOneSubject.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementDefinitionOnlyOneSubject.sysml", + "sha256": "b86ec782b0b42f70589950e4606659561a1dd7b1a717a146cf9bb451d3b5c81d" + }, + { + "file": "probes/validateRequirementDefinitionSubjectParameterPosition.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementDefinitionSubjectParameterPosition.sysml", + "sha256": "1e3fdf540a77d8bb9f9955d477a694e0362b25ce96697e42319d890d4e9db466" + }, + { + "file": "probes/validateRequirementUsageOnlyOneSubject.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementUsageOnlyOneSubject.sysml", + "sha256": "c546b453dcdb8dd7f6ddbee14f3af7e7e641d7770e9189611504bd3c888ceb2b" + }, + { + "file": "probes/validateRequirementUsageSubjectParameterPosition.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementUsageSubjectParameterPosition.sysml", + "sha256": "33567afdb58abe09e107e1dfda750b79cd646f9283962f2c7256d89df37c0c57" + }, + { + "file": "probes/validateRequirementUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementUsageType.sysml", + "sha256": "44f358caef373754f7ff9c287157e68e9d6fca39f78dec31dac8cb324d8694e6" + }, + { + "file": "probes/validateRequirementVerificationMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateRequirementVerificationMembershipOwningType.sysml", + "sha256": "cc410b6d1902422709c23343db88820c2d861fc546949979729036fd1528b7bd" + }, + { + "file": "probes/validateReturnParameterMembershipOwningType.kerml", + "source": "cmd/validation-census/testdata/probes/validateReturnParameterMembershipOwningType.kerml", + "sha256": "e414d44a901ba8cf345fae9ded7f18effe5e55c8976b80f2291c6ee839e3425c" + }, + { + "file": "probes/validateSatisfyRequirementUsageReference.sysml", + "source": "cmd/validation-census/testdata/probes/validateSatisfyRequirementUsageReference.sysml", + "sha256": "52687c8ba582bba2eab2431773f22c980a7534f3718f2d5a8ccae6ce001f1dde" + }, + { + "file": "probes/validateSendActionUsagePayloadArgument.sysml", + "source": "cmd/validation-census/testdata/probes/validateSendActionUsagePayloadArgument.sysml", + "sha256": "baa3dffd158e378f094ce8c1fc19c35c0ae6a17047e1bebe7e26d86099f6f1cc" + }, + { + "file": "probes/validateSendActionUsageReceiver.sysml", + "source": "cmd/validation-census/testdata/probes/validateSendActionUsageReceiver.sysml", + "sha256": "0972eb8b6d6ace7826b82926d66a0e8f0f01353344a8968139bd87b915e4c5fb" + }, + { + "file": "probes/validateSpecializationSpecificNotConjugated.kerml", + "source": "cmd/validation-census/testdata/probes/validateSpecializationSpecificNotConjugated.kerml", + "sha256": "d6f8eac60f9165df8dc0a95558d26407147c4efe86797d37ae832ce5ab05c866" + }, + { + "file": "probes/validateSpecializationSpecificNotConjugated.subset.kerml", + "source": "cmd/validation-census/testdata/probes/validateSpecializationSpecificNotConjugated.subset.kerml", + "sha256": "0748697edaf8064a2c65512759fdb86774dc8c0f83eb811cea7c5844d85389e4" + }, + { + "file": "probes/validateStakeholderMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateStakeholderMembershipOwningType.sysml", + "sha256": "62c404b7d5be56a667f511c0eaaba4be780c34b5f8ac22fb848f84e048291fae" + }, + { + "file": "probes/validateStateDefinitionParallelSubactions.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateDefinitionParallelSubactions.sysml", + "sha256": "81ee3a495d01b22250aca1ccddb994c214dfd3375bb707297b108b6d1889b72f" + }, + { + "file": "probes/validateStateDefinitionSubactionKind.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateDefinitionSubactionKind.sysml", + "sha256": "2739286ed5bbf3eead651d3f9fd52ba198f5e190edc24b88983755967e99aa00" + }, + { + "file": "probes/validateStateSubactionMembershioOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateSubactionMembershioOwningType.sysml", + "sha256": "37631cb4594507e02c948440505cb382aae84b1d3dd886160af490e7ff138be1" + }, + { + "file": "probes/validateStateUsageParallelSubactions.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateUsageParallelSubactions.sysml", + "sha256": "581f3251380febbcd7d1634af8e6c3bbabc252b695e23d8d11e06d214be49f0f" + }, + { + "file": "probes/validateStateUsageSubactionKind.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateUsageSubactionKind.sysml", + "sha256": "1f12d812e156330fe462d013e37c53624e63ff4a5d6ff960212dc8ad99e863c6" + }, + { + "file": "probes/validateStateUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateStateUsageType.sysml", + "sha256": "d662bc3f00cb585d3288b5da5b7fb712cd9c1ca5b6a0ea2e1d181aa6df8c5687" + }, + { + "file": "probes/validateStructureSpecialization.kerml", + "source": "cmd/validation-census/testdata/probes/validateStructureSpecialization.kerml", + "sha256": "d43386ae380bf2b22adc1a5c398d435e129ba61f162fa49f530bc2d523333fba" + }, + { + "file": "probes/validateSubjectMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateSubjectMembershipOwningType.sysml", + "sha256": "7e75b74f38b38a1a9af45971c4ca5726743eedf7066c824d4d0e0a422cd54340" + }, + { + "file": "probes/validateSubsettingConstantConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateSubsettingConstantConformance.kerml", + "sha256": "9f6a302d78458f79e0e304ae612e279eb4ffe2383fe0d7a6ca5c67a8c217cb97" + }, + { + "file": "probes/validateSubsettingFeaturingTypes.kerml", + "source": "cmd/validation-census/testdata/probes/validateSubsettingFeaturingTypes.kerml", + "sha256": "5411309d79c16eb3cd53f88524159b3ecf44a4d52b7271c9ec961b2afba22fb8" + }, + { + "file": "probes/validateSubsettingMultiplicityConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateSubsettingMultiplicityConformance.kerml", + "sha256": "ea9abe0cfb7da633ec8b4afa4bda593c4d7aff59ed579c2c77a66b441f139c1c" + }, + { + "file": "probes/validateSubsettingUniquenessConformance.kerml", + "source": "cmd/validation-census/testdata/probes/validateSubsettingUniquenessConformance.kerml", + "sha256": "b9dd0faefdd9426eb243fc66bf3ce542b6cde9dc2310073c67c73f8f0f7a6e1a" + }, + { + "file": "probes/validateTransitionFeatureMembershipGuardExpression.sysml", + "source": "cmd/validation-census/testdata/probes/validateTransitionFeatureMembershipGuardExpression.sysml", + "sha256": "870b3420d8a351bf2e6b993893d1c7a8bff72bb5411026b8b83784d23ff71ab1" + }, + { + "file": "probes/validateTransitionUsageSuccession.sysml", + "source": "cmd/validation-census/testdata/probes/validateTransitionUsageSuccession.sysml", + "sha256": "da5fd2b3de787fe1d7eb9b0fc1ed9e2c4f69b0a94fb02af5cd4e67eca8c15d9c" + }, + { + "file": "probes/validateTransitionUsageTriggerActions.sysml", + "source": "cmd/validation-census/testdata/probes/validateTransitionUsageTriggerActions.sysml", + "sha256": "db81b4c8573885822c6a8a5ddfc20a745b3a8298b03f2620edab2774f821f95b" + }, + { + "file": "probes/validateTriggerInvocationActionAfterArgument.sysml", + "source": "cmd/validation-census/testdata/probes/validateTriggerInvocationActionAfterArgument.sysml", + "sha256": "b7e84977c6ec72bc3db924e50aeb93879d17cea33e7423a2756295aba004554b" + }, + { + "file": "probes/validateTriggerInvocationActionAtArgument.sysml", + "source": "cmd/validation-census/testdata/probes/validateTriggerInvocationActionAtArgument.sysml", + "sha256": "634bdbb68310e46d9ba7e1785336086c4dcf8086b84726917452cae871ee63d3" + }, + { + "file": "probes/validateTriggerInvocationActionWhenArgument.sysml", + "source": "cmd/validation-census/testdata/probes/validateTriggerInvocationActionWhenArgument.sysml", + "sha256": "36e5e4c341188c09c0b39b1a701b6603cdfa048c150cb750bce61bb8726c0a5b" + }, + { + "file": "probes/validateTypeAtMostOneConjugator.kerml", + "source": "cmd/validation-census/testdata/probes/validateTypeAtMostOneConjugator.kerml", + "sha256": "6477e6e99b1bd52aea5ea84f21afdd33be889b861e630927903e049074ba7e5f" + }, + { + "file": "probes/validateTypeDifferencingTypesNotSelf.kerml", + "source": "cmd/validation-census/testdata/probes/validateTypeDifferencingTypesNotSelf.kerml", + "sha256": "d3882b1ca32cdf6e2c7c6b6d64f697aa6c43710180f2d56fa67adec4d9e35049" + }, + { + "file": "probes/validateTypeIntersectingTypesNotSelf.kerml", + "source": "cmd/validation-census/testdata/probes/validateTypeIntersectingTypesNotSelf.kerml", + "sha256": "8ccd6d3fe3ae9bc3a7fbabced0d721f33fa866437bd45c77e2e4c1f63a94fa9b" + }, + { + "file": "probes/validateTypeOwnedMultiplicity.kerml", + "source": "cmd/validation-census/testdata/probes/validateTypeOwnedMultiplicity.kerml", + "sha256": "c02eeda3e1e98cc9bd3fb6d1246682161e132c027364476216ca09d6212cfc60" + }, + { + "file": "probes/validateTypeUnioningTypesNotSelf.kerml", + "source": "cmd/validation-census/testdata/probes/validateTypeUnioningTypesNotSelf.kerml", + "sha256": "3566435d089e1b84b4945a78c4dadcf96fc0fa9a968d6637e09d8aa60483a746" + }, + { + "file": "probes/validateUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateUsageType.sysml", + "sha256": "7e9c886f7f8afb1c136d39711ca0b434f5901a5b7f45eacf986d5758a0266642" + }, + { + "file": "probes/validateUsageVariationMembership.sysml", + "source": "cmd/validation-census/testdata/probes/validateUsageVariationMembership.sysml", + "sha256": "1eb5637966fe3aec0ab07172a4b13f6c69d0e05d5283b619984e8c2f069d892d" + }, + { + "file": "probes/validateUsageVariationSpecialization.sysml", + "source": "cmd/validation-census/testdata/probes/validateUsageVariationSpecialization.sysml", + "sha256": "90b720a8bfdc1a9870e24ef77ee9482fb19e466e32dc120b9d1f62f8a6084c83" + }, + { + "file": "probes/validateUseCaseUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateUseCaseUsageType.sysml", + "sha256": "877e5ad9b819ce6bc10723cdf020855e79ef8baffef27f1843333f6dab877ca5" + }, + { + "file": "probes/validateVariationMembershipOwningNamespace.sysml", + "source": "cmd/validation-census/testdata/probes/validateVariationMembershipOwningNamespace.sysml", + "sha256": "1a3b889691464152d760018635738a58d552271072e228df953f8f10f1922eb0" + }, + { + "file": "probes/validateVerificationCaseUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateVerificationCaseUsageType.sysml", + "sha256": "a77c84a98e38705e1c87759ea58ccc4ffe588d535e9a5c826065ccc8f2dd3cc3" + }, + { + "file": "probes/validateViewDefinitionOnlyOnvViewRendering.sysml", + "source": "cmd/validation-census/testdata/probes/validateViewDefinitionOnlyOnvViewRendering.sysml", + "sha256": "77fa40ace821bb4d04ecd9e4396f8cf1abbab30f9cee7a24a6c7b8c22a4003d9" + }, + { + "file": "probes/validateViewRenderingMembershipOwningType.sysml", + "source": "cmd/validation-census/testdata/probes/validateViewRenderingMembershipOwningType.sysml", + "sha256": "11db4d502cd7889202619ec9fead0b6c0df153d5798feb175d0ae108ec2c3f49" + }, + { + "file": "probes/validateViewUsageOnlyOneRendering.sysml", + "source": "cmd/validation-census/testdata/probes/validateViewUsageOnlyOneRendering.sysml", + "sha256": "1ab8920c49acc25a190d6ca61f4d3f40df6a9b02bbd4b3abbbedd006b407d4b6" + }, + { + "file": "probes/validateViewUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateViewUsageType.sysml", + "sha256": "d129f904b04d4d16005c99bbdf454dd9788b77ea48949ca5d751b592a8708fa0" + }, + { + "file": "probes/validateViewpointUsageType.sysml", + "source": "cmd/validation-census/testdata/probes/validateViewpointUsageType.sysml", + "sha256": "1bdeeafcc4e15e351ce1df41f00ed1a88adde9a308d3534bf93d3f6b7d2b580a" + }, + { + "file": "negative/extensions/x01-initial-state-marker.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x01-initial-state-marker.sysml", + "sha256": "9fdcda5181cd7d60d625583b1a330b07e35235da32bb135ce7931f7971492b36" + }, + { + "file": "negative/extensions/x02-choice-pseudostate.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x02-choice-pseudostate.sysml", + "sha256": "99ed9604dcde4cb9de6e170bfaa353b649aea3341bb92d07c50cbe47e2c991a4" + }, + { + "file": "negative/extensions/x03-junction-pseudostate.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x03-junction-pseudostate.sysml", + "sha256": "5787354b30ce9c3a5e46ea28c5aacc24a80f81a1ee202775511da7c0e20c7aae" + }, + { + "file": "negative/extensions/x04-orthogonal-region.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x04-orthogonal-region.sysml", + "sha256": "5241496b97b24675a8d241ed92cb206110a18a77b3f5cfdddf190f0c2b14aee5" + }, + { + "file": "negative/extensions/x05-defer-member.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x05-defer-member.sysml", + "sha256": "e7474e4f3452a940de6bd0fc281b0b8547499df6d2d2cd2698f558f03f4c96b0" + }, + { + "file": "negative/extensions/x06-history-member.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x06-history-member.sysml", + "sha256": "2b862b37235827c6ac118748d17f08f06fdf25fe40f8f19e6f692cae35551e08" + }, + { + "file": "negative/extensions/x07-transition-to.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x07-transition-to.sysml", + "sha256": "ee2e8119809006b35d1c9f8867d1f0f9eb27e2476ac454bb8e04d41b683eede5" + }, + { + "file": "negative/extensions/x08-require-outside-requirement-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/extensions/x08-require-outside-requirement-body.sysml", + "sha256": "b06b6da37acb3d8ef1bfda92b018373ca3eae40482d6f4ea84c85fc13bf8720d" + }, + { + "file": "negative/grammar/g01-unclosed-package-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g01-unclosed-package-body.sysml", + "sha256": "29e610fb4b7a1d8fcb920fece50ad0240179ae6feb83f49ad8dc11d486925780" + }, + { + "file": "negative/grammar/g02-import-without-visibility.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g02-import-without-visibility.sysml", + "sha256": "99f280ad2a5400e712c15f23ad2cb39e7b80f621c23067263f3b531e83f7e3fe" + }, + { + "file": "negative/grammar/g03-alias-without-for.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g03-alias-without-for.sysml", + "sha256": "0ae5de6d154d4649170fc7ee1b0418bbb4b2e2ef376834cecaf532c71bf9939f" + }, + { + "file": "negative/grammar/g04-specialization-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g04-specialization-without-target.sysml", + "sha256": "00849ca582e1002450bd149a6152ee4646d157399456ec36d006110e8731d5de" + }, + { + "file": "negative/grammar/g05-typing-without-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g05-typing-without-type.sysml", + "sha256": "41f0edb51693626644dd6bb50e8b77368720cdffe98351af5941c659797e103b" + }, + { + "file": "negative/grammar/g06-definition-with-multiplicity.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g06-definition-with-multiplicity.sysml", + "sha256": "ad6ded34c13d1057509c1bfa6929789672488b067517dc63279e7742fbc29615" + }, + { + "file": "negative/grammar/g07-entry-outside-state-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g07-entry-outside-state-body.sysml", + "sha256": "aca89701f7d0bf8b1c4e1393c0718e745905ffefcf943f37072be50c57544981" + }, + { + "file": "negative/grammar/g08-do-outside-state-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g08-do-outside-state-body.sysml", + "sha256": "196c55ad9b9215f43f06419cd09ae61d0b7196a5c72d5f85df0ef42ab3791f12" + }, + { + "file": "negative/grammar/g09-value-without-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g09-value-without-expression.sysml", + "sha256": "22d04a7b64c52612e692e36d0e53ab434b36640af885170fa6d2896d956d7f99" + }, + { + "file": "negative/grammar/g10-operator-without-operand.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g10-operator-without-operand.sysml", + "sha256": "a35935f1754b4a7288cff01b449f036a3a3a8637f54ff3956d855ffb4f32e684" + }, + { + "file": "negative/grammar/g11-assignment-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g11-assignment-without-target.sysml", + "sha256": "9863ae635c0f6ce302c37218eb701c606f9700a28a4e89a134a237727f3632cd" + }, + { + "file": "negative/grammar/g12-unterminated-block-comment.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g12-unterminated-block-comment.sysml", + "sha256": "3d4a6082253432ae25a69eaf805931cab9c433d1753aee41e9a9b2b22c68b3db" + }, + { + "file": "negative/grammar/g13-entry-then-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g13-entry-then-without-target.sysml", + "sha256": "eff848678317dec67c61ba4ece1a5a5a0865b9b6e7f36a5055210d02d94b19c1" + }, + { + "file": "negative/grammar/g14-connect-without-to.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g14-connect-without-to.sysml", + "sha256": "8b2b3f4b3d795fca4a44c38f8f7f505e01fbedd4fe79c0dd3dc2c8a89b092f18" + }, + { + "file": "negative/grammar/g15-keyword-as-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g15-keyword-as-name.sysml", + "sha256": "48e39677639799c68e11df4ed10e7dda738fc56643c28ef23316a1f0a21f2c88" + }, + { + "file": "negative/grammar/g16-expose-without-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g16-expose-without-name.sysml", + "sha256": "1a7a747807d55b8ffb0d4a6306efcf596481a6803b1dcde09516d9bbb1d68c23" + }, + { + "file": "negative/grammar/g17-render-without-usage.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g17-render-without-usage.sysml", + "sha256": "4687e0593e74b5ea92f5affed0492fa0b1da3ac09430b2d8d3eadf944003ac82" + }, + { + "file": "negative/grammar/g18-require-without-constraint.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g18-require-without-constraint.sysml", + "sha256": "5a7e9c76165c27e67c1af21d0eb0d48807855ad467e2b1e9bfe2655f7d7d595b" + }, + { + "file": "negative/grammar/g19-frame-without-concern.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g19-frame-without-concern.sysml", + "sha256": "ea856658f5a71081a9e95a78903be10c6126d28d2a4b69e3207c090952250fdb" + }, + { + "file": "negative/grammar/g20-include-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g20-include-without-target.sysml", + "sha256": "c19fb8428db5d27be018232915ea22a877a3bdb9dcde4cfc1fa1f56becd27bd5" + }, + { + "file": "negative/grammar/g21-filter-without-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g21-filter-without-expression.sysml", + "sha256": "047292df090f92cd6920c391e2bcb693cb30b2a60dfbf3fc9d64d372738d1728" + }, + { + "file": "negative/grammar/g22-dependency-without-to.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g22-dependency-without-to.sysml", + "sha256": "9d7ee1ac5be5c5ecda657d7101e7e9c14d2e10fcf02c1d8f36f35c99fe678292" + }, + { + "file": "negative/grammar/g23-rep-without-language.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g23-rep-without-language.sysml", + "sha256": "5a9dc61e4f571ee18157af99cc2442fb73a1640c36a3035aa043991f7460256f" + }, + { + "file": "negative/grammar/g24-alias-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g24-alias-without-target.sysml", + "sha256": "759481c235d24df2d00636a4f8d11c7538c243692b21308e50b00478cbe23a82" + }, + { + "file": "negative/grammar/g25-library-without-package.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g25-library-without-package.sysml", + "sha256": "14b426dc72c7c38dc93af5b4f0c8b0d33283ed1d6b94a38174f65baceb52b3e0" + }, + { + "file": "negative/grammar/g26-multiplicity-open-range.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g26-multiplicity-open-range.sysml", + "sha256": "e1ef71b5ad9862314e4f333df011ca39a904270cd70b355e573dbc10fd55ca17" + }, + { + "file": "negative/grammar/g27-bind-without-right-end.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g27-bind-without-right-end.sysml", + "sha256": "15cb5485642ae67dff1f93c8ee686d8de9f92fd753d3c5e4f0056f8d8c9175c0" + }, + { + "file": "negative/grammar/g28-succession-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g28-succession-without-target.sysml", + "sha256": "e8d65a2e559495365ec46ce52da3eb2cca5e681c841c5bb502e887ac850aff7a" + }, + { + "file": "negative/grammar/g29-flow-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g29-flow-without-target.sysml", + "sha256": "c053631bb62cf4c3c4c80e42b100f6e2cd1207d45f2bbdcb128ec31f061697e0" + }, + { + "file": "negative/grammar/g30-message-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g30-message-without-target.sysml", + "sha256": "e7bf3a910e1a3626fc9439b6adb25265f547c7b470f818a82a63205a10a4fe2a" + }, + { + "file": "negative/grammar/g31-allocate-without-to.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g31-allocate-without-to.sysml", + "sha256": "2a3034bb47732b851ec0202e15bb7e9f352dc7719d720de884461bae0159e198" + }, + { + "file": "negative/grammar/g32-if-without-condition.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g32-if-without-condition.sysml", + "sha256": "fa4ea9252b78f460b6e5918a475e2758fd745e5c8f74441f2f232aa96b3ed235" + }, + { + "file": "negative/grammar/g33-while-without-condition.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g33-while-without-condition.sysml", + "sha256": "b433ae2f214ab7cf078765039c33ef7aab91c632ae800304735390f18bfde73b" + }, + { + "file": "negative/grammar/g34-for-without-in.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g34-for-without-in.sysml", + "sha256": "49e3698e4622d1fdae6a2442c23ba2a29288e560ec9b928a47ea5bd81e3284e8" + }, + { + "file": "negative/grammar/g35-accept-without-payload.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g35-accept-without-payload.sysml", + "sha256": "65a965c31a199d9f5e511e01222be9d006e2406f3edf88afd494bbe77aace964" + }, + { + "file": "negative/grammar/g36-direction-without-feature.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g36-direction-without-feature.sysml", + "sha256": "7b2fd3ada5bb84ac4091aeff5f2f73c03afbd83946295f28e65603af6be6d807" + }, + { + "file": "negative/grammar/g37-redefines-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g37-redefines-without-target.sysml", + "sha256": "88199ac2d6d14affc1c4be88d95ceb5a0e732ace93370c912b169d5ffc01d72a" + }, + { + "file": "negative/grammar/g38-references-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g38-references-without-target.sysml", + "sha256": "f5e960ef106b38ff6481ca0ca9ded7e4fc4ced2f2f1429b173c16cf70f30bd00" + }, + { + "file": "negative/grammar/g39-redefinition-symbol-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g39-redefinition-symbol-without-target.sysml", + "sha256": "26f2f253e2bab9fb37757e9fbc7a3db1e7fc7495844838c25af429277a3d665d" + }, + { + "file": "negative/grammar/g40-modulo-without-operand.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g40-modulo-without-operand.sysml", + "sha256": "80c7343310d6d50d9dc6afd7c5a29becd864a0feeedb7954951b8edd3c338659" + }, + { + "file": "negative/grammar/g41-exponent-without-operand.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g41-exponent-without-operand.sysml", + "sha256": "8167129cb4dc5fd36b59f9ef656c21b575fb4762f0a627a959836feba5f81eba" + }, + { + "file": "negative/grammar/g42-implies-without-operand.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g42-implies-without-operand.sysml", + "sha256": "06213e580288dae4dab80ab41f88626476aef2f0f4f69c87b3665d2563b96b8c" + }, + { + "file": "negative/grammar/g43-null-coalescing-without-operand.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g43-null-coalescing-without-operand.sysml", + "sha256": "60b86ced0c16eeaf2b092e7da2b518b68bcc64b9ffb57e3f0bbc86ac892bf58e" + }, + { + "file": "negative/grammar/g44-conditional-without-else.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g44-conditional-without-else.sysml", + "sha256": "68a59545fb75a6cec40983041f7ba88ed11fd55bd003d48f46a9936a1b2da991" + }, + { + "file": "negative/grammar/g45-classification-test-without-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g45-classification-test-without-type.sysml", + "sha256": "8291ebe1c06953f9800e3d35c0738e748470099db0835c4c198271c84e73c231" + }, + { + "file": "negative/grammar/g46-cast-without-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g46-cast-without-type.sysml", + "sha256": "36d6a4a70364f392ecdfa1efe148a15110773b1bb3c8e2ac78dce3894f34bb7b" + }, + { + "file": "negative/grammar/g47-prefix-metadata-without-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g47-prefix-metadata-without-name.sysml", + "sha256": "cd34d5b4c86eb2710fd27b0b4e0e8c81ffc43495d261f1f0f08770ead53cf6c8" + }, + { + "file": "negative/grammar/g48-decision-without-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g48-decision-without-body.sysml", + "sha256": "5d06c79240ffdd903389050649505ff9d58f304ad0e2ba3c8c789e88b7ba9956" + }, + { + "file": "negative/grammar/g49-assign-without-value.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g49-assign-without-value.sysml", + "sha256": "07ea44d4a4ac516f4a76a3c4986dfb8a4763b44b90b3881527d94b1bf2e96454" + }, + { + "file": "negative/grammar/g50-conjugated-port-typing-without-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g50-conjugated-port-typing-without-name.sysml", + "sha256": "d765abe4a5f997681afcc3e9999b2c63df8db304e871ce8da425b568d2323202" + }, + { + "file": "negative/grammar/g51-real-without-fraction.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g51-real-without-fraction.sysml", + "sha256": "b324e5c8a7f2baca9537606fba24dc8aedf502f800efaf454d7a63f32ab85e20" + }, + { + "file": "negative/grammar/g52-unterminated-string.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g52-unterminated-string.sysml", + "sha256": "0926be620124fac18f532662abca2512189daa723b7d19304fd801b06d3a4a02" + }, + { + "file": "negative/grammar/g53-range-without-upper-bound.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g53-range-without-upper-bound.sysml", + "sha256": "1f6775a623a6f8026e68403b7b59e29920e20dce465ca7b1dfeb9bf358c0fbad" + }, + { + "file": "negative/grammar/g54-argument-list-trailing-comma.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g54-argument-list-trailing-comma.sysml", + "sha256": "8f923c83328c775e8ea83adde39a8af5368c9634a94b0ad8112a3a291950b52a" + }, + { + "file": "negative/grammar/g55-feature-chain-trailing-dot.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g55-feature-chain-trailing-dot.sysml", + "sha256": "c40fa6f83e5101b94adf36979cd5830cf11d2320260c85c148c0689da369888c" + }, + { + "file": "negative/grammar/g56-qualified-name-trailing-separator.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g56-qualified-name-trailing-separator.sysml", + "sha256": "0509791486e519d63c78e09862fa091350caa0abb6d8d9a984bc0b13483c4710" + }, + { + "file": "negative/grammar/g57-unterminated-unrestricted-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g57-unterminated-unrestricted-name.sysml", + "sha256": "64dfb8213b791ddd8ed119d3c75d73175aff6b7bf6f49b5ea9f5de497605bd50" + }, + { + "file": "negative/grammar/g58-satisfy-without-reference.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g58-satisfy-without-reference.sysml", + "sha256": "c7268c0c71ad1598b72783f6c9c6f6f8dbf9fea59df0e2b4b45ea3287038f43f" + }, + { + "file": "negative/grammar/g59-crosses-without-target.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g59-crosses-without-target.sysml", + "sha256": "361e43ba484f9a98d454adbb07957d3c17fa6c1ac50fb7919089627c3b55b850" + }, + { + "file": "negative/grammar/g60-alias-keyword-as-name.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g60-alias-keyword-as-name.sysml", + "sha256": "8db240618e52a2cc16d0fe41a916bff60b9d220d684d700731aa5091243b3263" + }, + { + "file": "negative/grammar/g61-actor-outside-requirement-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g61-actor-outside-requirement-body.sysml", + "sha256": "1c42449cd7b05e698067eca7910f3b4bdb9e589a9710dfa764bbb4892a2fecc0" + }, + { + "file": "negative/grammar/g62-subject-outside-requirement-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g62-subject-outside-requirement-body.sysml", + "sha256": "35f24e44c29ea1143fd51f8c9394e9b56ac001527d15cb8afdac8248cfc5c3c9" + }, + { + "file": "negative/grammar/g63-objective-outside-case-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g63-objective-outside-case-body.sysml", + "sha256": "a196a3fc2ab8e588f671b7f0dc448e5bc76ceed481a192ff072ce68783a61013" + }, + { + "file": "negative/grammar/g64-stakeholder-outside-requirement-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g64-stakeholder-outside-requirement-body.sysml", + "sha256": "4775c69e0ea3c9bdbd8f82097374a6cab51d14e2af48d5a04d2b0efed35ed89c" + }, + { + "file": "negative/grammar/g65-entry-action-outside-state-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g65-entry-action-outside-state-body.sysml", + "sha256": "d1c9f25edf4efbe6ecc2ce0848991be50fbae87e8897c21f8728f77caf5cad95" + }, + { + "file": "negative/grammar/g66-render-outside-view-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g66-render-outside-view-body.sysml", + "sha256": "dc5386e5fe6b0a4118598b52a5765f94b57494316d5be01e318e61ec7f2f2f22" + }, + { + "file": "negative/grammar/g67-expose-outside-view-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g67-expose-outside-view-body.sysml", + "sha256": "4eb409449b79b59fab52470c295ee456f24851c90030a35182ea47d50e63e8eb" + }, + { + "file": "negative/grammar/g68-definition-in-enumeration-body.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g68-definition-in-enumeration-body.sysml", + "sha256": "afd9f10288bf23dfb707112a807e2e9d64934f597440ebea5299795487c2b9a0" + }, + { + "file": "negative/grammar/g69-calc-body-second-result-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g69-calc-body-second-result-expression.sysml", + "sha256": "aca3b18747cb40da97116dc64eef61061315768e6e73853dc84fb012eeeb9d51" + }, + { + "file": "negative/grammar/g70-name-before-usage-keyword.sysml", + "source": "cmd/pilot-reject/testdata/negative/grammar/g70-name-before-usage-keyword.sysml", + "sha256": "a15cc4d1114b09848b825ea571107eec291cf8e62ded847c123a93fa22619d42" + }, + { + "file": "negative/grammar/k01-specializes-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k01-specializes-without-target.kerml", + "sha256": "ed903802776cb5c4c6ec5e1a7d9549ce0db2b76cf50007c7c2418198cc31322c" + }, + { + "file": "negative/grammar/k02-sysml-keyword-in-kerml.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k02-sysml-keyword-in-kerml.kerml", + "sha256": "6e3e07394e7072566bdcb4a2690e811233448510804b9400acc23c6206e7167e" + }, + { + "file": "negative/grammar/k03-feature-typing-without-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k03-feature-typing-without-type.kerml", + "sha256": "4c28a45160657593a73702996c6a1752af99b697d3b50d6b738b1770799ff3b3" + }, + { + "file": "negative/grammar/k04-dangling-visibility.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k04-dangling-visibility.kerml", + "sha256": "925be73673580e29c14d08faa84eba78fdb2976bf59a8e84dd9f502f1d933680" + }, + { + "file": "negative/grammar/k05-unclosed-body.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k05-unclosed-body.kerml", + "sha256": "cb88ba94fa11a8efa56db011779fc596e4a13d49d06cdb5d39897f4f3d0aa3d6" + }, + { + "file": "negative/grammar/k06-disjoining-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k06-disjoining-without-target.kerml", + "sha256": "d7931451a77a2ad642f0d9e7abfcb31e8546dcb3b23ed210229ac540aeb1fee7" + }, + { + "file": "negative/grammar/k07-conjugation-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k07-conjugation-without-target.kerml", + "sha256": "5dcf32bf3413b07f7c897b74caf845e97e6de7421b5375d01e93c8408a0ab2b5" + }, + { + "file": "negative/grammar/k08-return-without-feature.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k08-return-without-feature.kerml", + "sha256": "cd95e6c72bb95f9a1d111ba6b6423f083f6e2aa7aed30c97e629f8241e2846f8" + }, + { + "file": "negative/grammar/k09-inverting-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k09-inverting-without-target.kerml", + "sha256": "f1a9a8b60de379be054b7c23acee4c27023e346e072e8c64a9778488eca21456" + }, + { + "file": "negative/grammar/k10-featuring-without-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k10-featuring-without-type.kerml", + "sha256": "95c665b40ae04f10e78493ea15ec1566ae49e731a45768f76cada3ec0b69f00d" + }, + { + "file": "negative/grammar/k11-namespace-prefix-metadata-without-name.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k11-namespace-prefix-metadata-without-name.kerml", + "sha256": "3285458fe9bff9ee04b7f9122938387900e023478d8a283dd8ca092ef113c487" + }, + { + "file": "negative/grammar/k12-multiplicity-subset-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k12-multiplicity-subset-without-target.kerml", + "sha256": "2126506441b42eb776515141057daa241b307a5cb4701560121cda1ac4c7b2af" + }, + { + "file": "negative/grammar/k13-step-without-declaration.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k13-step-without-declaration.kerml", + "sha256": "90a88278141dc7d7400f2e3bd0a90b17a5f4cca79f7129fbb70901fd277fd86a" + }, + { + "file": "negative/grammar/k14-flow-without-payload-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k14-flow-without-payload-target.kerml", + "sha256": "13b9abb311113369bf865552052e7c3d2f2155a79e140fd589dd482c4c1c2233" + }, + { + "file": "negative/grammar/k15-conjugation-without-original.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k15-conjugation-without-original.kerml", + "sha256": "7ab2bae5ef43801c53220ce58b57e09873304048bbe3c7bd4734b5a539820291" + }, + { + "file": "negative/grammar/k16-redefinition-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k16-redefinition-without-target.kerml", + "sha256": "e311e90db2cc363fa83f3c4ee0b8548fd34e88d57612aa1831206d5b619ccae0" + }, + { + "file": "negative/grammar/k17-unions-without-target.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k17-unions-without-target.kerml", + "sha256": "9565530613351eb7feeee9b841f403c98078adca227409a33f55118e355cf037" + }, + { + "file": "negative/grammar/k18-connector-end-without-reference.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k18-connector-end-without-reference.kerml", + "sha256": "aa28d786a86ec9d09a37cf595bc035df2050e87fe4fd5d32ef582c6b078e4398" + }, + { + "file": "negative/grammar/k19-metadata-typing-without-name.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k19-metadata-typing-without-name.kerml", + "sha256": "560d8584e831b3914b05c911488e25fb2c7598261119e1b761f43fe9f4dc335f" + }, + { + "file": "negative/grammar/k20-function-body-second-result-expression.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k20-function-body-second-result-expression.kerml", + "sha256": "e651aba59455a0eb3430903faabf29ed412547c9a8e76d1b8ee40210340cd0e8" + }, + { + "file": "negative/grammar/k21-name-before-feature-keyword.kerml", + "source": "cmd/pilot-reject/testdata/negative/grammar/k21-name-before-feature-keyword.kerml", + "sha256": "abc05115810a2f21efd47d53a62828cc47366d8eaec9f0c543cd9e28c7944728" + }, + { + "file": "negative/semantic/cn01-fork-two-incoming.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn01-fork-two-incoming.sysml", + "sha256": "76e16924a6936d1c80337427b08c99c7d99b60a05b721c6c00434b985d6d49c9" + }, + { + "file": "negative/semantic/cn02-join-two-outgoing.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn02-join-two-outgoing.sysml", + "sha256": "43a66e5421da4d77230ed4a1f6e502b0d43348dc1bc0ddff5e656b9af56212ca" + }, + { + "file": "negative/semantic/cn03-merge-two-outgoing.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn03-merge-two-outgoing.sysml", + "sha256": "3069888ca47ec4b79ec292f63c6313118964963592eb60bbaf9e4580f54f2883" + }, + { + "file": "negative/semantic/cn04-decide-two-incoming.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn04-decide-two-incoming.sysml", + "sha256": "b499ace0fc465240c743228e27bc3005a6a6fcc521cad99f1fafe52decc290e5" + }, + { + "file": "negative/semantic/cn05-control-node-outside-action.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn05-control-node-outside-action.sysml", + "sha256": "f77ae21b177dea2353f90cfcb4642f8fdc71182ae44e1f7b90ca9d410e3ac825" + }, + { + "file": "negative/semantic/cn06-fork-incoming-target-multiplicity.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn06-fork-incoming-target-multiplicity.sysml", + "sha256": "5ef2a4724da7a15f3658257565a055c8ab9d10bf0a4c5f6171e2612801969ac9" + }, + { + "file": "negative/semantic/cn07-join-outgoing-source-multiplicity.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn07-join-outgoing-source-multiplicity.sysml", + "sha256": "6aeba7b1afaa07b8bac701a094d5639bfa802800aea2a51ca5ab1abc56f9819e" + }, + { + "file": "negative/semantic/cn08-merge-incoming-source-multiplicity.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn08-merge-incoming-source-multiplicity.sysml", + "sha256": "ed788f8727db7984a985d0c064995a57caf44def7e1027b06650b615e45267d0" + }, + { + "file": "negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/cn09-decide-outgoing-target-multiplicity.sysml", + "sha256": "8f83715c9834b416384a13adaaa5652f0cb29b9443512e6ff1b62333b82e84bf" + }, + { + "file": "negative/semantic/k01-two-owned-multiplicities.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k01-two-owned-multiplicities.kerml", + "sha256": "a1caa8e03eeb77976b4ea6288b40140c4e568fd2dbc565e8820cce913ce282d1" + }, + { + "file": "negative/semantic/k02-differences-one-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k02-differences-one-type.kerml", + "sha256": "7dabcdc58d53e7763218b1d7e1874790270635a990bfc16dc61f3eef112e953c" + }, + { + "file": "negative/semantic/k03-intersects-one-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k03-intersects-one-type.kerml", + "sha256": "0fd49239c2e0388c4f0808c95582dc0dc417b192e003d2ae50b51f4031ba6387" + }, + { + "file": "negative/semantic/k04-unions-one-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k04-unions-one-type.kerml", + "sha256": "212c46b41592f359537f13baa47272e4b4d85dcecc3fa27be61e9798b29e51f7" + }, + { + "file": "negative/semantic/k05-differences-self.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k05-differences-self.kerml", + "sha256": "19805e65d041f7fa88dffe01f20625c981e740f0f59d6442e6bb9df674f8b35b" + }, + { + "file": "negative/semantic/k06-intersects-self.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k06-intersects-self.kerml", + "sha256": "b1576e75edffc043c09e8c5bbdddddf03ba1ed4e4cbda7b610ae684de5f56cd7" + }, + { + "file": "negative/semantic/k07-unions-self.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k07-unions-self.kerml", + "sha256": "01a1ce0e92b6f72ecfa5efa7829868f017cfc20ac903c2e1f59ae110c5ffd22d" + }, + { + "file": "negative/semantic/k08-conjugated-type-specialized.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k08-conjugated-type-specialized.kerml", + "sha256": "fa73d468253bfac5d63dd51e8572ba6a53f25262fe819e53c478c8744db6b2fb" + }, + { + "file": "negative/semantic/k09-two-reference-subsettings.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k09-two-reference-subsettings.kerml", + "sha256": "9615791ae3c075a08aabde44df456b2fdbd646d3a975c6e8a976647a747929c2" + }, + { + "file": "negative/semantic/k10-portion-var-feature.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k10-portion-var-feature.kerml", + "sha256": "6406d5bc818bd8e57cbb3955982c400a9585972ea238a2dfffe2756e0089aa89" + }, + { + "file": "negative/semantic/k11-initial-value-nonvariable.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k11-initial-value-nonvariable.kerml", + "sha256": "399afe2787ad957dc68652cc363ab49638e27c5aa2b527c49b2c131869014e0c" + }, + { + "file": "negative/semantic/k12-chain-through-self.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k12-chain-through-self.kerml", + "sha256": "3147f066f5014f66ddd2f6544d93e60e72264247ae5e2ee110bb3e91b4e9ae34" + }, + { + "file": "negative/semantic/k13-subsets-inaccessible-feature.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k13-subsets-inaccessible-feature.kerml", + "sha256": "dee344fe3ccfd0854da1e6b5c56fb64f0f5743a90943b61fb1f11aad6ff62285" + }, + { + "file": "negative/semantic/k14-variable-subsets-constant.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k14-variable-subsets-constant.kerml", + "sha256": "311b0f61fc215a905da83a81904f8a01caac35e646eefdf299c5c656b3e4ec82" + }, + { + "file": "negative/semantic/k15-nonend-redefines-end.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k15-nonend-redefines-end.kerml", + "sha256": "5908d88ededabbd39e210756a41c31382fb5e0310b2b8814c2eaecf73ca017ff" + }, + { + "file": "negative/semantic/k16-crosses-from-nonend.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k16-crosses-from-nonend.kerml", + "sha256": "8eea7c786cdfdb88fe0e0919f188adde625026c4d0d64d7df08fa8d85852b45b" + }, + { + "file": "negative/semantic/k17-crosses-not-through-opposite-end.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k17-crosses-not-through-opposite-end.kerml", + "sha256": "e452d8f9a1e9f9c670f15aa7374e924b86bcd962e8ee3d5c3298a5bc62d6b4df" + }, + { + "file": "negative/semantic/k18-cross-feature-type-differs.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k18-cross-feature-type-differs.kerml", + "sha256": "80a1cecadd92177a461e10b6c09226f6f6d4c62f6d71f0f264342381d44bf195" + }, + { + "file": "negative/semantic/k19-cross-feature-not-specializing.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k19-cross-feature-not-specializing.kerml", + "sha256": "7d403f9e8a599fb4ce896fd89891578763e78920b9742fe02145685cd61ebba0" + }, + { + "file": "negative/semantic/k20-datatype-specializes-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k20-datatype-specializes-class.kerml", + "sha256": "5a5502e43ec98ca6bbeed34259bf418bafde1b6d7b396a815feba6c495139070" + }, + { + "file": "negative/semantic/k21-class-specializes-datatype.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k21-class-specializes-datatype.kerml", + "sha256": "a1f0574d04a203bc019a56b466d106038fae786ad356faeb24ecd25f1172c96f" + }, + { + "file": "negative/semantic/k22-struct-specializes-behavior.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k22-struct-specializes-behavior.kerml", + "sha256": "b6300b859bd6f3a338c3b31d227ff3aa501391913cec7eca101c713baee6bf28" + }, + { + "file": "negative/semantic/k23-behavior-specializes-struct.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k23-behavior-specializes-struct.kerml", + "sha256": "ceff30950aaacbd79240a90d5913043335fcc16886f433f57b10c498fab4bf1d" + }, + { + "file": "negative/semantic/k24-binary-assoc-three-ends.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k24-binary-assoc-three-ends.kerml", + "sha256": "ab3f838f4abbde1fd3c9e5ec72148096da872571a226f4e01cb42f077e61e856" + }, + { + "file": "negative/semantic/k25-assoc-one-end.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k25-assoc-one-end.kerml", + "sha256": "58bf540494e59c661beed5e164720c026ddc199f00fa77554ebceea242b8fd29" + }, + { + "file": "negative/semantic/k26-binary-connector-three-ends.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k26-binary-connector-three-ends.kerml", + "sha256": "7a87d21071e6843a2f70c0d3d7ebacba8aedc2ad0c0bf006c3ca1d437dbd454a" + }, + { + "file": "negative/semantic/k27-connector-feature-outside-featuring-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k27-connector-feature-outside-featuring-type.kerml", + "sha256": "581607ad4927b403a5690c39582a0df42a2c6b28f97b4d01a169d0395e72ee11" + }, + { + "file": "negative/semantic/k28-expr-two-return-parameters.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k28-expr-two-return-parameters.kerml", + "sha256": "c01e82b4d205dc616ed751e81f8d009700f7ca0e3717240551decb18bbb09215" + }, + { + "file": "negative/semantic/k29-function-inherits-second-result-expression.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k29-function-inherits-second-result-expression.kerml", + "sha256": "e6bee7a213186f2ab8b68fc4c305ddfad9a44282271a08156ea790c859134e84" + }, + { + "file": "negative/semantic/k30-expr-inherits-second-result-expression.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k30-expr-inherits-second-result-expression.kerml", + "sha256": "9acfeb4171aaec01de9c7265889cd10f779c104d901382dd8531def89841c5ab" + }, + { + "file": "negative/semantic/k31-invoke-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k31-invoke-class.kerml", + "sha256": "4e5b8cec2f5fb1323fbd9d282a6e64405353b83798e71fc7f19ae201384fbeb6" + }, + { + "file": "negative/semantic/k32-too-many-arguments.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k32-too-many-arguments.kerml", + "sha256": "2c6b4c23c5e1af8e1e7599e74df5c5c7e31ccb24fe219fa46f13327f28ba3dd7" + }, + { + "file": "negative/semantic/k33-parameter-bound-twice.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k33-parameter-bound-twice.kerml", + "sha256": "42730a2aa7176058b863ed0ff447be4625764a8800b29cb3c9aac0d18e232f92" + }, + { + "file": "negative/semantic/k34-constructor-feature-bound-twice.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k34-constructor-feature-bound-twice.kerml", + "sha256": "61093cf88f78fc5f7759e4ce61a34e9edb804601ca7920dae5a27c6f438834d8" + }, + { + "file": "negative/semantic/k35-metadata-annotates-wrong-kind.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k35-metadata-annotates-wrong-kind.kerml", + "sha256": "39dd6961615fffa4b638218bb77cdd730fa3ab11da2a6b5f415262adc0070180" + }, + { + "file": "negative/semantic/k36-metadata-body-redefines-outside.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k36-metadata-body-redefines-outside.kerml", + "sha256": "f58244e170b7bc3ea5edcde7919111b952c8c7a2368443399ea96a4dfe9b4161" + }, + { + "file": "negative/semantic/k37-multiplicity-bound-not-natural.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k37-multiplicity-bound-not-natural.kerml", + "sha256": "bf1c0bf6fc7bc9f7366a795a3b8a670f835adc6b7032fa35ae0d001bc2427a23" + }, + { + "file": "negative/semantic/k38-flow-end-without-dot-notation.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k38-flow-end-without-dot-notation.kerml", + "sha256": "d92bf6a79b8ad4d17582c2026e30b761e56b50c84177746802bea7524fc67b1a" + }, + { + "file": "negative/semantic/k39-feature-reference-to-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k39-feature-reference-to-class.kerml", + "sha256": "317ee153fe71f3d4476d1eb18c3ab6cebf75fbaa6a06f1d0715164a7ae462555" + }, + { + "file": "negative/semantic/k40-metadata-typed-by-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k40-metadata-typed-by-class.kerml", + "sha256": "5fbcb5688a6f297e611ea4ae0cc2f6e47a7a9a871e9fe84f6c00bd8d223efe43" + }, + { + "file": "negative/semantic/k41-chain-expression-to-nested-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k41-chain-expression-to-nested-class.kerml", + "sha256": "e8c3fb0ac62d5e4ec934277f2692af321ea872dc2c26b595500b338e0f2b17f8" + }, + { + "file": "negative/semantic/k42-two-cross-subsettings.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k42-two-cross-subsettings.kerml", + "sha256": "c8acd2127ed405b024b8d05e9c0b2f344994766ee6fd514f77816f4b4ad0a4b5" + }, + { + "file": "negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k43-expr-typed-by-function-states-second-result-expression.kerml", + "sha256": "71fc6f788b1936f4acca0b5f53b0c1c1ffe33322e539c293e939e708a10ea7a9" + }, + { + "file": "negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k44-expr-referencing-expr-states-second-result-expression.kerml", + "sha256": "1ccd21a11d7222c1b6fe5f367e575b58d4c7b97bda61b9374cbbc844687cdee7" + }, + { + "file": "negative/semantic/k45-conjugated-feature-without-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k45-conjugated-feature-without-type.kerml", + "sha256": "f807ded885321c0188fcdb47467620064c81983bbe0e4f32099006988b225e41" + }, + { + "file": "negative/semantic/k46-conjugated-structure-not-an-object.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k46-conjugated-structure-not-an-object.kerml", + "sha256": "01346b0f68b18b253d6eb767d7ec3d69ddb2341f823eb7dddc6553de32711891" + }, + { + "file": "negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k47-feature-chain-through-alias-to-another-type.kerml", + "sha256": "6fd0ab91759909800da497c63f11ec46d16c2f067c1a756b29805f487fc7ca12" + }, + { + "file": "negative/semantic/k48-annotating-element-annotates-itself.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k48-annotating-element-annotates-itself.kerml", + "sha256": "9bbf8ef9ff1c4499b6de203b973003337034f65185b61cac8c1ac58bc6c28f02" + }, + { + "file": "negative/semantic/k49-binding-connector-with-three-ends.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k49-binding-connector-with-three-ends.kerml", + "sha256": "5e2906b4ca04fdfe262a275a364e74e8fced31875c74e8398973c97d880dc741" + }, + { + "file": "negative/semantic/k50-inline-cross-feature-also-crosses.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k50-inline-cross-feature-also-crosses.kerml", + "sha256": "98cdbca111b6fe0e4027c58fee89502ad816b5692a9fc77aa61513681e8c54f7" + }, + { + "file": "negative/semantic/k51-return-parameter-in-classifier.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k51-return-parameter-in-classifier.kerml", + "sha256": "2f422648ff9423a27a2ef0e0f0829cf09c48994dbcd98a29064a0f6a3b690522" + }, + { + "file": "negative/semantic/k52-two-conjugators.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k52-two-conjugators.kerml", + "sha256": "1142c4bfea9648208d1635cd71e17703dba7b47581d03e7b25e903942fdeaa79" + }, + { + "file": "negative/semantic/k53-boolean-expression-subsets-datatype.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k53-boolean-expression-subsets-datatype.kerml", + "sha256": "ef7112b82ec9cc250081a5be5467514017d344953fca32b0c955f54de1bbad47" + }, + { + "file": "negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k54-cross-feature-typed-narrower-than-end.kerml", + "sha256": "3cafd0d1ca601cd97ea1c0d8a7d53ed7755aed2033415fdac4326188f0325a58" + }, + { + "file": "negative/semantic/k55-subtype-specific-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k55-subtype-specific-is-package.kerml", + "sha256": "9b3d7932e396d5e6dad3f2ebdd804481304faab9c0ea6dcf47a91e9507369ebb" + }, + { + "file": "negative/semantic/k56-subtype-general-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k56-subtype-general-is-package.kerml", + "sha256": "40af7eb1af35dd862e46947a9cadc6874d77f7955737d441fa6e5e131f95c386" + }, + { + "file": "negative/semantic/k57-subclassifier-subclassifier-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k57-subclassifier-subclassifier-is-package.kerml", + "sha256": "edcfcd39125108a44b1e7b35dd55632f439e4be7c6cefb15caf604e035d3ea89" + }, + { + "file": "negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k58-subclassifier-superclassifier-is-feature.kerml", + "sha256": "55f41510200792d0f9489ffecca7fbd1ae4cad61f20d4c341d92aff59f2f8ca5" + }, + { + "file": "negative/semantic/k59-typing-typed-feature-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k59-typing-typed-feature-is-package.kerml", + "sha256": "fda1934888d567e97de8ac37b38b93995b0cbf89ed5f782f7d33e77327ffa663" + }, + { + "file": "negative/semantic/k60-typing-typed-feature-is-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k60-typing-typed-feature-is-class.kerml", + "sha256": "72fd0552f7e294a427f1aaf0c7d81480040a296f1ed29fa2a6c4f5f3a07f0174" + }, + { + "file": "negative/semantic/k61-typing-type-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k61-typing-type-is-package.kerml", + "sha256": "8386ad1f0fec01e6709a12ee4892c57be8f95e1b950c21487abaeae4268ca94c" + }, + { + "file": "negative/semantic/k62-subset-subsetting-feature-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k62-subset-subsetting-feature-is-package.kerml", + "sha256": "cf3730ce937ed53def8a7cf57e48c014ddcea57517c3838f3c5a47e39958630b" + }, + { + "file": "negative/semantic/k63-subset-subsetted-feature-is-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k63-subset-subsetted-feature-is-class.kerml", + "sha256": "84c283a537afc40c78ae9d7cf3ca4f0e4b2c267da3c21ee52ff50f5771805737" + }, + { + "file": "negative/semantic/k64-redefinition-redefining-feature-is-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k64-redefinition-redefining-feature-is-class.kerml", + "sha256": "34dd3ee403171d60ca141097c61c3dce5bc1f87c242add44d5f2431e010679c6" + }, + { + "file": "negative/semantic/k65-redefinition-redefined-feature-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k65-redefinition-redefined-feature-is-package.kerml", + "sha256": "779016a81879bce51020de2a9b8d703524024b6b0068b4392c2cc9bcb7e2823f" + }, + { + "file": "negative/semantic/k66-conjugate-conjugated-type-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k66-conjugate-conjugated-type-is-package.kerml", + "sha256": "4180bacb74837f87536a26169b67a321d6601a1642c0216ceeb6bff94d669dcc" + }, + { + "file": "negative/semantic/k67-conjugate-original-type-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k67-conjugate-original-type-is-package.kerml", + "sha256": "093c664af5a89009df0baa60f5839ea91d34ecd01b51979fc42e9bb3379a35d5" + }, + { + "file": "negative/semantic/k68-inverse-feature-inverted-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k68-inverse-feature-inverted-is-package.kerml", + "sha256": "7ad0ca23461e715dfbfcfa20850b43b0bdda24d29ee6ad9e29d7d91de682e66c" + }, + { + "file": "negative/semantic/k69-inverse-inverting-feature-is-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k69-inverse-inverting-feature-is-class.kerml", + "sha256": "2755eff4bb6b8e358c1d0a95ddadd53bf31c02b8226d8aa58517ca2988e3f98a" + }, + { + "file": "negative/semantic/k70-disjoint-type-disjoined-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k70-disjoint-type-disjoined-is-package.kerml", + "sha256": "a8c8c2fe3fd07e333c6acc95def6d38853454a0dfd469989871479af8793c9ae" + }, + { + "file": "negative/semantic/k71-disjoint-disjoining-type-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k71-disjoint-disjoining-type-is-package.kerml", + "sha256": "f6e6e0340a5ee8478bc7b6067473f6aa983f9e1882f4de666ae685f3649d786a" + }, + { + "file": "negative/semantic/k72-featuring-feature-of-type-is-class.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k72-featuring-feature-of-type-is-class.kerml", + "sha256": "c0038b64d49a3cfc71a13bf34814962f02838606179c3fe290c4e432244f727a" + }, + { + "file": "negative/semantic/k73-featuring-featuring-type-is-package.kerml", + "source": "cmd/pilot-reject/testdata/negative/semantic/k73-featuring-featuring-type-is-package.kerml", + "sha256": "89c0108977c672863769a618924d3fb3b8225e5096c927abb7efc59fcd3da47f" + }, + { + "file": "negative/semantic/s01-action-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s01-action-typed-by-part-def.sysml", + "sha256": "f07d453d407c8f056b0824aac4ba7fc19f3f9cf493d2283425c9fc20d1907c9d" + }, + { + "file": "negative/semantic/s02-allocation-typed-by-connection-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s02-allocation-typed-by-connection-def.sysml", + "sha256": "9930b963df8d27c5a8617f94a73be850c4e9e0454650b81f7648042dd640064c" + }, + { + "file": "negative/semantic/s03-analysis-typed-by-case-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s03-analysis-typed-by-case-def.sysml", + "sha256": "93310066a44507ce13305f1b7630a92d98a10b8d96ab4698420df12aa68315a9" + }, + { + "file": "negative/semantic/s04-assert-references-non-constraint.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s04-assert-references-non-constraint.sysml", + "sha256": "6ad0e902f189dd9b6182c9978507d0b5cce2db0eb5215bc00db120d3ad3fe0e9" + }, + { + "file": "negative/semantic/s05-assign-to-package-level-attribute.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s05-assign-to-package-level-attribute.sysml", + "sha256": "4c99a2d12942aefa9cf4215a4a2105760a488af84fd0781a8f30f8cdd6001f82" + }, + { + "file": "negative/semantic/s06-enum-attribute-two-types.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s06-enum-attribute-two-types.sysml", + "sha256": "400be2e8a49f8b62cb1a9d9f925f34f04266dd6e46dccc02a28e3bb4a7e67e17" + }, + { + "file": "negative/semantic/s07-calc-typed-by-action-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s07-calc-typed-by-action-def.sysml", + "sha256": "aaebd8ee2072e365d2b349f73c0a67869067c3807a297b0ab4ed38c406263b64" + }, + { + "file": "negative/semantic/s08-case-def-two-objectives.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s08-case-def-two-objectives.sysml", + "sha256": "868ab73c809504a7b472ccfb6c752af485c18b3f35cebfa88e1b8053773de626" + }, + { + "file": "negative/semantic/s09-case-def-two-subjects.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s09-case-def-two-subjects.sysml", + "sha256": "5d91f3520498c2a027a0bd6feca8ef15ec36496450a65b1093f665f611c05642" + }, + { + "file": "negative/semantic/s10-case-def-subject-not-first.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s10-case-def-subject-not-first.sysml", + "sha256": "e23a4debcd827d486918fee0b6cce50c0892cb88e95e6826b3e037b398da94d7" + }, + { + "file": "negative/semantic/s11-case-two-objectives.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s11-case-two-objectives.sysml", + "sha256": "090f918cc9dea813be39ce777d8759b5d459ec3054500348676ca2a7c9fe9bd6" + }, + { + "file": "negative/semantic/s12-case-two-subjects.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s12-case-two-subjects.sysml", + "sha256": "688a77923c0fb9dc1d9e5a9e6f21db20fa93e9977316ddabd7ecb2fe75e31063" + }, + { + "file": "negative/semantic/s13-case-subject-not-first.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s13-case-subject-not-first.sysml", + "sha256": "cbd74ef1c309e63236d144ed5c8fb0bf74fd3b977f29b57f4bb49a723ce5cb2b" + }, + { + "file": "negative/semantic/s14-case-typed-by-action-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s14-case-typed-by-action-def.sysml", + "sha256": "5c7a6eacff5a3b49c0e7c622233705e3e57b9f196ba9ecf30f55e06fc3f64909" + }, + { + "file": "negative/semantic/s15-connection-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s15-connection-typed-by-part-def.sysml", + "sha256": "ede3d38184d8ff5b875f5f19dec139ad1a23b663582084d5fccf17b6d367f173" + }, + { + "file": "negative/semantic/s16-event-references-non-occurrence.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s16-event-references-non-occurrence.sysml", + "sha256": "d6560eb37ad03311b958897a780f2f6efc762326e6432c98795902844d6435d3" + }, + { + "file": "negative/semantic/s17-exhibit-references-non-state.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s17-exhibit-references-non-state.sysml", + "sha256": "bcc817c05a96fe35eff2f44d701cb7a1e19b4824fda26b69ebbaac374826b73e" + }, + { + "file": "negative/semantic/s18-flow-def-three-ends.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s18-flow-def-three-ends.sysml", + "sha256": "cd3c290dba956644acc8dd77aee2701c679b6f741f0d25e456cde1787cbcc263" + }, + { + "file": "negative/semantic/s19-flow-typed-by-connection-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s19-flow-typed-by-connection-def.sysml", + "sha256": "01052f49bb00b246ec1b28b980792a242c92e608fe8513d035656048b26216aa" + }, + { + "file": "negative/semantic/s20-include-references-non-use-case.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s20-include-references-non-use-case.sysml", + "sha256": "c3f4122422e81d15474c7cb52680ce789082ed56aef2d5f2f364c091deab8ab2" + }, + { + "file": "negative/semantic/s21-interface-def-end-not-port.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s21-interface-def-end-not-port.sysml", + "sha256": "9dbf82406df16b0e1f1717f583879acaa86f6ecd637c1a441576e2a64c2e5315" + }, + { + "file": "negative/semantic/s22-interface-typed-by-connection-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s22-interface-typed-by-connection-def.sysml", + "sha256": "6e6b5266612c435b7c795748e80d51aca0befda37d9d5d77cf8a60e6f29c3427" + }, + { + "file": "negative/semantic/s23-metadata-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s23-metadata-typed-by-part-def.sysml", + "sha256": "04e1624ca67b3a6c524030653f45dca70c9e61aa2e5da2636bbd6785e6a884c6" + }, + { + "file": "negative/semantic/s24-perform-references-non-action.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s24-perform-references-non-action.sysml", + "sha256": "340d6308219eb41e4b204c3461c32e8f3c5da981b902f288fb6f59022ff731e1" + }, + { + "file": "negative/semantic/s25-port-nested-composite-part.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s25-port-nested-composite-part.sysml", + "sha256": "44e2bf67ecc5d1f3da55a14318043fd14aac1091bb4b3c22d78066e323d7e854" + }, + { + "file": "negative/semantic/s26-port-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s26-port-typed-by-part-def.sysml", + "sha256": "f5846020fa95ec36610dd9a607a5cd42ac1248e493fa7f693a8dce838579afaa" + }, + { + "file": "negative/semantic/s27-rendering-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s27-rendering-typed-by-part-def.sysml", + "sha256": "e4bfe950289284e5eab84f5617ff3f611a8a0b18de00d2b1f366088b9a108c15" + }, + { + "file": "negative/semantic/s28-requirement-def-subject-not-first.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s28-requirement-def-subject-not-first.sysml", + "sha256": "ad86ec3e329b4dfba626f6814d510a046cbd02cd95df49223580a94a4c3436a9" + }, + { + "file": "negative/semantic/s29-requirement-two-subjects.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s29-requirement-two-subjects.sysml", + "sha256": "cf79e6c8ffbd5fa9712aa8bcd1608faf1a938850b6092846e49671652cc1edca" + }, + { + "file": "negative/semantic/s30-requirement-subject-not-first.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s30-requirement-subject-not-first.sysml", + "sha256": "359913a01297998958fd5d761a24f63f899335841c2db383fcaba8d7bc549dda" + }, + { + "file": "negative/semantic/s31-requirement-typed-by-constraint-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s31-requirement-typed-by-constraint-def.sysml", + "sha256": "9769f8a306da979e1076312dd6ff87b04348fb1f4ebf9d68a05883ae6db16aa6" + }, + { + "file": "negative/semantic/s32-satisfy-references-non-requirement.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s32-satisfy-references-non-requirement.sysml", + "sha256": "3834f784258dce54a934092553d94ef2064db4a52aa0f468bc033d84a06eec64" + }, + { + "file": "negative/semantic/s33-parallel-state-usage-with-succession.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s33-parallel-state-usage-with-succession.sysml", + "sha256": "b93b9f8c0e968ed56531ea1860a7a718139624d2af34c01acd64d210e8478fa7" + }, + { + "file": "negative/semantic/s34-state-usage-two-entry-actions.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s34-state-usage-two-entry-actions.sysml", + "sha256": "0d8984409a2bb1cd4871c1fd7182f56e4bcffcb5e6fd7f8a64cd3a2d4b8ee437" + }, + { + "file": "negative/semantic/s35-state-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s35-state-typed-by-part-def.sysml", + "sha256": "224161a3c310f664e0cffe266682257e2a5be3404d99caac72143265e56c0d84" + }, + { + "file": "negative/semantic/s36-usage-typed-by-feature.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s36-usage-typed-by-feature.sysml", + "sha256": "6ac0c2a4a17203d4255f3a9586d4e5393a39f47ec9b94a5a1687328a3a8940b0" + }, + { + "file": "negative/semantic/s37-variation-usage-member-not-variant.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s37-variation-usage-member-not-variant.sysml", + "sha256": "b7b2bb09a32906edaf4feb81457666d28b28e053cc0e7c0f470530762b018bf9" + }, + { + "file": "negative/semantic/s38-use-case-typed-by-case-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s38-use-case-typed-by-case-def.sysml", + "sha256": "b62368fa45ec074e649d688392990792585cdd79cd8741f65d2c9c3cebd0cb3c" + }, + { + "file": "negative/semantic/s39-verification-typed-by-case-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s39-verification-typed-by-case-def.sysml", + "sha256": "dbeb62a8129384fa837001382b412d95b1e78bed9f45de564f9f0e8de9b3d843" + }, + { + "file": "negative/semantic/s40-view-def-two-renderings.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s40-view-def-two-renderings.sysml", + "sha256": "c31f781e99fe7d0047e775e186ef5ba9fd4b1ca594cc7b6fce347e63e05db182" + }, + { + "file": "negative/semantic/s41-view-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s41-view-typed-by-part-def.sysml", + "sha256": "d90466aebdfe75162687b8e5fde322e58950a965eb548294ae021ccc9f243daa" + }, + { + "file": "negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s42-viewpoint-typed-by-requirement-def.sysml", + "sha256": "1ac6cfaf3b4731123361aa2abb8ac2aac6283dea8fd19c03d96d44398c7f0b2a" + }, + { + "file": "negative/semantic/s43-assign-to-non-feature.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s43-assign-to-non-feature.sysml", + "sha256": "bdd82633e3a751c32d22b17e53bb79e91376e156d541da44c8cbbce1f623879c" + }, + { + "file": "negative/semantic/s44-transition-target-not-action.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s44-transition-target-not-action.sysml", + "sha256": "044078720d1ddd88e6c2054bfb048cdc94c8e93941e66dd4b1220bba85ba5857" + }, + { + "file": "negative/semantic/s45-snapshot-outside-occurrence.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s45-snapshot-outside-occurrence.sysml", + "sha256": "e981ac66134f8cf560d7c2daecd6ba33f6fddb361ee6bca7ecaba4cbc952c3a0" + }, + { + "file": "negative/semantic/s46-feature-value-overriding.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s46-feature-value-overriding.sysml", + "sha256": "1cb0deab890c61aa7f7167730a7c5793ab26276a6f972eda6d052af6b1811f1c" + }, + { + "file": "negative/semantic/s47-enumeration-specializes-enumeration.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s47-enumeration-specializes-enumeration.sysml", + "sha256": "14e10194546fa43d072fd21b289cbf3a4280c998f926fb4a3c76a456fdf6f0fd" + }, + { + "file": "negative/semantic/s48-after-trigger-not-duration.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s48-after-trigger-not-duration.sysml", + "sha256": "c09f3d8ee901f5f22ba725bf39959c1f3d47b354f9ee4fbc7e420373cb1821ae" + }, + { + "file": "negative/semantic/s49-at-trigger-not-time-instant.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s49-at-trigger-not-time-instant.sysml", + "sha256": "07b3309c030d43cba7b9c2fce1617ab870a13e516f4f004e2e8759afa3f58653" + }, + { + "file": "negative/semantic/s50-when-trigger-not-boolean.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s50-when-trigger-not-boolean.sysml", + "sha256": "7cc1fac59acb2dcb888e2a9ff81f0173f5409c5ae5b0863807d617ae58b5f243" + }, + { + "file": "negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s51-enum-value-body-typed-outside-enumeration.sysml", + "sha256": "a4ee6b69e747f90cee65315b20f22b95f5aa030df5872c871c18e186b0918297" + }, + { + "file": "negative/semantic/s52-variant-port-composite.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s52-variant-port-composite.sysml", + "sha256": "e056d2d1566209e4e78fa4b70957b2d3f65d420c63e5959a68acbd015325bfdf" + }, + { + "file": "negative/semantic/s80-constant-attribute-not-variable.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s80-constant-attribute-not-variable.sysml", + "sha256": "745101f9d88dfbc45496fab45a3f1ccba81ebf7e94e82d1a22707382c124afab" + }, + { + "file": "negative/semantic/s81-guarded-succession-guard-not-boolean.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s81-guarded-succession-guard-not-boolean.sysml", + "sha256": "cc3e263fd5cd5b089f48cbe50a6960fdbe6ef2ce14caeca7b2226e78dfe05d5d" + }, + { + "file": "negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s82-constraint-specialization-states-second-result-expression.sysml", + "sha256": "c56daa9a9af44e8b1ce0c263aa767487aa97f0f764e758b6a754145afedd3189" + }, + { + "file": "negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s83-redefined-constraint-usage-states-second-result-expression.sysml", + "sha256": "8db6baf16264824e8ee76508b7af17c4db5a51ff8181fe323e413bdc7d1513e0" + }, + { + "file": "negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s84-referencing-constraint-usage-states-second-result-expression.sysml", + "sha256": "6e6acfb04c749eb40b03fd0cf76514a9ad319681ff1d39f3b6d4a7f5ca375e5b" + }, + { + "file": "negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s85-viewpoint-inherits-second-result-expression.sysml", + "sha256": "ec12ae25513485f2b0c2a7e33372a8562e6768d266118c2ca5e161df7bf6f79c" + }, + { + "file": "negative/semantic/s86-end-with-direction.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s86-end-with-direction.sysml", + "sha256": "54c10bb6684f21abc3ea7eae371beb426c3da9ac8632778488d12e24c6d0add9" + }, + { + "file": "negative/semantic/s87-end-derived-or-abstract.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s87-end-derived-or-abstract.sysml", + "sha256": "714404264649ed229c72c2f181fb2c9683483a953f21b24b9765fafdb958340f" + }, + { + "file": "negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s88-cross-feature-typed-narrower-than-end.sysml", + "sha256": "c51f578b7ba2e0d99631edc7f49e6c3239dfb5b3525d872246fcfce5f731f807" + }, + { + "file": "negative/semantic/s89-case-def-inherits-two-objectives.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s89-case-def-inherits-two-objectives.sysml", + "sha256": "45a6eb7d6162aed4b83d6053770c4cc3611ced623e4a08d4207d214fcdb96c21" + }, + { + "file": "negative/semantic/s90-requirement-def-inherits-two-subjects.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s90-requirement-def-inherits-two-subjects.sysml", + "sha256": "31510eac5816337c9c049444ba34dc8261584b7cd331e208acb397c5188ab9f8" + }, + { + "file": "negative/semantic/s91-case-references-second-objective.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s91-case-references-second-objective.sysml", + "sha256": "e67f61e5318c85f2f64e7ca4dec0c7df47af92df0503c24754b8210c99aa08bb" + }, + { + "file": "negative/semantic/s92-requirement-references-second-subject.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s92-requirement-references-second-subject.sysml", + "sha256": "2619a97843e072eb185b18aae6f3043844306ca626d5d01902dd5c7cb77d3266" + }, + { + "file": "negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/s93-assert-through-owner-of-unnamed-assertion.sysml", + "sha256": "930a8abbe9b7a040c4465396d29c64c47ff5f759309d783e0a1893a9866eebdc" + }, + { + "file": "negative/semantic/send-constructor-non-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/send-constructor-non-type.sysml", + "sha256": "c1462621695f2b06877c99b8b7b61975f86cf8cbe1c906cfe0483a12c460ed4c" + }, + { + "file": "negative/semantic/send-payload-non-behavior.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/send-payload-non-behavior.sysml", + "sha256": "dd1f4457a1a2cd4da3781f038bca91ff171d980eead917f956ba5c662c356cb8" + }, + { + "file": "negative/semantic/send-subaction-no-payload.sysml", + "source": "cmd/pilot-reject/testdata/negative/semantic/send-subaction-no-payload.sysml", + "sha256": "fd1dbafefab70819777cd9db46369bcae629b081c7647e50821865303a66ecf6" + }, + { + "file": "negative/xpect/p01-public-root-import.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p01-public-root-import.kerml", + "sha256": "d23dc8a8294a870cf8ac7a046db46fe7f409e91dc069d9484172918898f3aa3e" + }, + { + "file": "negative/xpect/p02-association-end-two-types.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p02-association-end-two-types.kerml", + "sha256": "70d46c0e55be859d35f5037f8aee3b63dae218e27df02e028ec8146ce7d158f3" + }, + { + "file": "negative/xpect/p03-variable-in-datatype.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p03-variable-in-datatype.kerml", + "sha256": "924a8f0b490e47867ac400c562d14ae508040e72e030b4a7a3f2b131a087e577" + }, + { + "file": "negative/xpect/p04-nonunique-subsets-unique.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p04-nonunique-subsets-unique.kerml", + "sha256": "fceeb9e75bb0cd31588eb99941f8d81236141b61599e08d1f3000d057c329e12" + }, + { + "file": "negative/xpect/p05-single-chaining-feature.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p05-single-chaining-feature.kerml", + "sha256": "0b77b5e24c9e3d1cf1e9268c8b456f878b7ff8ed58620ceb4e8f8f7995f78e0a" + }, + { + "file": "negative/xpect/p06-private-member-reference.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p06-private-member-reference.kerml", + "sha256": "fde7364e24cd794641d90f8b27e53c70394cea25cb0340483fe41102eca1eda3" + }, + { + "file": "negative/xpect/p07-extraneous-closing-brace.kerml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p07-extraneous-closing-brace.kerml", + "sha256": "2bc1a4460d46884cbba8cff73280a9c4f27dc4ed2afe097db79dd9b1a8e0a43c" + }, + { + "file": "negative/xpect/p08-variant-outside-variation.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p08-variant-outside-variation.sysml", + "sha256": "047514c6a3d29df31fa3a43fbf8ad75e986bdc001273beaff545e289efc7f5ab" + }, + { + "file": "negative/xpect/p09-variation-member-not-variant.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p09-variation-member-not-variant.sysml", + "sha256": "68e9fc3a4fc01030f13b7b608085d74b60c423d8b6d920f19d0f94ac2ac390d5" + }, + { + "file": "negative/xpect/p10-variation-specializes-variation.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p10-variation-specializes-variation.sysml", + "sha256": "21f60962b93e20cc6a940e60033dc9ecb4fc9b497680c286fcbb9ca462660def" + }, + { + "file": "negative/xpect/p11-metadata-body-not-evaluable.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p11-metadata-body-not-evaluable.sysml", + "sha256": "bffc4ac6385e812529a8342e06ecdfca8990b4039820d9b6cf86f8206a91dde7" + }, + { + "file": "negative/xpect/p12-filter-integer-condition.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p12-filter-integer-condition.sysml", + "sha256": "79e936d6b975b5341b5124d19469affefd0764f471ea97644260d48581722456" + }, + { + "file": "negative/xpect/p13-state-two-entry-actions.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p13-state-two-entry-actions.sysml", + "sha256": "e81a74143d4da2b6e593669b0ff02f15731725d4af7af2f04f4b5e181c5a6a66" + }, + { + "file": "negative/xpect/p14-requirement-two-subjects.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p14-requirement-two-subjects.sysml", + "sha256": "800682eac8fe41bb22ad6932dead0aa6778a8499f48f970f9f4cd964aa891b1b" + }, + { + "file": "negative/xpect/p15-attribute-typed-by-part-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p15-attribute-typed-by-part-def.sysml", + "sha256": "b9d47ab8c6f9f76e6525606ef7772e5ed2de8285d26f88b3cd78abaed8a4391b" + }, + { + "file": "negative/xpect/p16-part-typed-by-attribute-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p16-part-typed-by-attribute-def.sysml", + "sha256": "ecd1841740b347558d209f092a07a4eded23bad2b3f70f4fbd3f2ed7dbf979e1" + }, + { + "file": "negative/xpect/p17-calc-two-return-parameters.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p17-calc-two-return-parameters.sysml", + "sha256": "3c3be56ed943dcbde1da783518188893c644a0accba6ccb3ed91991b803bfbd4" + }, + { + "file": "negative/xpect/p18-enum-two-types.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p18-enum-two-types.sysml", + "sha256": "0e7080c2a21dea3f71ca7fc124c7d1391ab85cd80cdb8b5843dbea9ea34590c5" + }, + { + "file": "negative/xpect/p18-enum-value-typed-outside-enumeration.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p18-enum-value-typed-outside-enumeration.sysml", + "sha256": "35fe24f63079e825750b236ca3c1ff45a23e5902b3944fb7df92b37c4d018c86" + }, + { + "file": "negative/xpect/p19-parallel-state-with-transition.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p19-parallel-state-with-transition.sysml", + "sha256": "f1cabc5b0442450e2d630cbc7dc26d1d80c5aa4db3f6c71f75c03be7a4bf2081" + }, + { + "file": "negative/xpect/p20-connection-with-one-end.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p20-connection-with-one-end.sysml", + "sha256": "00cfeaffc36471bb7af646c58c188dda5ca4536da8118dd720135558ea0fb3bf" + }, + { + "file": "negative/xpect/p21-filter-constructor-condition.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p21-filter-constructor-condition.sysml", + "sha256": "594cef262e56f0b5568bcf4c69ee890bdd06807bd21c655e42dfbecff4876605" + }, + { + "file": "negative/xpect/p22-filter-not-model-level-evaluable.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p22-filter-not-model-level-evaluable.sysml", + "sha256": "3d5dc1a4f00995a44359a17b60e79f1b10b9a56f5e44634530189d49b7e68d74" + }, + { + "file": "negative/xpect/p23-metadata-body-feature-not-redefining.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p23-metadata-body-feature-not-redefining.sysml", + "sha256": "69071eed0a3951bc82f05d39c3bdb877ff62fc167e4a08fcdc0609e43bb8d5f0" + }, + { + "file": "negative/xpect/p24-metadata-abstract-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p24-metadata-abstract-type.sysml", + "sha256": "4aff9c8f8b222cfff7f1c6ee4f3794c869ede431600ccd12dcbc1ff0ab81066f" + }, + { + "file": "negative/xpect/p25-two-individual-definitions.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p25-two-individual-definitions.sysml", + "sha256": "2e67ca5a7db2ef3e6320ce86404263a38629fe04ade5d6797d878046be1227bd" + }, + { + "file": "negative/xpect/p26-port-def-nonreferential-usage.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p26-port-def-nonreferential-usage.sysml", + "sha256": "83c64ab3944d582c223ac8bad83da84fb9a4ac86277327d111c3deb2eb139a20" + }, + { + "file": "negative/xpect/p27-interface-end-not-port.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p27-interface-end-not-port.sysml", + "sha256": "dade43491b5e34a835ba2f00246e41b01ad482bffe48969d720c1d05959fed7e" + }, + { + "file": "negative/xpect/p28-package-level-feature-redefined.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p28-package-level-feature-redefined.sysml", + "sha256": "b9c0fa8bdd241caa981f01124bfce7fa12786c8d2e841e33bdfd0dcda5b17ca0" + }, + { + "file": "negative/xpect/p29-verify-outside-objective.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p29-verify-outside-objective.sysml", + "sha256": "e8c2eb93970abdae6f8deda3c745dd50c67406f982006b07cf3847b55f188b0f" + }, + { + "file": "negative/xpect/p30-two-view-renderings.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p30-two-view-renderings.sysml", + "sha256": "aad124dee496e551273e3529cd8e7b1cc968f11f728acfb2e7016f7300b49057" + }, + { + "file": "negative/xpect/p31-redefinition-incompatible-direction.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p31-redefinition-incompatible-direction.sysml", + "sha256": "a37cb3f6cb8ef4b97016b1b1fc751150dc6d4b86c006d67baa859a1d77f03263" + }, + { + "file": "negative/xpect/p32-redefinition-same-featuring-type.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p32-redefinition-same-featuring-type.sysml", + "sha256": "40f09e0417db77d9f7824bfe3e6bd08bfac9111b1c33d2bed4344479d543e814" + }, + { + "file": "negative/xpect/p33-individual-typed-by-plain-def.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p33-individual-typed-by-plain-def.sysml", + "sha256": "376a0dcceb828108144c7b121eb0c8f31e00228e28a77af9e099b3b1561f3e88" + }, + { + "file": "negative/xpect/p34-accepter-source-not-state.sysml", + "source": "cmd/pilot-reject/testdata/negative/xpect/p34-accepter-source-not-state.sysml", + "sha256": "40ca490f1df6ff7b558241c10ab9d617e9b3234b5fc4d11fdae700eccf6524fc" + } + ] +} diff --git a/crates/sysmlv2-parser/tests/fixtures/opensysml/static-contracts.json b/crates/sysmlv2-parser/tests/fixtures/opensysml/static-contracts.json new file mode 100644 index 0000000..95de157 --- /dev/null +++ b/crates/sysmlv2-parser/tests/fixtures/opensysml/static-contracts.json @@ -0,0 +1,1055 @@ +{ + "external_revision": "d7d432ff410e60f9146c38bfe51b4db749a924b1", + "contracts": [ + { + "fixture": "validateAssertConstraintUsageReference.sysml", + "rule": "validateAssertConstraintUsageReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateAssignmentActionUsageReferent.sysml", + "rule": "validateAssignmentActionUsageReferent", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateAssignmentActionUsageReferentIsTimeVarying.sysml", + "rule": "validateAssignmentActionUsageReferentIsTimeVarying", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateAssociationBinarySpecialization.kerml", + "rule": "validateAssociationBinarySpecialization", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateAssociationEndTypes.kerml", + "rule": "validateAssociationEndTypes", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateAssociationRelatedTypes.kerml", + "rule": "validateAssociationRelatedTypes", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBehaviorSpecialization.kerml", + "rule": "validateBehaviorSpecialization", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBindingConnectorIsBinary.kerml", + "rule": "validateBindingConnectorIsBinary", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBindingConnectorTypeConformance.kerml", + "rule": "validateBindingConnectorTypeConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBindingConnectorTypeConformance.result.kerml", + "rule": "validateBindingConnectorTypeConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBindingConnectorTypeConformance.satisfy.sysml", + "rule": "validateBindingConnectorTypeConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateBindingConnectorTypeConformance.subject.sysml", + "rule": "validateBindingConnectorTypeConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateClassSpecialization.kerml", + "rule": "validateClassSpecialization", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateClassifierDefaultSupertype.kerml", + "rule": "validateClassifierDefaultSupertype", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateConnectorRelatedFeatures.sysml", + "rule": "validateConnectorRelatedFeatures", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml", + "rule": "validateConstructorExpressionNoDuplicateFeatureRedefinition", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateControlNodeIncomingSuccessions.sysml", + "rule": "validateControlNodeIncomingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateControlNodeOutgoingSuccessions.sysml", + "rule": "validateControlNodeOutgoingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateControlNodeOwningType.sysml", + "rule": "validateControlNodeOwningType", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateCrossSubsettingCrossingFeature.kerml", + "rule": "validateCrossSubsettingCrossingFeature", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateDataTypeSpecialization.kerml", + "rule": "validateDataTypeSpecialization", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateDecisionNodeIncomingSuccessions.sysml", + "rule": "validateDecisionNodeIncomingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateDecisionNodeOutgoingSuccessions.sysml", + "rule": "validateDecisionNodeOutgoingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateElementFilterMembershipIsBoolean.kerml", + "rule": "validateElementFilterMembershipIsBoolean", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateElementFilterMembershipIsModelLevelEvaluable.sysml", + "rule": "validateElementFilterMembershipIsModelLevelEvaluable", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateEventOccurrenceUsageReferent.sysml", + "rule": "validateEventOccurrenceUsageReferent", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateExhibitStateUsageReference.sysml", + "rule": "validateExhibitStateUsageReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateExpressionResultExpressionMembership.kerml", + "rule": "validateExpressionResultExpressionMembership", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateExpressionResultParameterMembership.kerml", + "rule": "validateExpressionResultParameterMembership", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureChainExpressionFeatureConformance.kerml", + "rule": "validateFeatureChainExpressionFeatureConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureChainingFeatureConformance.kerml", + "rule": "validateFeatureChainingFeatureConformance", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureChainingFeatureNotOne.kerml", + "rule": "validateFeatureChainingFeatureNotOne", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureChainingFeaturesNotSelf.kerml", + "rule": "validateFeatureChainingFeaturesNotSelf", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureConstantIsVariable.sysml", + "rule": "validateFeatureConstantIsVariable", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureCrossFeatureType.kerml", + "rule": "validateFeatureCrossFeatureType", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureEndFeatureMultiplicity.kerml", + "rule": "validateFeatureEndFeatureMultiplicity", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureHasType.kerml", + "rule": "validateFeatureHasType", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureIsVariable.kerml", + "rule": "validateFeatureIsVariable", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureOwnedCrossSubsetting.kerml", + "rule": "validateFeatureOwnedCrossSubsetting", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureOwnedReferenceSubsetting.kerml", + "rule": "validateFeatureOwnedReferenceSubsetting", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeaturePortionNotVariable.kerml", + "rule": "validateFeaturePortionNotVariable", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureReferenceExpressionReferentIsFeature.kerml", + "rule": "validateFeatureReferenceExpressionReferentIsFeature", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureValueIsInitial.kerml", + "rule": "validateFeatureValueIsInitial", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureValueOverriding.kerml", + "rule": "validateFeatureValueOverriding", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFeatureValueOverriding.sysml", + "rule": "validateFeatureValueOverriding", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFlowEndImplicitSubsetting.kerml", + "rule": "validateFlowEndImplicitSubsetting", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFlowEndImplicitSubsetting.sysml", + "rule": "validateFlowEndImplicitSubsetting", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFlowEndSubsetting.kerml", + "rule": "validateFlowEndSubsetting", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateForkNodeIncomingSuccessions.sysml", + "rule": "validateForkNodeIncomingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFunctionResultExpressionMembership.kerml", + "rule": "validateFunctionResultExpressionMembership", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateFunctionResultParameterMembership.kerml", + "rule": "validateFunctionResultParameterMembership", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateIncludeUseCaseUsageReference.sysml", + "rule": "validateIncludeUseCaseUsageReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateInstantiationExpressionInstantiatedType.kerml", + "rule": "validateInstantiationExpressionInstantiatedType", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateInterfaceDefinitionEnd.sysml", + "rule": "validateInterfaceDefinitionEnd", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateInterfaceUsageEnd.sysml", + "rule": "validateInterfaceUsageEnd", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateInvocationExpressionInstantiatedType.kerml", + "rule": "validateInvocationExpressionInstantiatedType", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateJoinNodeOutgoingSuccessions.sysml", + "rule": "validateJoinNodeOutgoingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateLibraryPackageNotStandard.kerml", + "rule": "validateLibraryPackageNotStandard", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateMergeNodeIncomingSuccessions.sysml", + "rule": "validateMergeNodeIncomingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateMergeNodeOutgoingSuccessions.sysml", + "rule": "validateMergeNodeOutgoingSuccessions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateMetadataFeatureAnnotatedElement.kerml", + "rule": "validateMetadataFeatureAnnotatedElement", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateMetadataFeatureBody.kerml", + "rule": "validateMetadataFeatureBody", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateMetadataFeatureMetadataNotAbstract.kerml", + "rule": "validateMetadataFeatureMetadataNotAbstract", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOccurrenceUsageIndividualDefinition.sysml", + "rule": "validateOccurrenceUsageIndividualDefinition", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOccurrenceUsageIndividualUsage.sysml", + "rule": "validateOccurrenceUsageIndividualUsage", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOccurrenceUsageIsPortion.sysml", + "rule": "validateOccurrenceUsageIsPortion", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOperatorExpressionBracketOperator.kerml", + "rule": "validateOperatorExpressionBracketOperator", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOperatorExpressionCastConformance.kerml", + "rule": "validateOperatorExpressionCastConformance", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOperatorExpressionQuantity.sysml", + "rule": "validateOperatorExpressionQuantity", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOwnedDifferencingNotOne.kerml", + "rule": "validateOwnedDifferencingNotOne", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOwnedIntersectingNotOne.kerml", + "rule": "validateOwnedIntersectingNotOne", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateOwnedUnioningNotOne.kerml", + "rule": "validateOwnedUnioningNotOne", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validatePerformActionUsageReference.sysml", + "rule": "validatePerformActionUsageReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validatePortDefinitionOwnedUsagesNotComposite.sysml", + "rule": "validatePortDefinitionOwnedUsagesNotComposite", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validatePortUsageIsReference.sysml", + "rule": "validatePortUsageIsReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validatePortUsageNestedUsagesNotComposite.sysml", + "rule": "validatePortUsageNestedUsagesNotComposite", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateRedefinitionDirectionConformance.kerml", + "rule": "validateRedefinitionDirectionConformance", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateRedefinitionEndConformance.kerml", + "rule": "validateRedefinitionEndConformance", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateRedefinitionFeaturingTypes.kerml", + "rule": "validateRedefinitionFeaturingTypes", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateRequirementVerificationMembershipOwningType.sysml", + "rule": "validateRequirementVerificationMembershipOwningType", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSatisfyRequirementUsageReference.sysml", + "rule": "validateSatisfyRequirementUsageReference", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSendActionUsagePayloadArgument.sysml", + "rule": "validateSendActionUsagePayloadArgument", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSendActionUsageReceiver.sysml", + "rule": "validateSendActionUsageReceiver", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Warning", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSpecializationSpecificNotConjugated.kerml", + "rule": "validateSpecializationSpecificNotConjugated", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSpecializationSpecificNotConjugated.subset.kerml", + "rule": "validateSpecializationSpecificNotConjugated", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateStateDefinitionParallelSubactions.sysml", + "rule": "validateStateDefinitionParallelSubactions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateStateDefinitionSubactionKind.sysml", + "rule": "validateStateDefinitionSubactionKind", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateStateUsageParallelSubactions.sysml", + "rule": "validateStateUsageParallelSubactions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateStateUsageSubactionKind.sysml", + "rule": "validateStateUsageSubactionKind", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateStructureSpecialization.kerml", + "rule": "validateStructureSpecialization", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSubsettingConstantConformance.kerml", + "rule": "validateSubsettingConstantConformance", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSubsettingFeaturingTypes.kerml", + "rule": "validateSubsettingFeaturingTypes", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateSubsettingUniquenessConformance.kerml", + "rule": "validateSubsettingUniquenessConformance", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTransitionFeatureMembershipGuardExpression.sysml", + "rule": "validateTransitionFeatureMembershipGuardExpression", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTransitionUsageSuccession.sysml", + "rule": "validateTransitionUsageSuccession", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTransitionUsageTriggerActions.sysml", + "rule": "validateTransitionUsageTriggerActions", + "authority": "SysML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTriggerInvocationActionAfterArgument.sysml", + "rule": "validateTriggerInvocationActionAfterArgument", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTriggerInvocationActionAtArgument.sysml", + "rule": "validateTriggerInvocationActionAtArgument", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTriggerInvocationActionWhenArgument.sysml", + "rule": "validateTriggerInvocationActionWhenArgument", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "known result/argument types and resolved library classifiers", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTypeDifferencingTypesNotSelf.kerml", + "rule": "validateTypeDifferencingTypesNotSelf", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTypeIntersectingTypesNotSelf.kerml", + "rule": "validateTypeIntersectingTypesNotSelf", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTypeOwnedMultiplicity.kerml", + "rule": "validateTypeOwnedMultiplicity", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateTypeUnioningTypesNotSelf.kerml", + "rule": "validateTypeUnioningTypesNotSelf", + "authority": "KerML 2025-02 pinned XMI", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateViewDefinitionOnlyOnvViewRendering.sysml", + "rule": "validateViewDefinitionOnlyOnvViewRendering", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + }, + { + "fixture": "validateViewUsageOnlyOneRendering.sysml", + "rule": "validateViewUsageOnlyOneRendering", + "authority": "OpenSysML pinned validator label; absent from 2025-02 XMI inventory", + "prerequisites": "resolved owning, specializing, typing, or reference relationships", + "severity": "Error", + "location": "nonempty source span after the fixture comments", + "full_library_verdict": "violated", + "missing_prerequisites": "unknown; independent structural violations may still be diagnosed" + } + ] +} diff --git a/crates/sysmlv2-parser/tests/format.rs b/crates/sysmlv2-parser/tests/format.rs index 04fd8ce..c6b031d 100644 --- a/crates/sysmlv2-parser/tests/format.rs +++ b/crates/sysmlv2-parser/tests/format.rs @@ -311,3 +311,423 @@ fn at_type_spacing_follows_the_spelling() { "idempotent" ); } + +#[test] +fn anonymous_comment_members_keep_their_indentation() { + // A bare `/* … */` member has no keyword before its body; the body + // printer must not trim the indentation it just received. + let src = "package P {\n part def A {\n /* a member comment */\n attribute x;\n comment /* keyworded */\n }\n /* top-level member */\n}\n"; + let formatted = format_source(src, Dialect::Sysml).unwrap(); + assert_eq!( + formatted, + "package P {\n part def A {\n /* a member comment */\n attribute x;\n /* keyworded */\n }\n /* top-level member */\n}\n" + ); + let again = format_source(&formatted, Dialect::Sysml).unwrap(); + assert_eq!(again, formatted, "not idempotent"); + // A multi-line anonymous body: the opening line keeps the member's + // indentation, so the gutter lines up under it. + let src = "package P {\n part def A {\n /* first\n * second\n */\n }\n}\n"; + let formatted = format_source(src, Dialect::Sysml).unwrap(); + assert_eq!(formatted, src); + assert_eq!( + format_source(&formatted, Dialect::Sysml).unwrap(), + formatted + ); + // A comment with an identification keeps its body on the keyword line. + let src = "package P {\n comment c /* named */\n comment about P /* about */\n}\n"; + let formatted = format_source(src, Dialect::Sysml).unwrap(); + assert_eq!( + formatted, + "package P {\n comment c /* named */\n comment about P /* about */\n}\n" + ); +} + +/// Names that are reserved words print quoted in the dialect that +/// reserves them — and only there — and re-parse: declarations and +/// qualified references alike. +#[test] +fn reserved_word_names_round_trip_in_each_dialect() { + let sysml = "package 'part' {\n part def 'action';\n part 'view' : 'action';\n \ + view 'state' {\n expose 'part'::'view';\n }\n}\n"; + let kerml = "package 'class' {\n classifier 'if';\n feature part : 'if';\n \ + feature 'feature' : 'if';\n}\n"; + for (src, dialect) in [(sysml, Dialect::Sysml), (kerml, Dialect::Kerml)] { + let parsed = parse(src, dialect); + assert!(parsed.diagnostics.is_empty(), "{:?}", parsed.diagnostics); + let printed = print_source(&parsed.unit); + let reparsed = parse(&printed, dialect); + assert!( + reparsed.diagnostics.is_empty(), + "printed output does not parse: {}\n---\n{printed}", + reparsed.diagnostics[0].message + ); + assert_eq!(normalized(&parsed.unit), normalized(&reparsed.unit)); + let formatted = format_source(src, dialect).unwrap(); + assert_eq!( + format_source(&formatted, dialect).unwrap(), + formatted, + "idempotent" + ); + } + let formatted = format_source(sysml, Dialect::Sysml).unwrap(); + assert!( + formatted.contains("part 'view' : 'action';") + && formatted.contains("expose 'part'::'view';"), + "{formatted}" + ); + // `part` is not a KerML word: the KerML printer leaves it bare. + let formatted = format_source(kerml, Dialect::Kerml).unwrap(); + assert!( + formatted.contains("feature part : 'if';") + && formatted.contains("feature 'feature' : 'if';"), + "{formatted}" + ); +} + +/// A binding whose detail carries other than the pair of ends the notation +/// spells — a shape the parser never builds, but one an assembled tree can +/// reach — prints a member that parses and stays that one member. The +/// binding form spells only the pair, so another count is never printed +/// behind it: one end would read as a missing right side, three as a chain +/// of two whose third end is quietly lost. +/// +/// SysML requires the `bind` clause after that keyword, and KerML, which +/// takes the keyword alone, draws a finding for a binding connector that +/// does not bind two features. So in both the member survives as its +/// declaration alone — behind `feature` in KerML, as `ref` where SysML +/// has nothing to declare — and every end with it, spelled as an +/// `end ::> …;` body member. +/// +/// Every case keeps a member *after* the binding: a member that prints as +/// nothing but its terminator parses only in last position, where the +/// repair of a body's result expression swallows it. +#[test] +fn binding_with_other_than_two_ends_still_round_trips() { + use sysmlv2_parser::ast::{Member, MemberKind, UsageDetail, UsageKind}; + + fn set_end_count(unit: &mut SourceUnit, count: usize) { + let MemberKind::Package(p) = &mut unit.members[0].kind else { + panic!("expected a package") + }; + for m in p.body.as_mut().expect("package body") { + if let MemberKind::Usage(u) = &mut m.kind { + if let UsageDetail::Binding { ends } = &mut u.detail { + assert_eq!(ends.len(), 2); + let spare = ends[0].clone(); + ends.resize(count, spare); + } + } + } + } + + fn package_body<'a>(unit: &'a SourceUnit, printed: &str) -> &'a [Member] { + let MemberKind::Package(p) = &unit.members[0].kind else { + panic!("{printed:?}: expected a package") + }; + p.body.as_deref().expect("package body") + } + + for (dialect, src) in [ + (Dialect::Sysml, "package P { bind a = b; part z; }"), + ( + Dialect::Sysml, + "package P { binding b1 : B bind a = b; part z; }", + ), + ( + Dialect::Sysml, + "package P { bind a = b { part q; } part z; }", + ), + ( + Dialect::Sysml, + "package P { binding b1 : B bind a = b { part q; } part z; }", + ), + (Dialect::Kerml, "package P { binding of a = b; feature z; }"), + ( + Dialect::Kerml, + "package P { binding b1 : B of a = b; feature z; }", + ), + ( + Dialect::Kerml, + "package P { binding of a = b { feature q; } feature z; }", + ), + ( + Dialect::Kerml, + "package P { binding b1 : B of a = b { feature q; } feature z; }", + ), + ] { + for count in [0, 1, 3, 4] { + let mut unit = parse(src, dialect).unit; + set_end_count(&mut unit, count); + let printed = print_source(&unit); + let back = parse(&printed, dialect); + assert!( + back.diagnostics.is_empty(), + "{src} with {count} end(s) printed {printed:?}: {:#?}", + back.diagnostics + ); + // Printing what came back changes nothing further. + assert_eq!( + print_source(&back.unit), + printed, + "{src} with {count} end(s): a second round trip moved" + ); + let body = package_body(&back.unit, &printed); + // The connector and the member after it, both still there. + assert_eq!(body.len(), 2, "{printed:?}: a member disappeared"); + let MemberKind::Usage(u) = &body[0].kind else { + panic!("{printed:?}: expected a usage") + }; + assert!( + !printed.contains('='), + "{printed:?}: ends spelled as a pair without one" + ); + // Nothing spells the binding, so the member keeps its + // declaration alone — behind `feature` in KerML, which names + // a metaclass on every member, and as `ref` where SysML has + // nothing to declare — and every end moves into the body as + // an `end` member. + assert!( + !printed.contains("bind") && !printed.contains("connect"), + "{printed:?}: a connector form without its clause" + ); + let declared = src.contains("binding b1"); + assert_eq!( + u.kind, + match (dialect, declared) { + (Dialect::Kerml, _) => UsageKind::Feature, + (_, true) => UsageKind::Default, + (_, false) => UsageKind::Ref, + }, + "{printed:?}" + ); + let kept = u + .body + .iter() + .flatten() + .filter(|m| matches!(&m.kind, MemberKind::Usage(e) if e.prefix.is_end)) + .count(); + assert_eq!(kept, count, "{printed:?}: ends kept"); + } + } + + // The pair the notation does spell still prints as the binding it is. + let unit = parse_source("package P { bind a = b; }").unit; + assert_eq!(print_source(&unit), "package P {\n bind a = b;\n}\n"); + let unit = parse_kerml_source("package P { binding of a = b; }").unit; + assert_eq!(print_source(&unit), "package P {\n binding a = b;\n}\n"); +} + +/// The chain threshold counts operands, not their low eight bits: a chain +/// whose operand count crosses a byte boundary still breaks per condition. +#[test] +fn long_logical_chain_breaks_past_a_byte_of_operands() { + for n in [255usize, 256, 257, 300] { + let chain = (0..n) + .map(|i| format!("a{i} > 0.0")) + .collect::>() + .join(" and "); + let src = format!("package P {{\n constraint c {{\n {chain}\n }}\n}}\n"); + let out = format_source(&src, Dialect::Sysml).unwrap(); + let broken = out + .lines() + .filter(|l| l.trim_start().starts_with("and ")) + .count(); + assert_eq!(broken, n - 1, "{n} operands did not break per condition"); + assert_eq!( + format_source(&out, Dialect::Sysml).unwrap(), + out, + "idempotent" + ); + } +} + +/// A failed format reports one error value: it lists what went wrong, keeps +/// the individual diagnostics reachable as a slice, and propagates with `?`. +#[test] +fn a_failed_format_is_one_error_value() { + const BROKEN: &str = "package P { part a = ; part b = ; }"; + + fn format(src: &str) -> Result> { + Ok(format_source(src, Dialect::Sysml)?) + } + + let listed = format(BROKEN).unwrap_err().to_string(); + let diagnostics = format_source(BROKEN, Dialect::Sysml).unwrap_err(); + assert!(!diagnostics.is_empty()); + assert_eq!(listed.lines().count(), diagnostics.len()); + assert!(listed.starts_with("error: "), "{listed}"); + // The slice is still there behind the wrapper. + assert_eq!(Some(&diagnostics[0]), diagnostics.first()); + assert_eq!(diagnostics.iter().count(), diagnostics.len()); + assert_eq!(diagnostics.clone().into_vec(), diagnostics.to_vec()); +} + +/// The notation's end clause reads two ends or more — `from a to b`, +/// `(a, b, c)` — so a connector an assembled tree gave fewer has no +/// clause to put them in: `(a)` is not a list the parser reads back, and +/// printing one would emit text that fails where it used to succeed. +/// The ends go into the body instead, as the `end ::> …;` members the +/// notation already gives an end written out rather than listed, which +/// is what a one-ended connector lifted from interchange already spells. +#[test] +fn a_connector_below_the_clause_keeps_its_ends_as_members() { + use sysmlv2_parser::ast::{MemberKind, UsageDetail}; + + fn set_end_count(unit: &mut SourceUnit, count: usize) { + let MemberKind::Package(p) = &mut unit.members[0].kind else { + panic!("expected a package") + }; + for m in p.body.as_mut().expect("package body") { + if let MemberKind::Usage(u) = &mut m.kind { + if let UsageDetail::Connector { ends } = &mut u.detail { + assert_eq!(ends.len(), 2); + let spare = ends[0].clone(); + ends.resize(count, spare); + } + } + } + } + + for (dialect, src) in [ + ( + Dialect::Sysml, + "package P { connection c1 connect a to b; part z; }", + ), + (Dialect::Sysml, "package P { connect a to b; part z; }"), + ( + Dialect::Sysml, + "package P { allocation c1 allocate a to b; part z; }", + ), + ( + Dialect::Sysml, + "package P { interface i1 connect a to b; part z; }", + ), + ( + Dialect::Kerml, + "package P { connector c1 from a to b; feature z; }", + ), + ( + Dialect::Kerml, + "package P { connector c1 from a to b { feature q; } feature z; }", + ), + ] { + for count in [0, 1] { + let mut unit = parse(src, dialect).unit; + set_end_count(&mut unit, count); + let printed = print_source(&unit); + let back = parse(&printed, dialect); + assert!( + back.diagnostics.is_empty(), + "{src} with {count} end(s) printed {printed:?}: {:#?}", + back.diagnostics + ); + assert!( + !printed.contains('('), + "{printed:?}: a list the clause does not read" + ); + // Printing what came back changes nothing further. + assert_eq!( + print_source(&back.unit), + printed, + "{src} with {count} end(s): a second round trip moved" + ); + let MemberKind::Package(p) = &back.unit.members[0].kind else { + panic!("{printed:?}: expected a package") + }; + let body = p.body.as_deref().expect("package body"); + assert_eq!(body.len(), 2, "{printed:?}: a member disappeared"); + let MemberKind::Usage(u) = &body[0].kind else { + panic!("{printed:?}: expected a usage") + }; + let kept = u + .body + .iter() + .flatten() + .filter(|m| matches!(&m.kind, MemberKind::Usage(e) if e.prefix.is_end)) + .count(); + assert_eq!(kept, count, "{printed:?}: ends kept"); + } + } +} + +/// An end with no name, no multiplicity and an unspelled target has +/// nothing to print after its prefix. SysML reads a member that is only +/// its prefix; KerML wants an element after one, and stops on the +/// terminator — so the bare end is spelled `end feature;`, naming the +/// metaclass the end has anyway, which both dialects read and print back +/// unchanged. `end;` would leave the other dialect text it cannot parse. +#[test] +fn a_bare_end_member_names_an_element_both_dialects_read() { + use sysmlv2_parser::ast::{MemberKind, TargetRef, UsageDetail}; + + /// Leave the connector one end with nothing spelled on it at all. + fn strip_the_end(unit: &mut SourceUnit) { + let MemberKind::Package(p) = &mut unit.members[0].kind else { + panic!("expected a package") + }; + for m in p.body.as_mut().expect("package body") { + if let MemberKind::Usage(u) = &mut m.kind { + if let UsageDetail::Connector { ends } = &mut u.detail { + ends.truncate(1); + ends[0].name = None; + ends[0].multiplicity = None; + ends[0].target = TargetRef::unspelled(); + } + } + } + } + + for (dialect, src) in [ + ( + Dialect::Sysml, + "package P { connection c1 connect a to b; part z; }", + ), + ( + Dialect::Kerml, + "package P { connector c1 from a to b; feature z; }", + ), + ] { + let mut unit = parse(src, dialect).unit; + strip_the_end(&mut unit); + let printed = print_source(&unit); + assert!(printed.contains("end feature;"), "{printed:?}"); + let back = parse(&printed, dialect); + assert!( + back.diagnostics.is_empty(), + "{printed:?}: {:#?}", + back.diagnostics + ); + assert_eq!( + print_source(&back.unit), + printed, + "{src}: a second round trip moved" + ); + } + + // The spelling itself, in each dialect's own container: what the + // printer writes now is read by both, and what it wrote before was + // read by one. + for (dialect, container) in [ + (Dialect::Sysml, "package P { connection c1 { @ } part z; }"), + ( + Dialect::Kerml, + "package P { connector c1 { @ } feature z; }", + ), + ] { + assert!( + parse(&container.replace('@', "end feature;"), dialect) + .diagnostics + .is_empty(), + "{dialect:?} does not read `end feature;`" + ); + } + assert!( + !parse( + "package P { connector c1 { end; } feature z; }", + Dialect::Kerml + ) + .diagnostics + .is_empty(), + "`end;` reads in both dialects after all" + ); +} diff --git a/crates/sysmlv2-parser/tests/full_baseline.rs b/crates/sysmlv2-parser/tests/full_baseline.rs new file mode 100644 index 0000000..eddccc5 --- /dev/null +++ b/crates/sysmlv2-parser/tests/full_baseline.rs @@ -0,0 +1,257 @@ +//! Full-form corpus baseline: every derived (and owned) property of every +//! element the standard corpus emits, digested per (metaclass, property) +//! and pinned in `tests/fixtures/full-form-baseline.tsv`. +//! +//! The gate that the derived-property port (plan §33) runs under: a +//! change to the emitter must leave every (metaclass, property) digest +//! identical except for the names the change deliberately promotes. A +//! difference prints the changed pairs, so a promotion is adjudicated +//! name by name rather than discovered as a byte diff of a 50k-element +//! payload. Refresh the baseline deliberately with +//! `SYSMLV2_UPDATE_BASELINE=1 cargo test --test full_baseline`; the +//! resulting fixture diff is the change's allowlist and belongs in the +//! same commit. +//! +//! Per pair the fixture carries an order-independent digest of +//! `(element id, canonical JSON value)`, the element count, and how many +//! values are *non-empty* — not `null`, `[]`, `false`, or a self-reference +//! (the catalog's required-reference placeholder; `featureTarget` is the +//! one name whose normative value is legitimately `self` for every +//! unchained feature, so its non-empty count under-reports). The counts +//! feed the derived-property census (`tools/derived_census.py`). + +#![cfg(feature = "json")] + +use serde_json::Value; +use std::collections::BTreeMap; +use std::fs; +use std::path::PathBuf; +use sysmlv2_parser::full::model_to_full_json; +use sysmlv2_parser::model::Model; + +/// Order-independent, version-stable digest of one property across a +/// metaclass: the wrapping sum of per-element FNV-1a hashes, so element +/// order cannot move it and no hashing crate is needed. +#[derive(Default, Clone, Copy, PartialEq, Eq)] +struct Digest { + sum: u64, + elements: u64, + nonempty: u64, +} + +fn fnv1a(bytes: &[u8]) -> u64 { + let mut h: u64 = 0xcbf2_9ce4_8422_2325; + for &b in bytes { + h ^= b as u64; + h = h.wrapping_mul(0x0000_0100_0000_01b3); + } + h +} + +fn is_empty_value(v: &Value, self_id: &str) -> bool { + match v { + Value::Null => true, + Value::Bool(b) => !b, + Value::Array(a) => a.is_empty(), + Value::Object(o) => o.get("@id").and_then(Value::as_str) == Some(self_id), + _ => false, + } +} + +type Table = BTreeMap<(String, String), Digest>; + +fn digest_corpus() -> Option
{ + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return None; + } + let files = sysmlv2_testkit::user_files(); + if files.is_empty() { + eprintln!("skipping: corpus model files not present (sparse checkout without sysml/src)"); + return None; + } + let mut model = Model::new(); + model + .load_library_dir(&root.join("sysml.library")) + .expect("library loads"); + for path in files { + let src = fs::read_to_string(&path).unwrap(); + // Unit names salt the root ids; two corpus files share a basename, + // so name units by corpus-relative path to keep every id unique + // (as the parity and loader gates do). + let name = path + .strip_prefix(&root) + .unwrap_or(&path) + .to_string_lossy() + .into_owned(); + model.add_source(name, &src); + } + let full = model_to_full_json(&model); + let elements = full.as_array().expect("full form is an element array"); + let mut table: Table = BTreeMap::new(); + for el in elements { + let obj = el.as_object().expect("element object"); + let ty = obj["@type"].as_str().expect("@type").to_string(); + let id = obj["@id"].as_str().expect("@id"); + for (k, v) in obj { + if k == "@type" || k == "@id" { + continue; + } + // Canonical: serde_json's map is key-sorted, so nested objects + // serialize deterministically. + let canon = serde_json::to_string(v).unwrap(); + let entry = table.entry((ty.clone(), k.clone())).or_default(); + entry.sum = entry + .sum + .wrapping_add(fnv1a(format!("{id}\t{canon}").as_bytes())); + entry.elements += 1; + if !is_empty_value(v, id) { + entry.nonempty += 1; + } + } + } + Some(table) +} + +fn fixture_path() -> PathBuf { + PathBuf::from(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/full-form-baseline.tsv") +} + +fn render(table: &Table) -> String { + let mut out = String::from("# metaclass\tproperty\tdigest\telements\tnonempty\n"); + for ((ty, prop), d) in table { + out.push_str(&format!( + "{ty}\t{prop}\t{:016x}\t{}\t{}\n", + d.sum, d.elements, d.nonempty + )); + } + out +} + +fn parse(text: &str) -> Table { + let mut table = Table::new(); + for line in text + .lines() + .filter(|l| !l.starts_with('#') && !l.is_empty()) + { + let cols: Vec<&str> = line.split('\t').collect(); + assert_eq!(cols.len(), 5, "malformed baseline line: {line}"); + table.insert( + (cols[0].to_string(), cols[1].to_string()), + Digest { + sum: u64::from_str_radix(cols[2], 16).unwrap(), + elements: cols[3].parse().unwrap(), + nonempty: cols[4].parse().unwrap(), + }, + ); + } + table +} + +#[test] +fn corpus_full_form_matches_baseline() { + let Some(actual) = digest_corpus() else { + return; + }; + let path = fixture_path(); + if std::env::var_os("SYSMLV2_UPDATE_BASELINE").is_some() { + fs::create_dir_all(path.parent().unwrap()).unwrap(); + fs::write(&path, render(&actual)).unwrap(); + eprintln!( + "baseline written: {} pairs over {} metaclasses", + actual.len(), + actual + .keys() + .map(|(t, _)| t) + .collect::>() + .len() + ); + return; + } + let text = fs::read_to_string(&path).unwrap_or_else(|_| { + panic!( + "no baseline at {} — create it with SYSMLV2_UPDATE_BASELINE=1", + path.display() + ) + }); + let expected = parse(&text); + // Aggregate by property: a promoted Type-level name touches ~90 + // metaclasses, so per-pair lines would swamp the report. Metaclasses + // are listed only for properties with few affected pairs. + #[derive(Default)] + struct Change { + added: Vec, + removed: Vec, + changed: Vec, + nonempty_before: u64, + nonempty_after: u64, + } + let mut by_prop: BTreeMap = BTreeMap::new(); + for (key, d) in &actual { + match expected.get(key) { + None => by_prop + .entry(key.1.clone()) + .or_default() + .added + .push(key.0.clone()), + Some(e) if e != d => { + let c = by_prop.entry(key.1.clone()).or_default(); + let what = if e.nonempty == d.nonempty && e.elements == d.elements { + format!("{} (values changed)", key.0) + } else { + format!( + "{} (non-empty {} -> {}, elements {} -> {})", + key.0, e.nonempty, d.nonempty, e.elements, d.elements + ) + }; + c.changed.push(what); + c.nonempty_before += e.nonempty; + c.nonempty_after += d.nonempty; + } + Some(_) => {} + } + } + for key in expected.keys() { + if !actual.contains_key(key) { + by_prop + .entry(key.1.clone()) + .or_default() + .removed + .push(key.0.clone()); + } + } + if !by_prop.is_empty() { + let mut report = String::new(); + for (prop, c) in by_prop.iter().take(100) { + let pairs = c.added.len() + c.removed.len() + c.changed.len(); + report.push_str(&format!( + " {prop}: {pairs} pairs (+{} -{} ~{}; non-empty {} -> {} over the changed pairs)\n", + c.added.len(), + c.removed.len(), + c.changed.len(), + c.nonempty_before, + c.nonempty_after + )); + if pairs <= 10 { + for m in &c.added { + report.push_str(&format!(" + {m}\n")); + } + for m in &c.removed { + report.push_str(&format!(" - {m}\n")); + } + for m in &c.changed { + report.push_str(&format!(" ~ {m}\n")); + } + } + } + if by_prop.len() > 100 { + report.push_str(&format!(" … {} more properties\n", by_prop.len() - 100)); + } + panic!( + "full-form emission differs from the baseline in {} properties; adjudicate each, then \ + refresh with SYSMLV2_UPDATE_BASELINE=1 and commit the fixture diff:\n{report}", + by_prop.len() + ); + } +} diff --git a/crates/sysmlv2-parser/tests/full_json.rs b/crates/sysmlv2-parser/tests/full_json.rs index 5137149..083a1e1 100644 --- a/crates/sysmlv2-parser/tests/full_json.rs +++ b/crates/sysmlv2-parser/tests/full_json.rs @@ -1,12 +1,24 @@ //! Full-form JSON gates: derived properties and implied //! relationships, validated against the published normative schema. +//! +//! One departure from that schema is deliberate and is the exception the +//! conformance note in `INTEROP.md` names: the value of a numeric literal +//! that no JSON number denotes exactly — an integer past 64 bits, more +//! significant digits than a double holds, an exponent outside its range — +//! is emitted as the literal's own text, where the schema declares +//! `LiteralInteger.value` an integer or null and `LiteralRational.value` a +//! number or null. Evaluation reads literals exactly, so rounding one into +//! a JSON number would make a model's two forms disagree about its value. +//! Anything validated here that carries such a literal has to allow the +//! string spelling for that property; nothing else is exempt. #![cfg(feature = "json")] -use serde_json::Value; -use sysmlv2_parser::full::{model_to_full_json, to_full_json}; +use serde_json::{Value, json}; +use std::collections::HashMap; +use sysmlv2_parser::full::{from_compact_value, model_to_full_json, to_full_json}; use sysmlv2_parser::model::Model; -use sysmlv2_parser::parser::parse_source; +use sysmlv2_parser::parser::{parse_kerml_source, parse_source}; fn schema_validator() -> jsonschema::Validator { let path = sysmlv2_testkit::workspace_root().join("spec-refs/SysML.schema.json"); @@ -34,7 +46,7 @@ fn validate_elements(validator_schema: &Value, elements: &[Value]) -> Vec 25 { break; @@ -88,6 +100,10 @@ fn full_form_validates_against_published_schema() { wheel_sub.unwrap()["superclassifier"]["@id"], "0774a545-39e3-5bc1-9607-63beabc6bf65" ); + // An implied specialization is owned by its specific side and says so. + let wheel_sub = *wheel_sub.unwrap(); + assert_eq!(wheel_sub["owningClassifier"], wheel_sub["subclassifier"]); + assert_eq!(wheel_sub["owningType"], wheel_sub["subclassifier"]); // Vehicle has an explicit base? No — it also gets one. car : Vehicle has // explicit typing but no subsetting → implied Subsetting to Parts::parts. assert!(implied.iter().any(|e| e["@type"] == "Subsetting")); @@ -129,11 +145,14 @@ fn full_form_validates_against_published_schema() { #[test] fn full_form_without_library_completes_properties() { - let parse = parse_source("package P { part def V; part v : V; }"); + let parse = parse_source("package P { part def V; part v : V; enum def E { a; } }"); let full = to_full_json(&parse.unit); let elements = full.as_array().unwrap(); - // No library → no implied relationships, flag stays false. + // No library → no implied relationships (the variant typing of `a` + // included), flag stays false: `ownedRelationship->exists(isImplied) + // implies isImpliedIncluded`. assert!(elements.iter().all(|e| e["isImpliedIncluded"] == false)); + assert!(elements.iter().all(|e| e["isImplied"] != true)); let def = elements .iter() .find(|e| e["@type"] == "PartDefinition") @@ -148,6 +167,59 @@ fn full_form_without_library_completes_properties() { assert_eq!(def["ownedElement"].as_array().unwrap().len(), 0); } +/// Element::isLibraryElement follows the ownership tree (KerML +/// deriveElementIsLibraryElement): a `library package` and everything it +/// owns, memberships included, are library elements; nothing else is. +/// The property is a boolean on every element, never null. +#[test] +fn full_form_derives_is_library_element() { + let parse = parse_source( + "library package L { part def X { attribute a; } }\n\ + package P { part def A :> L::X; part a : A; }", + ); + let full = to_full_json(&parse.unit); + let elements = full.as_array().unwrap(); + assert!( + elements.iter().all(|e| e["isLibraryElement"].is_boolean()), + "isLibraryElement must be derived for every element" + ); + let by_qn = |qn: &str| { + elements + .iter() + .find(|e| e["qualifiedName"] == qn) + .unwrap_or_else(|| panic!("no element {qn}")) + }; + for (qn, expected) in [ + ("L", true), + ("L::X", true), + ("L::X::a", true), + ("P", false), + ("P::A", false), + ("P::a", false), + ] { + assert_eq!(by_qn(qn)["isLibraryElement"], expected, "{qn}"); + } + // Relationships take their owning element's answer. + let memberships_of = |qn: &str| { + let id = by_qn(qn)["@id"].clone(); + elements + .iter() + .filter(move |e| e["owningRelatedElement"]["@id"] == id) + .collect::>() + }; + assert!(!memberships_of("L").is_empty()); + assert!( + memberships_of("L") + .iter() + .all(|m| m["isLibraryElement"] == true) + ); + assert!( + memberships_of("P") + .iter() + .all(|m| m["isLibraryElement"] == false) + ); +} + /// Unresolved-reference recovery (`to_full_json_with(recover_refs)`): /// the injected TextualRepresentation annotations are schema-valid like /// every other element, and a partial model round-trips losslessly @@ -211,6 +283,136 @@ fn recovery_annotations_are_schema_valid_and_round_trip() { ); } +/// A `doc`, `comment`, `rep`, or `dependency` written with an +/// identification is an owned member of its namespace, and its owning +/// membership carries that name: an `about` clause — of a comment or of a +/// metadata usage — reaches it by local name, short name, or qualified +/// name, and the emitted Annotation's `annotatedElement` is that element +/// itself. Anonymous ones bind no name at all. +#[test] +fn named_annotating_elements_are_about_targets() { + let src = "package P { + metadata def Note; + part def Vehicle { + doc vehicleDoc /* A vehicle. */ + comment namedComment /* a named comment */ + rep inOCL language \"ocl\" /* self.x > 0 */ + doc /* anonymous */ + comment about namedComment /* local name */ + comment about vd /* short name */ + comment about inOCL /* textual representation */ + @Note about vehicleDoc; + } + comment about Vehicle::vehicleDoc /* qualified */ + comment about P::Vehicle::namedComment /* fully qualified */ + dependency vDep from Vehicle to Note; + comment about vDep /* dependency */ + comment about P::vDep /* qualified dependency */ + }"; + let parse = parse_source(src); + assert!(parse.diagnostics.is_empty()); + let full = sysmlv2_parser::full::to_full_json_with_policy( + &parse.unit, + sysmlv2_parser::full::UnresolvedReferencePolicy::Reject, + ) + .expect("every about target resolves"); + let elements = full.as_array().unwrap(); + let by_id = |id: &Value| elements.iter().find(|e| &e["@id"] == id).unwrap(); + + // Each Annotation, keyed by the body (or metaclass) of the element + // that wrote the `about`, targets the named annotating element. + let mut targets: Vec<(String, String)> = elements + .iter() + .filter(|e| e["@type"] == "Annotation") + .map(|ann| { + let owner = by_id(&ann["owningRelatedElement"]["@id"]); + let target = by_id(&ann["annotatedElement"]["@id"]); + let from = owner["body"] + .as_str() + .map(|b| b.trim().to_string()) + .unwrap_or_else(|| owner["@type"].as_str().unwrap().to_string()); + let to = format!( + "{} {}", + target["@type"].as_str().unwrap(), + target["declaredName"].as_str().unwrap() + ); + (from, to) + }) + .collect(); + targets.sort(); + assert_eq!( + targets, + [ + ("MetadataUsage".into(), "Documentation vehicleDoc".into()), + ("dependency".into(), "Dependency vDep".into()), + ("fully qualified".into(), "Comment namedComment".into()), + ("local name".into(), "Comment namedComment".into()), + ("qualified".into(), "Documentation vehicleDoc".into()), + ("qualified dependency".into(), "Dependency vDep".into()), + ("short name".into(), "Documentation vehicleDoc".into()), + ( + "textual representation".into(), + "TextualRepresentation inOCL".into() + ), + ] + ); + + // The owning memberships name their annotating elements; an anonymous + // one names nothing. + let member_names = |ty: &str| -> Vec<(Option, Option)> { + elements + .iter() + .filter(|e| e["@type"] == ty) + .map(|e| { + let m = by_id(&e["owningRelationship"]["@id"]); + assert_eq!(m["@type"], "OwningMembership"); + ( + m["memberName"].as_str().map(str::to_string), + m["memberShortName"].as_str().map(str::to_string), + ) + }) + .collect() + }; + assert_eq!( + member_names("Documentation"), + [(Some("vehicleDoc".into()), Some("vd".into())), (None, None)] + ); + assert_eq!( + member_names("TextualRepresentation"), + [(Some("inOCL".into()), None)] + ); + assert_eq!(member_names("Dependency"), [(Some("vDep".into()), None)]); + + // The same facts seen through the resolver: the names resolve to the + // annotating elements, nothing resolves *through* one (they own no + // members), and an anonymous element is reachable by no name — in + // particular not by the internal path segment its id derives from. + let mut model = Model::new(); + model.add_source("p.sysml", src); + let mut r = sysmlv2_parser::json::ResolvedModel::build(&model); + for (qn, ty, name) in [ + ("P::Vehicle::vehicleDoc", "Documentation", "vehicleDoc"), + ("P::Vehicle::vd", "Documentation", "vehicleDoc"), + ("P::Vehicle::namedComment", "Comment", "namedComment"), + ("P::Vehicle::inOCL", "TextualRepresentation", "inOCL"), + ("P::vDep", "Dependency", "vDep"), + ] { + let e = r + .resolve_qualified(qn) + .unwrap_or_else(|| panic!("{qn} resolves")); + assert_eq!(r.element_type(e), ty); + assert_eq!(r.element_name(e), Some(name)); + assert!(r.element_scope(e).is_none(), "{qn} owns no scope"); + } + assert!(r.resolve_qualified("P::Vehicle::vehicleDoc::x").is_none()); + assert!(r.resolve_qualified("P::Vehicle::doc3").is_none()); + let vehicle = r.resolve_qualified("P::Vehicle").unwrap(); + let scope = r.element_scope(vehicle).unwrap(); + assert!(r.name_is_bound_in(scope, "vehicleDoc")); + assert!(r.name_is_bound_in(scope, "vd")); + assert!(!r.name_is_bound_in(scope, "doc3")); +} + #[test] fn strict_full_form_rejects_unresolved_references() { let parse = parse_source("package P { part x : Missing; }"); @@ -230,3 +432,706 @@ fn strict_full_form_rejects_unresolved_references() { .is_ok() ); } + +/// The owning-side derived properties and `Type::multiplicity` carry real +/// references instead of the catalog's null default. +#[test] +fn owning_properties_and_multiplicity_derive() { + let parse = parse_source( + "package Demo { + part def Vehicle { + attribute mass; + part wheel[4]; + } + part v : Vehicle { + part w2; + } + }", + ); + assert!(parse.diagnostics.is_empty()); + let full = to_full_json(&parse.unit); + let elements = full.as_array().unwrap(); + let by_name = |n: &str| { + elements + .iter() + .find(|e| e.get("declaredName").and_then(Value::as_str) == Some(n)) + .unwrap() + }; + let id_of = |e: &Value| e.get("@id").unwrap().as_str().unwrap().to_string(); + let ref_id = |e: &Value, k: &str| { + e.get(k) + .and_then(|v| v.get("@id")) + .and_then(Value::as_str) + .map(str::to_string) + }; + + let vehicle = by_name("Vehicle"); + let wheel = by_name("wheel"); + // Feature side: owner through a FeatureMembership. + assert_eq!(ref_id(wheel, "owningType").as_ref(), Some(&id_of(vehicle))); + assert_eq!( + ref_id(wheel, "owningDefinition").as_ref(), + Some(&id_of(vehicle)), + "owner is a Definition" + ); + assert!( + wheel.get("owningUsage").unwrap().is_null(), + "owner is not a Usage" + ); + let fm = ref_id(wheel, "owningFeatureMembership").unwrap(); + let fm_el = elements + .iter() + .find(|e| e.get("@id").and_then(Value::as_str) == Some(fm.as_str())) + .unwrap(); + assert_eq!(fm_el.get("@type").unwrap(), "FeatureMembership"); + // The membership itself names the type on both of its owner properties. + assert_eq!(ref_id(fm_el, "owningType").as_ref(), Some(&id_of(vehicle))); + assert_eq!( + ref_id(fm_el, "membershipOwningNamespace").as_ref(), + Some(&id_of(vehicle)) + ); + // Nested usage: both narrowings point at the usage owner. + let w2 = by_name("w2"); + let v = by_name("v"); + assert_eq!(ref_id(w2, "owningType").as_ref(), Some(&id_of(v))); + assert_eq!(ref_id(w2, "owningUsage").as_ref(), Some(&id_of(v))); + assert!(w2.get("owningDefinition").unwrap().is_null()); + // Package-owned usages have no owning type. + assert!(v.get("owningType").unwrap().is_null()); + // Type::multiplicity references the owned MultiplicityRange. + let mult = ref_id(wheel, "multiplicity").expect("wheel[4] has a multiplicity"); + let mr = elements + .iter() + .find(|e| e.get("@id").and_then(Value::as_str) == Some(mult.as_str())) + .unwrap(); + assert_eq!(mr.get("@type").unwrap(), "MultiplicityRange"); + assert!(by_name("mass").get("multiplicity").unwrap().is_null()); +} + +fn find_named<'a>(elements: &'a [Value], name: &str) -> &'a Value { + elements + .iter() + .find(|e| e.get("declaredName").and_then(Value::as_str) == Some(name)) + .unwrap_or_else(|| panic!("no element named {name}")) +} + +fn find_id<'a>(elements: &'a [Value], id: &str) -> &'a Value { + elements + .iter() + .find(|e| e.get("@id").and_then(Value::as_str) == Some(id)) + .unwrap_or_else(|| panic!("no element with id {id}")) +} + +fn elem_id(e: &Value) -> String { + e["@id"].as_str().unwrap().to_string() +} + +fn ref_of_prop(e: &Value, k: &str) -> Option { + e.get(k) + .and_then(|v| v.get("@id")) + .and_then(Value::as_str) + .map(str::to_string) +} + +fn refs_of_prop(e: &Value, k: &str) -> Vec { + e.get(k) + .and_then(Value::as_array) + .unwrap_or_else(|| panic!("{k} is not an array on {}", e["@type"])) + .iter() + .map(|v| v["@id"].as_str().unwrap().to_string()) + .collect() +} + +/// The relationships of metaclass `kind` whose owning related element is +/// `owner` — the owned (not membership-carried) shape. +fn owned_rels_of_kind<'a>(elements: &'a [Value], kind: &str, owner: &str) -> Vec<&'a Value> { + elements + .iter() + .filter(|e| { + e["@type"] == kind && ref_of_prop(e, "owningRelatedElement").as_deref() == Some(owner) + }) + .collect() +} + +/// Relationship-side owners: a relationship owned by its own source +/// reports that source as `owningType`, narrowed to `owningClassifier` +/// or `owningFeature`; inverting and featuring report `owningFeature` +/// and `owningFeatureOfType`. A standalone relationship rides a +/// membership and reports none of them. +#[test] +fn relationship_side_owners_derive() { + let parse = parse_kerml_source( + "package P { + classifier A; + classifier D; + classifier B specializes A disjoint from D; + classifier X conjugates A; + feature g : A; + feature f : A subsets g inverse of g featured by B; + classifier C specializes B { + feature :>> g; + } + specialization Sub subclassifier B specializes A; + typing g typed by A; + subset g subsets f; + inverse g of f; + featuring g by B; + conjugate D ~ A; + disjoint D from A; + }", + ); + assert!(parse.diagnostics.is_empty(), "{:?}", parse.diagnostics); + let full = to_full_json(&parse.unit); + let elements = full.as_array().unwrap(); + let a = elem_id(find_named(elements, "A")); + let b = elem_id(find_named(elements, "B")); + let d = elem_id(find_named(elements, "D")); + let x = elem_id(find_named(elements, "X")); + let f = elem_id(find_named(elements, "f")); + + let [sub] = owned_rels_of_kind(elements, "Subclassification", &b)[..] else { + panic!("B owns exactly one Subclassification"); + }; + assert_eq!(ref_of_prop(sub, "owningType").as_deref(), Some(b.as_str())); + assert_eq!( + ref_of_prop(sub, "owningClassifier").as_deref(), + Some(b.as_str()) + ); + assert!( + sub.get("owningFeature").is_none(), + "not a Subclassification property" + ); + + let [dis] = owned_rels_of_kind(elements, "Disjoining", &b)[..] else { + panic!("B owns exactly one Disjoining"); + }; + assert_eq!(ref_of_prop(dis, "owningType").as_deref(), Some(b.as_str())); + + let [conj] = owned_rels_of_kind(elements, "Conjugation", &x)[..] else { + panic!("X owns exactly one Conjugation"); + }; + assert_eq!(ref_of_prop(conj, "owningType").as_deref(), Some(x.as_str())); + + let [typing] = owned_rels_of_kind(elements, "FeatureTyping", &f)[..] else { + panic!("f owns exactly one FeatureTyping"); + }; + assert_eq!( + ref_of_prop(typing, "owningType").as_deref(), + Some(f.as_str()) + ); + assert_eq!( + ref_of_prop(typing, "owningFeature").as_deref(), + Some(f.as_str()) + ); + let [subsetting] = owned_rels_of_kind(elements, "Subsetting", &f)[..] else { + panic!("f owns exactly one Subsetting"); + }; + assert_eq!( + ref_of_prop(subsetting, "owningFeature").as_deref(), + Some(f.as_str()) + ); + let [inverting] = owned_rels_of_kind(elements, "FeatureInverting", &f)[..] else { + panic!("f owns exactly one FeatureInverting"); + }; + assert_eq!( + ref_of_prop(inverting, "owningFeature").as_deref(), + Some(f.as_str()) + ); + assert!( + inverting.get("owningType").is_none(), + "an inverting is not a specialization" + ); + let [featuring] = owned_rels_of_kind(elements, "TypeFeaturing", &f)[..] else { + panic!("f owns exactly one TypeFeaturing"); + }; + assert_eq!( + ref_of_prop(featuring, "owningFeatureOfType").as_deref(), + Some(f.as_str()) + ); + + // The anonymous redefining feature in C owns its Redefinition. + let redefinition = elements + .iter() + .find(|e| e["@type"] == "Redefinition") + .expect("one redefinition"); + let redefiner = + ref_of_prop(redefinition, "owningRelatedElement").expect("owned by its feature"); + assert_eq!( + ref_of_prop(redefinition, "owningFeature"), + Some(redefiner.clone()) + ); + assert_eq!(ref_of_prop(redefinition, "owningType"), Some(redefiner)); + + // A standalone relationship is a member, not an owned relationship, and + // names no owner of any kind — for every family. + let sub = find_named(elements, "Sub"); + assert_eq!(sub["@type"], "Subclassification"); + assert!(ref_of_prop(sub, "owningRelationship").is_some()); + let standalone: Vec<&Value> = elements + .iter() + .filter(|e| { + e["owningRelatedElement"].is_null() + && ref_of_prop(e, "owningRelationship").is_some() + && matches!( + e["@type"].as_str(), + Some( + "Subclassification" + | "FeatureTyping" + | "Subsetting" + | "FeatureInverting" + | "TypeFeaturing" + | "Conjugation" + | "Disjoining" + ) + ) + }) + .collect(); + let kinds: Vec<&Value> = standalone.iter().map(|e| &e["@type"]).collect(); + assert_eq!(standalone.len(), 7, "{kinds:?}"); + for rel in &standalone { + for prop in [ + "owningType", + "owningClassifier", + "owningFeature", + "owningFeatureOfType", + ] { + assert!( + rel.get(prop).is_none_or(Value::is_null), + "{} {prop}", + rel["@type"] + ); + } + } + // A standalone conjugation still has its spelled ends. + let conj = standalone + .iter() + .find(|e| e["@type"] == "Conjugation") + .unwrap(); + assert_eq!(refs_of_prop(conj, "source"), [d.as_str()]); + assert_eq!(refs_of_prop(conj, "target"), [a.as_str()]); +} + +/// `Type::multiplicity` is the owned member that is a Multiplicity of any +/// kind, including KerML `multiplicity` members; a multiplicity does not +/// own one of its own. +#[test] +fn type_multiplicity_derives_for_kerml_members() { + let parse = parse_kerml_source( + "package P { + classifier K { + multiplicity m [2]; + feature f [3]; + } + classifier N { + multiplicity n subsets K::m; + } + }", + ); + assert!(parse.diagnostics.is_empty(), "{:?}", parse.diagnostics); + let full = to_full_json(&parse.unit); + let elements = full.as_array().unwrap(); + let m = find_named(elements, "m"); + assert_eq!(m["@type"], "MultiplicityRange"); + assert_eq!( + ref_of_prop(find_named(elements, "K"), "multiplicity"), + Some(elem_id(m)) + ); + assert!( + m["multiplicity"].is_null(), + "a multiplicity owns no multiplicity" + ); + let range = ref_of_prop(find_named(elements, "f"), "multiplicity").expect("f [3]"); + assert_eq!(find_id(elements, &range)["@type"], "MultiplicityRange"); + let n = find_named(elements, "n"); + assert_eq!(n["@type"], "Multiplicity"); + assert_eq!( + ref_of_prop(find_named(elements, "N"), "multiplicity"), + Some(elem_id(n)) + ); +} + +/// Annotation ends in the shape this toolkit emits: the Annotation is +/// owned by its annotating element, so that element is the source and the +/// owning annotating element; the annotated element owns nothing. +#[test] +fn annotation_ends_derive() { + let parse = parse_source( + "package P { + part def V; + part def W; + comment C about V /* about V */ + comment C2 about V, W /* about both */ + doc /* on P */ + metadata def M; + #M part p; + @M about V; + }", + ); + assert!(parse.diagnostics.is_empty(), "{:?}", parse.diagnostics); + let full = to_full_json(&parse.unit); + let elements = full.as_array().unwrap(); + let p = elem_id(find_named(elements, "P")); + let v = elem_id(find_named(elements, "V")); + let c = find_named(elements, "C"); + let c_id = elem_id(c); + + let [ann] = owned_rels_of_kind(elements, "Annotation", &c_id)[..] else { + panic!("C owns exactly one Annotation"); + }; + let ann_id = elem_id(ann); + assert_eq!( + ref_of_prop(ann, "annotatingElement").as_deref(), + Some(c_id.as_str()) + ); + assert_eq!( + ref_of_prop(ann, "annotatedElement").as_deref(), + Some(v.as_str()) + ); + assert_eq!( + ref_of_prop(ann, "owningAnnotatingElement").as_deref(), + Some(c_id.as_str()) + ); + assert!(ann["owningAnnotatedElement"].is_null()); + assert!(ann["ownedAnnotatingElement"].is_null()); + assert_eq!(refs_of_prop(ann, "source"), [c_id.as_str()]); + assert_eq!(refs_of_prop(ann, "target"), [v.as_str()]); + assert_eq!( + refs_of_prop(ann, "relatedElement"), + [c_id.clone(), v.clone()] + ); + + assert_eq!(refs_of_prop(c, "annotation"), [ann_id.as_str()]); + assert_eq!( + refs_of_prop(c, "ownedAnnotatingRelationship"), + [ann_id.as_str()] + ); + assert!(c["owningAnnotatingRelationship"].is_null()); + assert_eq!(refs_of_prop(c, "annotatedElement"), [v.as_str()]); + assert!(refs_of_prop(c, "ownedAnnotation").is_empty()); + assert!(refs_of_prop(find_id(elements, &v), "ownedAnnotation").is_empty()); + + // An implicit annotation: no Annotation at all, the owner is annotated. + let doc = elements + .iter() + .find(|e| e["@type"] == "Documentation") + .expect("one doc"); + assert!(refs_of_prop(doc, "annotation").is_empty()); + assert!(refs_of_prop(doc, "ownedAnnotatingRelationship").is_empty()); + assert_eq!(refs_of_prop(doc, "annotatedElement"), [p.as_str()]); + + // Prefix metadata rides an owning membership of the annotated usage. + let part = elem_id(find_named(elements, "p")); + let metadata_owned_by = |owner: &str| { + elements + .iter() + .find(|e| { + e["@type"] == "MetadataUsage" && ref_of_prop(e, "owner").as_deref() == Some(owner) + }) + .unwrap_or_else(|| panic!("no metadata usage owned by {owner}")) + }; + let meta = metadata_owned_by(&part); + assert!(meta["owningAnnotatingRelationship"].is_null()); + assert!(refs_of_prop(meta, "annotation").is_empty()); + assert_eq!(refs_of_prop(meta, "annotatedElement"), [part.as_str()]); + assert!(refs_of_prop(find_id(elements, &part), "ownedAnnotation").is_empty()); + + // A metadata usage with an `about` clause owns its Annotation like a + // comment does. + let about_meta = metadata_owned_by(&p); + let about_id = elem_id(about_meta); + let [meta_ann] = owned_rels_of_kind(elements, "Annotation", &about_id)[..] else { + panic!("the about metadata usage owns exactly one Annotation"); + }; + assert_eq!( + ref_of_prop(meta_ann, "annotatingElement").as_deref(), + Some(about_id.as_str()) + ); + assert_eq!(refs_of_prop(meta_ann, "source"), [about_id.as_str()]); + assert_eq!(refs_of_prop(about_meta, "annotation"), [elem_id(meta_ann)]); + assert_eq!(refs_of_prop(about_meta, "annotatedElement"), [v.as_str()]); + assert!(about_meta["owningAnnotatingRelationship"].is_null()); + + // Several `about` targets: one Annotation each, in declaration order. + let c2 = find_named(elements, "C2"); + let w = elem_id(find_named(elements, "W")); + assert_eq!( + owned_rels_of_kind(elements, "Annotation", &elem_id(c2)).len(), + 2 + ); + assert_eq!( + refs_of_prop(c2, "annotatedElement"), + [v.as_str(), w.as_str()] + ); + assert_eq!(refs_of_prop(c2, "annotation").len(), 2); + assert_eq!( + refs_of_prop(c2, "annotation"), + refs_of_prop(c2, "ownedAnnotatingRelationship") + ); +} + +/// A foreign prefix annotation remains an Annotation with its original +/// id and ownership. Full-form enrichment must not normalize it into a +/// different membership or project references to a reconstructed graph. +#[test] +fn prefix_annotation_shape_derives_from_compact() { + const P: &str = "00000000-0000-4000-8000-000000000001"; + const M1: &str = "00000000-0000-4000-8000-000000000002"; + const X: &str = "00000000-0000-4000-8000-000000000003"; + const A1: &str = "00000000-0000-4000-8000-000000000004"; + const C1: &str = "00000000-0000-4000-8000-000000000005"; + const A2: &str = "00000000-0000-4000-8000-000000000006"; + // The Comment is owned by A1 (annotating X) and itself owns A2, an + // `about` Annotation of the package. + let payload = |spell_annotated: bool| { + let mut annotation = json!({"@type": "Annotation", "@id": A1, "isImplied": false, + "owningRelatedElement": {"@id": X}, "ownedRelatedElement": [{"@id": C1}]}); + if spell_annotated { + annotation["annotatedElement"] = json!({"@id": X}); + } + json!([ + {"@type": "Package", "@id": P, "declaredName": "P", + "ownedRelationship": [{"@id": M1}]}, + {"@type": "OwningMembership", "@id": M1, "isImplied": false, "visibility": "public", + "owningRelatedElement": {"@id": P}, "ownedRelatedElement": [{"@id": X}]}, + {"@type": "PartDefinition", "@id": X, "declaredName": "X", + "owningRelationship": {"@id": M1}, "ownedRelationship": [{"@id": A1}]}, + {"@type": "Comment", "@id": C1, "body": "hi", "owningRelationship": {"@id": A1}, + "ownedRelationship": [{"@id": A2}]}, + {"@type": "Annotation", "@id": A2, "isImplied": false, + "owningRelatedElement": {"@id": C1}, "annotatedElement": {"@id": P}}, + annotation, + ]) + }; + for spell in [true, false] { + let full = from_compact_value(payload(spell), &HashMap::new(), false); + let elements = full.as_array().unwrap(); + // Untouched elements keep their ids. + assert_eq!(find_id(elements, P)["@type"], "Package"); + assert_eq!(find_id(elements, X)["@type"], "PartDefinition"); + // The comment is still owned through the Annotation, annotating X and P. + let comment = elements + .iter() + .find(|e| e["@type"] == "Comment") + .expect("the comment survives"); + assert_eq!(comment["body"], "hi"); + assert_eq!(ref_of_prop(comment, "owner").as_deref(), Some(X)); + let annotated = refs_of_prop(comment, "annotatedElement"); + assert!( + annotated.contains(&X.to_string()) && annotated.contains(&P.to_string()), + "spell={spell}: {annotated:?}" + ); + assert_eq!(elem_id(comment), C1, "the comment keeps its id"); + let annotation = find_id(elements, A1); + assert_eq!(annotation["@type"], "Annotation"); + assert_eq!( + ref_of_prop(annotation, "annotatingElement").as_deref(), + Some(C1) + ); + assert_eq!( + ref_of_prop(comment, "owningAnnotatingRelationship").as_deref(), + Some(A1) + ); + assert_eq!(refs_of_prop(find_id(elements, X), "ownedAnnotation"), [A1]); + assert!(refs_of_prop(find_id(elements, X), "ownedMembership").is_empty()); + } +} + +/// The payload path emits exactly what the text path emits: a toolkit +/// payload converted with `from_compact_value` equals the full form of +/// the model it came from, id for id (the loader keeps the document's +/// ids), and a payload carrying foreign ids equals it under those ids. +#[test] +fn payload_route_matches_the_model_route() { + let src = "package P { + part def A { attribute x; attribute y = 3; } + part def B :> A { part b : A; } + import Q::*; + alias C for B; + comment about A /* about A */ + } + package Q { part def D; }"; + let mut model = Model::new(); + model.add_source("m.sysml", src); + assert!(!model.has_errors()); + let compact = sysmlv2_parser::json::model_to_compact_json(&model); + let expected = model_to_full_json(&model); + let by_id = |v: &Value| -> HashMap { + v.as_array() + .unwrap() + .iter() + .map(|e| { + ( + e["@id"].as_str().unwrap().to_string(), + serde_json::to_string(e).unwrap(), + ) + }) + .collect() + }; + let want = by_id(&expected); + + // Same ids, same values. + let got = by_id(&from_compact_value(compact.clone(), &HashMap::new(), true)); + assert_eq!(got.len(), want.len(), "element count"); + let mut differing = 0; + for (id, el) in &want { + if got.get(id) != Some(el) { + differing += 1; + if differing == 1 { + let w: Value = serde_json::from_str(el).unwrap(); + let g: Value = got + .get(id) + .map(|s| serde_json::from_str(s).unwrap()) + .unwrap_or(Value::Null); + for (k, v) in w.as_object().unwrap() { + if g.get(k) != Some(v) { + eprintln!( + "differs at {id} ({}) key {k}: want {v} got {:?}", + w["@type"], + g.get(k) + ); + } + } + } + } + } + assert_eq!(differing, 0, "toolkit payload through the payload route"); + + // Foreign ids: every id replaced consistently; the output equals the + // model route's under the foreign ids. + let mut map: HashMap = HashMap::new(); + for e in compact.as_array().unwrap() { + let id = e["@id"].as_str().unwrap(); + map.insert( + id.to_string(), + uuid::Uuid::new_v5(&uuid::Uuid::NAMESPACE_OID, format!("f:{id}").as_bytes()) + .to_string(), + ); + } + fn rewrite(v: &Value, map: &HashMap) -> Value { + match v { + Value::Object(o) => Value::Object( + o.iter() + .map(|(k, x)| { + let x = if (k == "@id" + || k == "elementId" + || k == "memberElementId" + || k == "ownedMemberElementId") + && x.is_string() + { + map.get(x.as_str().unwrap()) + .map(|s| Value::String(s.clone())) + .unwrap_or_else(|| x.clone()) + } else { + rewrite(x, map) + }; + (k.clone(), x) + }) + .collect(), + ), + Value::Array(a) => Value::Array(a.iter().map(|x| rewrite(x, map)).collect()), + other => other.clone(), + } + } + let foreign = rewrite(&compact, &map); + let got = from_compact_value(foreign, &HashMap::new(), true); + // Compare after mapping the expected form's ids the same way; the + // implied relationships and recovery elements the emitter adds derive + // fresh ids on both routes, so compare the user elements only. + let expected_foreign = by_id(&rewrite(&expected, &map)); + let got = by_id(&got); + let mut differing = 0; + for old in map.keys() { + let id = &map[old]; + if got.get(id) != expected_foreign.get(id) { + differing += 1; + if differing == 1 { + eprintln!( + "foreign differs at {id}:\n want {:?}\n got {:?}", + expected_foreign.get(id), + got.get(id) + ); + } + } + } + assert_eq!(differing, 0, "foreign-id payload through the payload route"); +} + +/// Under the closure policy the full form writes the closures and the +/// inheritance-aware properties over them; at the passthrough level the +/// closure names carry the catalog's empty value. A walk past the depth +/// budget refuses the emission. +#[test] +fn closure_policy_writes_the_closures() { + use sysmlv2_parser::full::{EmissionError, EmissionPolicy, resolved_to_full_json}; + use sysmlv2_parser::json::{ClosurePolicy, ResolvedModel}; + use sysmlv2_parser::model::Model; + let mut model = Model::new(); + model.add_source( + "m.sysml", + "package P { part def V { attribute mass; } part def W :> V { attribute extra; } package Q { part q; } package R { import Q::*; } }", + ); + let mut r = ResolvedModel::build(&model); + let find = |full: &serde_json::Value, name: &str| -> serde_json::Value { + full.as_array() + .unwrap() + .iter() + .find(|e| e["declaredName"] == name) + .cloned() + .expect(name) + }; + let passthrough = resolved_to_full_json(&mut r, &model, EmissionPolicy::default()).unwrap(); + let w = find(&passthrough, "W"); + assert_eq!(w["inheritedFeature"], serde_json::json!([])); + assert_eq!(w["feature"].as_array().unwrap().len(), 1); + let closed = resolved_to_full_json( + &mut r, + &model, + EmissionPolicy { + closures: ClosurePolicy::Closure { + include_implied: false, + }, + ..EmissionPolicy::default() + }, + ) + .unwrap(); + let w = find(&closed, "W"); + let mass_id = find(&closed, "mass")["@id"].clone(); + assert_eq!( + w["inheritedFeature"], + serde_json::json!([{ "@id": mass_id }]) + ); + assert_eq!(w["feature"].as_array().unwrap().len(), 2); + assert_eq!(w["inheritedMembership"].as_array().unwrap().len(), 1); + let rpkg = find(&closed, "R"); + assert_eq!(rpkg["importedMembership"].as_array().unwrap().len(), 1); + assert_eq!(rpkg["membership"].as_array().unwrap().len(), 1); + assert_eq!(find(&passthrough, "R")["membership"], serde_json::json!([])); + // The policy is restored after the emission. + assert_eq!(r.closure_policy(), ClosurePolicy::Passthrough); + // A heritage deeper than the budget. + let mut src = String::from("package P { part def D0;"); + for i in 1..=26 { + src.push_str(&format!(" part def D{i} :> D{};", i - 1)); + } + src.push('}'); + let mut deep = Model::new(); + deep.add_source("d.sysml", &src); + let mut r = ResolvedModel::build(&deep); + let err = resolved_to_full_json( + &mut r, + &deep, + EmissionPolicy { + closures: ClosurePolicy::Closure { + include_implied: false, + }, + ..EmissionPolicy::default() + }, + ) + .unwrap_err(); + assert!( + matches!(err, EmissionError::TruncatedClosures { ref elements } if !elements.is_empty()) + ); + // Restored after the refusal too. + assert_eq!(r.closure_policy(), ClosurePolicy::Passthrough); + assert!(resolved_to_full_json(&mut r, &deep, EmissionPolicy::default()).is_ok()); +} diff --git a/crates/sysmlv2-parser/tests/fuzz.rs b/crates/sysmlv2-parser/tests/fuzz.rs index 9c6719e..763c71c 100644 --- a/crates/sysmlv2-parser/tests/fuzz.rs +++ b/crates/sysmlv2-parser/tests/fuzz.rs @@ -171,6 +171,169 @@ fn pathological_inputs_never_panic() { } } +/// Input nested deeper than the parser will descend is reported, not +/// crashed into. Bodies and expressions both recurse, and exhausting the +/// stack ends the process instead of producing a diagnostic, so the depth +/// is bounded. +/// +/// The probe runs on a thread with room for the bound itself: reaching it +/// means holding one frame per level, and an unoptimized build's frames +/// are large. The point is that ten thousand levels of input stop at the +/// bound with a diagnostic instead of descending until the stack is gone. +#[test] +fn deeply_nested_input_reports_a_diagnostic() { + std::thread::Builder::new() + .stack_size(64 * 1024 * 1024) + .spawn(deep_nesting_probe) + .unwrap() + .join() + .unwrap(); +} + +fn deep_nesting_probe() { + const N: usize = 10_000; + for src in [ + format!("package P {{ {}{} }}", "part x { ".repeat(N), "}".repeat(N)), + format!( + "package P {{ attribute a = {}1{}; }}", + "(".repeat(N), + ")".repeat(N) + ), + format!( + "package P {{ attribute a = {}1{}; }}", + "{ ".repeat(N), + " }".repeat(N) + ), + // Right-associative operators recurse into themselves rather than + // returning through the expression entry point; the bound is + // charged there too, or a chain of them descends until the stack + // is gone. + format!("package P {{ attribute a = {}1; }}", "2**".repeat(N)), + format!("package P {{ attribute a = {}1; }}", "2^".repeat(N)), + ] { + let parse = parse_source(&src); + assert!( + parse + .diagnostics + .iter() + .any(|d| d.message.contains("nesting is too deep")), + "expected a nesting diagnostic, got {:?}", + parse.diagnostics.first().map(|d| d.message.clone()) + ); + // One report per truncated subtree, as the body path gives — not + // one per token of the abandoned text. + assert!( + parse.diagnostics.len() <= 2, + "expected the refusal to be reported once, got {:#?}", + parse.diagnostics + ); + // The rest of the pipeline takes the bounded tree without panicking. + exercise(&src); + } + + // A left-associative chain is built iteratively, so no descent is + // charged for it — but the tree leans one node deep per operator and + // every walk over it recurses, dropping it included. The operator + // budget bounds that, for every shape that leans the same way: a + // binary chain, a feature chain, an index, a bracket, an applied + // operator and a cast all add one node per step. + for src in [ + format!("package P {{ attribute a = {}1; }}", "1+".repeat(N)), + format!("package P {{ attribute a = {}1; }}", "1 and ".repeat(N)), + format!("package P {{ attribute a = {}x; }}", "y.".repeat(N)), + format!("package P {{ attribute a = x{}; }}", "[1]".repeat(N)), + format!("package P {{ attribute a = x{}; }}", "#(1)".repeat(N)), + format!("package P {{ attribute a = x{}; }}", "->f(1)".repeat(N)), + format!("package P {{ attribute a = x{}; }}", " as T".repeat(N)), + ] { + let parse = parse_source(&src); + assert!( + parse + .diagnostics + .iter() + .any(|d| d.message.contains("operators")), + "expected an operator-count diagnostic, got {:?}", + parse.diagnostics.first().map(|d| d.message.clone()) + ); + assert!( + parse.diagnostics.len() <= 2, + "expected the refusal to be reported once, got {:#?}", + parse.diagnostics + ); + exercise(&src); + } + + // A branch gives its chain back to its siblings, but never to what is + // built above it: an expression leaning a full chain at every level + // of nesting is refused however those levels are spelled. + for nested in ["f(#)", "x[#]", "(#)"] { + let mut inner = "1".to_string(); + for _ in 0..120 { + inner = nested.replace('#', &inner) + &"+1".repeat(1000); + } + let src = format!("package P {{ attribute a = {inner}; }}"); + let parse = parse_source(&src); + assert!( + parse + .diagnostics + .iter() + .any(|d| d.message.contains("operators")), + "expected an operator-count diagnostic for `{nested}`, got {:?}", + parse.diagnostics.first().map(|d| d.message.clone()) + ); + exercise(&src); + } + + // A chain within the budget still parses, and everything downstream + // still walks it. + let src = format!( + "package P {{ attribute a = {}1; }}", + "1+".repeat(sysmlv2_parser::parser::MAX_EXPR_OPERATORS as usize - 1) + ); + assert!(parse_source(&src).diagnostics.is_empty()); + exercise(&src); + + // Operands beside one another are not operators stacked on one + // another: a long sequence, a long argument list, a sum of products + // half the budget long, and a body full of statements all stay well + // inside it — and a body's members each spell their own chain rather + // than sharing one budget with their siblings. + let statements: String = (0..600) + .map(|i| format!("attribute x{i} = 1+1+1; ")) + .collect(); + for src in [ + format!( + "package P {{ attribute a = ({}); }}", + ["1+1"; 1100].join(", ") + ), + format!( + "package P {{ attribute a = f({}); }}", + ["1+1"; 1100].join(", ") + ), + format!( + "package P {{ attribute a = {}; }}", + ["2*3"; 550].join(" + ") + ), + format!("package P {{ part p {{ attribute a = xs->select {{ {statements} }}; }} }}"), + format!("package P {{ part p {{ {statements} }} }}"), + ] { + let parse = parse_source(&src); + assert!( + parse.diagnostics.is_empty(), + "expected no diagnostics, got {:#?}", + parse.diagnostics + ); + } + // The bound is well clear of what written models reach: the deepest + // file in the published examples and libraries nests ten braces. + let src = format!( + "package P {{ {}{} }}", + "part x { ".repeat(12), + "}".repeat(12) + ); + assert!(parse_source(&src).diagnostics.is_empty()); +} + thread_local! { static LAST: std::cell::RefCell> = const { std::cell::RefCell::new(None) }; diff --git a/crates/sysmlv2-parser/tests/goldens.rs b/crates/sysmlv2-parser/tests/goldens.rs index c5a416d..bcead49 100644 --- a/crates/sysmlv2-parser/tests/goldens.rs +++ b/crates/sysmlv2-parser/tests/goldens.rs @@ -20,6 +20,7 @@ use serde_json::Value; use std::collections::BTreeMap; +use std::fmt::Write as _; use std::fs; use std::path::PathBuf; use sysmlv2_parser::json::model_to_compact_json; @@ -110,16 +111,16 @@ fn golden_snapshots_per_metaclass() { for (ty, text) in &snap { let path = expected_dir.join(format!("{ty}.json")); match fs::read_to_string(&path) { - Err(_) => report.push_str(&format!(" new metaclass without a golden: {ty}\n")), + Err(_) => writeln!(report, " new metaclass without a golden: {ty}").unwrap(), Ok(want) if want != *text => { - report.push_str(&format!(" golden differs: {ty}\n")); + writeln!(report, " golden differs: {ty}").unwrap(); } Ok(_) => {} } } for ty in &on_disk { if !snap.contains_key(ty) { - report.push_str(&format!(" golden no longer produced: {ty}\n")); + writeln!(report, " golden no longer produced: {ty}").unwrap(); } } assert!( diff --git a/crates/sysmlv2-parser/tests/goldens/expected/FeatureChaining.json b/crates/sysmlv2-parser/tests/goldens/expected/FeatureChaining.json index 96836af..1ca1355 100644 --- a/crates/sysmlv2-parser/tests/goldens/expected/FeatureChaining.json +++ b/crates/sysmlv2-parser/tests/goldens/expected/FeatureChaining.json @@ -108,7 +108,7 @@ "@id": "94424ec9-e9bc-5fce-ad96-903db14d9b0e", "@type": "FeatureChaining", "chainingFeature": { - "@ref": "mode" + "@id": "8baee662-5f02-512b-b671-c812c4a7bf95" }, "elementId": "94424ec9-e9bc-5fce-ad96-903db14d9b0e", "isImplied": false, diff --git a/crates/sysmlv2-parser/tests/goldens/expected/PartDefinition.json b/crates/sysmlv2-parser/tests/goldens/expected/PartDefinition.json index 5fbb57e..4ff2256 100644 --- a/crates/sysmlv2-parser/tests/goldens/expected/PartDefinition.json +++ b/crates/sysmlv2-parser/tests/goldens/expected/PartDefinition.json @@ -267,6 +267,7 @@ "elementId": "8fba673f-bee3-5999-b909-a97fdfd8dd96", "isAbstract": false, "isImpliedIncluded": false, + "isIndividual": true, "isSufficient": false, "isVariation": false, "ownedRelationship": [ diff --git a/crates/sysmlv2-parser/tests/grammar_edge.rs b/crates/sysmlv2-parser/tests/grammar_edge.rs index d3b26a5..67e4fcd 100644 --- a/crates/sysmlv2-parser/tests/grammar_edge.rs +++ b/crates/sysmlv2-parser/tests/grammar_edge.rs @@ -284,6 +284,20 @@ fn accept_node_trigger_forms() { sysml_ok("package P { action def A { accept when c; } }"); sysml_ok("package P { action def A { accept at t0; } }"); sysml_ok("package P { action def A { accept x : T via p; } }"); + // A trigger, a `via` clause and a payload's value each take a full + // expression, and a conditional is one — parenthesized or not. + sysml_ok("package P { action def A { accept when (if a ? b else c); } }"); + sysml_ok("package P { action def A { accept when if a ? b else c; } }"); + sysml_ok("package P { action def A { accept when if a ? b else if c ? d else e; } }"); + sysml_ok("package P { action def A { accept x : T via if a ? p else q; } }"); + sysml_ok("package P { action def A { accept x : T when if g ? b else c; } }"); + // The word-spelled operators take an operand, and an operand may be + // spelled as a body. + sysml_ok("package P { action def A { accept when a and { b }; } }"); + sysml_ok("package P { action def A { accept when a or { b }; } }"); + sysml_ok("package P { action def A { accept when a xor { b }; } }"); + sysml_ok("package P { action def A { accept when a implies { b }; } }"); + sysml_ok("package P { action def A { accept when not { b }; } }"); } #[test] diff --git a/crates/sysmlv2-parser/tests/ids_derive.rs b/crates/sysmlv2-parser/tests/ids_derive.rs index 77b37d3..02e70c4 100644 --- a/crates/sysmlv2-parser/tests/ids_derive.rs +++ b/crates/sysmlv2-parser/tests/ids_derive.rs @@ -114,3 +114,57 @@ fn foreign_ids_mismatch_without_panic() { .count(); assert!(mismatches >= 1, "foreign id surfaces as a mismatch"); } + +/// Ids and segment paths come out of the same walk, so deriving ids +/// without materializing paths cannot change them: an element has a +/// derived id exactly when it has a non-empty path, and re-deriving +/// along that path from its root reproduces the id the derivation gave. +#[test] +fn segment_paths_describe_the_id_derivation() { + use sysmlv2_parser::ids::segment_paths; + let mut model = Model::new(); + model.add_source( + "t.sysml", + "package P { + part def Car { attribute mass = 1; } + part c : Car { attribute :>> mass = 2; } + alias wheels for c; + }", + ); + let compact = model_to_compact_json(&model); + let elements = compact.as_array().unwrap(); + let none = |_: &str| None; + let derived = derive_ids(&compact, &none).expect("payload well-formed"); + let paths = segment_paths(&compact, &none).expect("payload well-formed"); + assert_eq!(derived.len(), elements.len()); + assert_eq!(paths.len(), elements.len()); + let mut chained = 0usize; + for (i, (id, path)) in derived.iter().zip(&paths).enumerate() { + let Some((root, path)) = path else { + assert!(id.is_none(), "element {i} has an id but no path"); + continue; + }; + if path.is_empty() { + assert_eq!(*root, i, "only a root carries the empty path"); + assert!(id.is_none(), "a root's id is assigned, not derived"); + continue; + } + let mut namespace = + Uuid::parse_str(elements[*root]["@id"].as_str().unwrap()).expect("a root id"); + for segment in path.split('/') { + namespace = Uuid::new_v5(&namespace, segment.as_bytes()); + } + assert_eq!(Some(namespace), *id, "element {i} at {path}"); + chained += 1; + } + assert!(chained > 10, "the model has a body to walk: {chained}"); + // The named chain skips the membership level: a named member takes + // the owner-scope segment, and its membership hangs off the member. + assert!( + paths + .iter() + .flatten() + .any(|(_, p)| p.ends_with("::P/::Car/m")), + "{paths:?}" + ); +} diff --git a/crates/sysmlv2-parser/tests/inherited_battery.rs b/crates/sysmlv2-parser/tests/inherited_battery.rs new file mode 100644 index 0000000..9ee9baa --- /dev/null +++ b/crates/sysmlv2-parser/tests/inherited_battery.rs @@ -0,0 +1,341 @@ +//! Adversarial battery for inherited-membership enumeration: corner +//! cases assembled from the KerML 8.3 OCL (`inheritableMemberships` / +//! `nonPrivateMemberships` / `removeRedefinedFeatures`), the pilot's +//! serializer scope cases, and the resolver's own composition rules. +//! Enumeration must mirror the resolver; where the resolver itself +//! deviates from the spec, the deviation is recorded, never patched +//! from here. + +#![cfg(feature = "json")] + +use sysmlv2_parser::json::ResolvedModel; +use sysmlv2_parser::model::Model; + +fn build(src: &str) -> ResolvedModel { + let mut model = Model::new(); + model.add_source("b.sysml", src); + assert!(!model.has_errors(), "battery model must parse clean"); + ResolvedModel::build(&model) +} + +fn inherited_names(r: &mut ResolvedModel, qn: &str) -> Vec { + let e = r.resolve_qualified(qn).unwrap(); + let mut names: Vec = r + .inherited_memberships(e, false) + .iter() + .filter_map(|&m| r.membership_member_name(m)) + .collect(); + names.sort(); + names +} + +#[test] +fn protected_members_inherit_two_levels() { + let mut r = build( + "package P { + part def Base { protected attribute guarded; attribute open; } + part def Mid :> Base; + part def Sub :> Mid; + }", + ); + assert_eq!(inherited_names(&mut r, "P::Sub"), ["guarded", "open"]); +} + +#[test] +fn short_name_only_member_inherits_once() { + let mut r = build( + "package P { + part def Base { attribute named; } + part def Sub :> Base; + }", + ); + // Registered under both spellings; the membership appears once. + let sub = r.resolve_qualified("P::Sub").unwrap(); + assert_eq!(r.inherited_memberships(sub, false).len(), 1); +} + +#[test] +fn supertype_reached_through_import_contributes() { + // Pilot serializer case: the supertype itself arrives via an import. + let mut r = build( + "package P { + package Lib { part def Basis { attribute deep; } } + package Use { + private import Lib::*; + part def Sub :> Basis; + } + }", + ); + assert_eq!(inherited_names(&mut r, "P::Use::Sub"), ["deep"]); +} + +#[test] +fn recursive_import_descends_members_only_through_owned() { + let mut r = build( + "package P { + package Other { part def Alien { part deep; } } + package Lib { + public import Other::*; + part def Outer { part inner; } + } + part def Base { public import Lib::*::**; } + part def Sub :> Base; + }", + ); + let names = inherited_names(&mut r, "P::Sub"); + assert!( + names.contains(&"Outer".to_string()) && names.contains(&"inner".to_string()), + "::** brings nested members: {names:?}" + ); + assert!( + names.contains(&"Alien".to_string()), + "the imported member is visible at Lib itself: {names:?}" + ); + assert!( + !names.contains(&"deep".to_string()), + "recursion descends owned members only, not imported ones: {names:?}" + ); +} + +#[test] +fn diamond_same_feature_is_one_membership() { + let mut r = build( + "package P { + part def Root { attribute x; } + part def L :> Root; + part def R :> Root; + part def D :> L, R; + }", + ); + assert_eq!( + inherited_names(&mut r, "P::D"), + ["x"], + "one membership, not two" + ); +} + +#[test] +fn specialization_cycle_terminates_without_self_members() { + let mut r = build( + "package P { + part def A :> B { attribute a; } + part def B :> A { attribute b; } + }", + ); + // The heritage is cyclic (the checker reports it; the walk must still + // terminate): each type inherits the other's member once, never its + // own. + assert_eq!(inherited_names(&mut r, "P::A"), ["b"]); + assert_eq!(inherited_names(&mut r, "P::B"), ["a"]); +} + +#[test] +fn kerml_same_name_features_both_retained() { + // No SysML implicit usage redefinition in the KerML dialect: an + // owned same-named feature does not remove the inherited one. + let mut model = Model::new(); + model.add_source( + "k.kerml", + "package P { + class Base { feature f; } + class Sub specializes Base { feature f; } + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let inherited: Vec<_> = r + .inherited_features(sub, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert_eq!( + inherited, + ["f"], + "KerML keeps the inherited f (ambiguous, not shadowed)" + ); +} + +#[test] +fn direct_import_filter_applies_at_first_hop() { + let mut r = build( + "package P { + metadata def Safety; + package Lib { + part safe { @Safety; } + part plain; + } + part def Base { public import Lib::*[@Safety]; } + part def Sub :> Base; + }", + ); + let names = inherited_names(&mut r, "P::Sub"); + assert!(names.contains(&"safe".to_string()), "{names:?}"); + assert!(!names.contains(&"plain".to_string()), "{names:?}"); +} + +#[test] +fn alias_with_short_name_only_inherits() { + let mut r = build( + "package P { + part def Base { attribute mass; alias for mass; } + part def Sub :> Base; + }", + ); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let memberships = r.inherited_memberships(sub, false); + assert!( + memberships.iter().any(|&m| r.membership_is_alias(m)), + "short-name-only alias must inherit" + ); +} + +#[test] +fn unnamed_redefining_feature_removes_target_only() { + let mut r = build( + "package P { + part def Base { attribute a; attribute b; } + part def Sub :> Base { attribute :>> a; } + }", + ); + assert_eq!( + inherited_names(&mut r, "P::Sub"), + ["b"], + "the unnamed :>> a redefines a; b unaffected" + ); +} + +#[test] +fn protected_import_of_a_base_inherits_a_private_one_does_not() { + let mut r = build( + "package P { + package Lib { part def Shared { attribute deep; } } + part def Guarded { protected import Lib::*; } + part def Hidden { private import Lib::*; } + part def SubG :> Guarded; + part def SubH :> Hidden; + }", + ); + // KerML nonPrivateMemberships: the public and the protected imports of + // a base re-export through heritage; a private one does not. + assert_eq!(inherited_names(&mut r, "P::SubG"), ["Shared"]); + assert!(inherited_names(&mut r, "P::SubH").is_empty()); +} + +#[test] +fn filtered_import_diamond_is_path_independent() { + // A is reached filtered and unfiltered; the unfiltered member must + // arrive whichever path the walk takes first. Two shapes: the filter + // as an import bracket, and as a `filter` member of the re-exporting + // package. + let shapes = [ + ( + "public import A::*[@Safety];", + "public import B::*;", + "public import A::*;", + ), + ( + "public import A::*;", + "public import B::*;", + "filter @Safety; public import A::*;", + ), + ]; + for (direct, via_b, b_body) in shapes { + for (first, second) in [(direct, via_b), (via_b, direct)] { + let mut r = build(&format!( + "package P {{ + metadata def Safety; + package A {{ part def Plain; #Safety part def Safe; }} + package B {{ {b_body} }} + part def Base {{ {first} {second} }} + part def Sub :> Base; + }}" + )); + assert_eq!( + inherited_names(&mut r, "P::Sub"), + ["Plain", "Safe"], + "B: `{b_body}`, order: {first} {second}" + ); + } + } +} + +#[test] +fn short_name_implicit_redefinition_shadows_like_lookup() { + let mut r = build( + "package P { + part def A { part long; } + part def B :> A { part sn; } + }", + ); + // `sn` looked up in B resolves the owned usage over the inherited one + // whose short name it matches, so enumeration drops the inherited one. + assert!(inherited_names(&mut r, "P::B").is_empty()); +} + +#[test] +fn owned_redefinition_seed_is_one_hop() { + // KerML removeRedefinedFeatures, second condition: the owned side + // contributes `ownedFeature.redefinition.redefinedFeature` — one hop. + // `z` redefines `Other::o`, which redefines `x`; `x` arrives from + // `Base` unredefined by any inherited candidate, so it stays. + let mut r = build( + "package P { + part def Base { attribute x; } + part def Other :> Base { attribute o :>> x; } + part def Sub :> Base { attribute z :>> Other::o; } + }", + ); + assert_eq!(inherited_names(&mut r, "P::Sub"), ["x"]); +} + +#[test] +fn deep_heritage_reports_truncation_and_terminates() { + // The walk shares lookup's recursion budget; past it the enumeration + // says so instead of silently presenting a cut result. + let chain = |n: usize| -> String { + let mut src = String::from("package P { part def T0 { attribute a0; }"); + for i in 1..=n { + src.push_str(&format!( + " part def T{i} :> T{} {{ attribute a{i}; }}", + i - 1 + )); + } + src.push('}'); + src + }; + let mut r = build(&chain(10)); + let leaf = r.resolve_qualified("P::T10").unwrap(); + assert!(!r.inheritance_walk_truncated(leaf, false)); + assert_eq!(r.inherited_features(leaf, false).len(), 10); + + let mut r = build(&chain(30)); + let leaf = r.resolve_qualified("P::T30").unwrap(); + assert!(r.inheritance_walk_truncated(leaf, false)); + let n = r.inherited_features(leaf, false).len(); + assert!((24..30).contains(&n), "cut at the budget, got {n}"); + // A shallow type in the same model is complete. + let mid = r.resolve_qualified("P::T5").unwrap(); + assert!(!r.inheritance_walk_truncated(mid, false)); +} + +#[test] +fn recursive_import_descends_whatever_the_import_order() { + // A scope first reached through a plain `Q::*` import must still be + // descended when a later `::**` import reaches it recursively: the + // visit key carries the recursion flag, as lookup always descends. + for imports in [ + "public import Outer::Q::*; public import Outer::**;", + "public import Outer::**; public import Outer::Q::*;", + ] { + let mut r = build(&format!( + "package P {{ + package Outer {{ package Q {{ package Deep {{ part def X; }} }} }} + part def Base {{ {imports} }} + part def Sub :> Base; + }}" + )); + let names = inherited_names(&mut r, "P::Sub"); + assert!(names.contains(&"X".to_string()), "{imports}: {names:?}"); + } +} diff --git a/crates/sysmlv2-parser/tests/json.rs b/crates/sysmlv2-parser/tests/json.rs index 522a251..9d5d827 100644 --- a/crates/sysmlv2-parser/tests/json.rs +++ b/crates/sysmlv2-parser/tests/json.rs @@ -146,6 +146,40 @@ fn feature_value_and_literals() { assert_eq!(real["value"], 3.5); } +/// A real literal a double cannot denote exactly travels as its written +/// text, and lifts back to that same text — the JSON-path model and the +/// text-path model agree on the value either way. +#[test] +fn real_literals_beyond_double_precision_travel_as_text() { + use sysmlv2_parser::lift::from_compact_json; + use sysmlv2_parser::print::print_source; + for (written, wire) in [ + // Exactly representable: a number, as before. + ("3.5", Value::from(3.5)), + ("0.1", Value::from(0.1)), + // More significant digits than a double holds. + ( + "1.234567890123456789012345678901", + Value::from("1.234567890123456789012345678901"), + ), + // An exponent past the double range, which would otherwise + // become an infinity — and JSON has no spelling for that. + ("1e400", Value::from("1e400")), + ] { + let elements = emit(&format!("package P {{ attribute a = {written}; }}")); + let real = find(&elements, "LiteralRational"); + assert_eq!(real["value"], wire, "wire value of {written}"); + + let lifted = from_compact_json(&Value::Array(elements)).expect("lift"); + assert!(lifted.errors.is_empty(), "{:?}", lifted.errors); + let text = print_source(&lifted.unit); + assert!( + text.contains(written), + "{written} survives the lift: {text}" + ); + } +} + #[test] fn initial_and_default_value_flags() { let elements = emit("package P { attribute a : X := 1; }"); diff --git a/crates/sysmlv2-parser/tests/lexer.rs b/crates/sysmlv2-parser/tests/lexer.rs index a47012d..25a7fc5 100644 --- a/crates/sysmlv2-parser/tests/lexer.rs +++ b/crates/sysmlv2-parser/tests/lexer.rs @@ -224,3 +224,19 @@ fn tokens_cover_entire_input() { } assert_eq!(pos, src.len() as u32); } + +/// Decoding a name or string value is total: text that is not a complete +/// token — empty, unterminated, cut inside a multi-byte character, or never +/// quoted — decodes to what it holds. +#[test] +fn unescape_accepts_text_that_is_not_a_complete_token() { + assert_eq!(unescape(""), ""); + assert_eq!(unescape("'"), ""); + assert_eq!(unescape("\""), ""); + assert_eq!(unescape("''"), ""); + assert_eq!(unescape("\"\""), ""); + assert_eq!(unescape("'é"), "é"); + assert_eq!(unescape("\"héllo"), "héllo"); + assert_eq!(unescape("plain"), "plain"); + assert_eq!(unescape(r"'a\"), "a"); +} diff --git a/crates/sysmlv2-parser/tests/libcache.rs b/crates/sysmlv2-parser/tests/libcache.rs index 56bb27c..de58b0d 100644 --- a/crates/sysmlv2-parser/tests/libcache.rs +++ b/crates/sysmlv2-parser/tests/libcache.rs @@ -1,7 +1,7 @@ //! Standard-library resolution cache: recording, replay, and the //! cold/warm equivalence gate. -use sysmlv2_parser::json::model_to_compact_json; +use sysmlv2_parser::json::{library_to_compact_json, model_to_compact_json}; use sysmlv2_parser::libcache::{LibraryCache, TOOLKIT_BUILD, hash_library_dir}; use sysmlv2_parser::model::Model; @@ -51,6 +51,46 @@ fn cold_and_warm_builds_are_identical() { assert_eq!(cold, warm, "replayed build diverged from cold build"); } +/// A recorded miss that a user root import completes must resolve afresh +/// under replay: outcomes carry the root names they missed, and replay +/// skips exactly the entries a model's root additions reach. +#[test] +fn replay_re_resolves_outcomes_a_root_import_completes() { + let library = "package Other { part def X; } package L { part def A :> X; }"; + let mut recorder = Model::new(); + recorder.add_library_source("Lib.sysml", library); + recorder.record_library_cache(); + let _ = model_to_compact_json(&recorder); + let cache = recorder.take_recorded_library_cache().unwrap(); + let cache = LibraryCache::from_bytes(&cache.to_bytes()).expect("miss names round-trip"); + for user in [ + "private import Other::*; package U { part a : L::A; }", + "package U { part a : L::A; }", + ] { + let graphs = |cache: Option| { + let mut model = Model::new(); + model.add_library_source("Lib.sysml", library); + model.add_source("t.sysml", user); + if let Some(cache) = cache { + model.set_library_cache(cache); + } + ( + serde_json::to_string(&model_to_compact_json(&model)).unwrap(), + serde_json::to_string(&library_to_compact_json(&model)).unwrap(), + ) + }; + let cold = graphs(None); + let warm = graphs(Some(cache.clone())); + assert_eq!(cold, warm, "{user}"); + let completed = user.starts_with("private import"); + assert_eq!( + !warm.1.contains("\"@ref\":\"X\""), + completed, + "{user}: the library reference resolves only through the import" + ); + } +} + /// A user reference that disambiguates through a *library-internal* /// redefinition must resolve identically cold and warm: replay records /// spec outcomes like the slow path, so the inherited-merge shadowing @@ -207,6 +247,31 @@ fn invalid_cache_files_are_rejected() { std::fs::remove_dir_all(&dir).ok(); } +/// Both cache loaders refuse a file too large to be one of theirs before +/// reading it, so a wrong or hostile file at the cache path costs a file +/// size lookup rather than its length in memory. The snapshot loader is +/// the sibling of the resolution-recording loader here: they share the +/// limit and the capped read. +#[test] +fn oversized_cache_files_are_refused_without_reading_them() { + use sysmlv2_parser::prepared::PreparedLibrary; + let dir = std::env::temp_dir().join(format!("sysmlv2-libcache-huge-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("huge.libcache"); + // Sparse: the bytes are never allocated on disk either. + let file = std::fs::File::create(&path).unwrap(); + file.set_len(256 * 1024 * 1024 + 1).unwrap(); + drop(file); + let started = std::time::Instant::now(); + assert!(LibraryCache::load(&path).is_none()); + assert!(PreparedLibrary::load(&path, 0).is_none()); + assert!( + started.elapsed() < std::time::Duration::from_secs(5), + "the file must be refused by size, not read" + ); + std::fs::remove_dir_all(&dir).ok(); +} + /// The header's build identity must be finer than the crate version: two /// working-tree states share a version, and a semantics change that /// leaves the pending queue unchanged slips past the sequence @@ -230,7 +295,7 @@ fn header_carries_a_source_fingerprint_beyond_the_crate_version() { fn cache_from_another_toolkit_build_is_rejected() { fn sealed_empty_cache(build: &[u8]) -> Vec { let mut buf = Vec::new(); - buf.extend_from_slice(b"SYSML5LC"); + buf.extend_from_slice(b"SYSML6LC"); buf.push(build.len() as u8); buf.extend_from_slice(build); buf.extend_from_slice(&0u64.to_le_bytes()); // pending fingerprint @@ -285,3 +350,34 @@ fn library_hash_is_content_keyed() { assert_ne!(h1, h2); std::fs::remove_dir_all(&dir).ok(); } + +#[test] +fn anonymous_redefinition_fanout_survives_library_replay() { + if !sysmlv2_testkit::library_dir().exists() { + return; + } + let source = "package Demo { + part def Item; + part def Container { ref part items : Item[*]; } + part a : Item; + part c : Container { + ref :>> items = a; ref :>> items = a; ref :>> items = a; + } + }"; + let mut model = lib_model(source); + model.record_library_cache(); + let cold = model_to_compact_json(&model); + let cache = model.take_recorded_library_cache().unwrap(); + let rows = cold.as_array().unwrap(); + let base = &rows.iter().find(|e| e["declaredName"] == "items").unwrap()["@id"]; + let edges: Vec<_> = rows + .iter() + .filter(|e| e["@type"] == "Redefinition") + .collect(); + assert_eq!(edges.len(), 3); + assert!(edges.iter().all(|e| &e["redefinedFeature"]["@id"] == base)); + let mut model = lib_model(source); + model.set_library_cache(cache); + assert_eq!(model_to_compact_json(&model), cold); + assert!(sysmlv2_parser::check::validate_model(&model).is_empty()); +} diff --git a/crates/sysmlv2-parser/tests/model.rs b/crates/sysmlv2-parser/tests/model.rs index c1c1332..e072e83 100644 --- a/crates/sysmlv2-parser/tests/model.rs +++ b/crates/sysmlv2-parser/tests/model.rs @@ -969,3 +969,694 @@ fn view_exposure_honors_filters() { "{cool:?}" ); } + +#[cfg(feature = "json")] +#[test] +fn anonymous_redefinition_fanout_targets_the_inherited_feature() { + use sysmlv2_parser::{check, json::ResolvedModel}; + let lib = "package Lib { part def Item { attribute name; } + part def Container { ref part items : Item[*]; } }"; + for count in 1..=4 { + for reverse_files in [false, true] { + let members = (0..count) + .map(|i| format!("ref :>> items = a{i};")) + .collect::>() + .join("\n"); + let values = (0..count) + .map(|i| format!("part a{i} : Item;")) + .collect::>() + .join("\n"); + let usage = format!( + "package Usage {{ private import Lib::*; {values} + part c : Container {{ {members} }} }}" + ); + let mut model = Model::new(); + let mut sources = vec![("lib.sysml", lib), ("usage.sysml", usage.as_str())]; + if reverse_files { + sources.reverse(); + } + for (name, text) in sources { + model.add_source(name, text); + } + assert!(!model.has_errors()); + let mut resolved = ResolvedModel::build(&model); + let base = resolved.resolve_qualified("Lib::Container::items").unwrap(); + let target = resolved.element_id(base).to_string(); + let rows = emit(&model); + let edges: Vec<_> = rows + .iter() + .filter(|e| e["@type"] == "Redefinition") + .collect(); + assert_eq!(edges.len(), count); + for edge in edges { + assert_eq!( + edge["redefinedFeature"]["@id"].as_str(), + Some(target.as_str()), + "{count} siblings, reversed={reverse_files}: {edge}" + ); + } + assert!(check::validate_model(&model).is_empty()); + assert!(check::validate_semantics(&model).is_empty()); + let sites: Vec<_> = resolved + .reference_sites() + .iter() + .filter(|site| site.kind == "redefinedFeature") + .collect(); + assert_eq!(sites.len(), count); + assert!(sites.iter().all(|site| site.target == base)); + } + } +} + +#[cfg(feature = "json")] +#[test] +fn redefinition_fanout_preserves_inherited_overrides_and_named_members() { + use sysmlv2_parser::{check, json::ResolvedModel}; + for members in [ + "ref :>> items = a; ref :>> items = b;", + "ref namedItem :>> items = a; ref :>> items = b;", + "ref :>> items = b; ref namedItem :>> items = a;", + ] { + let source = format!( + "package P {{ + part def Item {{ attribute marker = 7; }} + part def Base {{ ref part items : Item[*]; }} + part def Derived :> Base {{ ref :>> items; }} + part a : Item; part b : Item; + part c : Derived {{ {members} }} + }}" + ); + let mut model = Model::new(); + model.add_source("inherit.sysml", &source); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let base = r.resolve_qualified("P::Base::items").unwrap(); + let inherited = r.resolve_qualified("P::Derived::items").unwrap(); + assert_ne!(base, inherited); + let rows = emit(&model); + let edges: Vec<_> = rows + .iter() + .filter(|e| e["@type"] == "Redefinition") + .collect(); + assert_eq!(edges.len(), 3); + assert_eq!( + edges[0]["redefinedFeature"]["@id"], + r.element_id(base).to_string() + ); + for edge in &edges[1..] { + assert_eq!( + edge["redefinedFeature"]["@id"], + r.element_id(inherited).to_string() + ); + } + assert!(check::validate_model(&model).is_empty()); + } + // Declared local targets remain visible: the fix is not an + // inherited-only lookup, nor a blanket removal of local members. + let mut model = Model::new(); + model.add_source( + "local.kerml", + "class C { feature x; feature y redefines x; }", + ); + let mut r = ResolvedModel::build(&model); + let x = r.resolve_qualified("C::x").unwrap(); + let rows = emit(&model); + let edge = rows.iter().find(|e| e["@type"] == "Redefinition").unwrap(); + assert_eq!(edge["redefinedFeature"]["@id"], r.element_id(x).to_string()); +} + +#[cfg(feature = "json")] +#[test] +fn redefinition_fanout_does_not_hide_missing_or_ambiguous_targets() { + use sysmlv2_parser::check; + for (definitions, typing, diagnostic) in [ + ("part def C;", "C", "unresolved reference `items`"), + ( + "part def L { ref part items : Item[*]; } + part def R { ref part items : Item[*]; }", + "L, R", + "ambiguous reference `items`", + ), + ] { + let mut model = Model::new(); + model.add_source( + "invalid.sysml", + &format!( + "package P {{ + part def Item; {definitions} part a : Item; + part c : {typing} {{ ref :>> items = a; ref :>> items = a; }} + }}" + ), + ); + assert!(!model.has_errors()); + let findings = check::validate_model(&model); + assert_eq!(findings.len(), 2, "{findings:?}"); + assert!( + findings.iter().all(|(_, d)| d.message.contains(diagnostic)), + "{findings:?}" + ); + } + // Ordinary references to indistinguishable siblings remain ambiguous. + let mut model = Model::new(); + model.add_source( + "ordinary.sysml", + "package P { + part def Item; part def C { ref part items : Item[*]; } + part a : Item; + part c : C { ref :>> items = a; ref :>> items = a; } + attribute probe = c::items; + }", + ); + let findings = check::validate_model(&model); + assert_eq!(findings.len(), 1, "{findings:?}"); + assert!(findings[0].1.message.contains("ambiguous"), "{findings:?}"); +} + +#[cfg(feature = "json")] +#[test] +fn kerml_redefinition_fanout_keeps_inherited_member_lookup() { + use sysmlv2_parser::{check, json::ResolvedModel}; + let mut model = Model::new(); + model.add_source( + "fanout.kerml", + "package P { + class Item { feature marker = 7; } + class C { feature items : Item[*]; } + feature c : C { + feature redefines items { feature result = marker; } + feature redefines items { feature result = marker; } + feature redefines items { feature result = marker; } + } + }", + ); + assert!(!model.has_errors()); + assert!(check::validate_model(&model).is_empty()); + let mut r = ResolvedModel::build(&model); + let base = r.resolve_qualified("P::C::items").unwrap(); + let marker = r.resolve_qualified("P::Item::marker").unwrap(); + let sites: Vec<_> = r + .reference_sites() + .iter() + .filter(|site| site.kind == "redefinedFeature") + .collect(); + assert_eq!(sites.len(), 3); + assert!(sites.iter().all(|site| site.target == base)); + assert_eq!(r.references_to(marker).len(), 3); +} + +/// `inherited_memberships` / `inherited_features` / +/// `effective_features` — the resolver's inheritance walk enumerated. +#[cfg(feature = "json")] +#[test] +fn inherited_members_enumeration() { + use sysmlv2_parser::json::ResolvedModel; + let mut model = Model::new(); + model.add_source( + "m.sysml", + "package P { + part def Base { + attribute mass; + private attribute hidden; + } + part def Mid :> Base { attribute midOnly; } + part def Sub :> Mid { attribute own; } + part def Shadow :> Base { attribute mass; } + part def Redef :> Base { attribute total :>> mass; } + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let by_name = |r: &mut ResolvedModel, qn: &str| r.resolve_qualified(qn).unwrap(); + + // Transitive inheritance, private excluded; memberships returned, + // declaring type = the membership's owner. + let sub = by_name(&mut r, "P::Sub"); + let inherited = r.inherited_memberships(sub, false); + let names: Vec<_> = inherited + .iter() + .map(|&m| r.membership_member_name(m).unwrap()) + .collect(); + assert_eq!(names, ["midOnly", "mass"], "BFS order: Mid's before Base's"); + let mid = by_name(&mut r, "P::Mid"); + let base = by_name(&mut r, "P::Base"); + assert_eq!(r.owner(inherited[0]), Some(mid), "midOnly declared by Mid"); + assert_eq!(r.owner(inherited[1]), Some(base), "mass declared by Base"); + for &m in &inherited { + assert!(!r.membership_is_alias(m)); + assert!(r.membership_member(m).is_some()); + } + + // effective = owned then inherited. + let eff: Vec<_> = r + .effective_features(sub, true) + .iter() + .map(|&m| r.element_name(m).unwrap().to_string()) + .collect(); + assert_eq!(eff, ["own", "midOnly", "mass"]); + + // Same-name shadowing: an owned `mass` hides the inherited one. + let shadow = by_name(&mut r, "P::Shadow"); + assert!(r.inherited_features(shadow, false).is_empty()); + + // Redefinition shadowing under a *different* name: `total :>> mass`. + let redef = by_name(&mut r, "P::Redef"); + assert!(r.inherited_features(redef, false).is_empty()); + + // No heritage -> empty; and the definition itself is not a feature. + assert!(r.inherited_memberships(base, false).is_empty()); +} + +/// `include_implied` walks the Tables 31/32 library bases — +/// an action usage inherits `Actions::Action`'s `start`/`done`. +#[cfg(feature = "json")] +#[test] +fn inherited_members_implied_library_bases() { + use sysmlv2_parser::json::ResolvedModel; + let lib = sysmlv2_testkit::library_dir(); + let mut model = Model::new(); + model.load_library_dir(&lib).unwrap(); + model.add_source("a.sysml", "package Q { action a { action step1; } }"); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let a = r.resolve_qualified("Q::a").unwrap(); + + // Explicit-only: no written heritage, nothing inherited. + assert!(r.inherited_features(a, false).is_empty()); + + // Implied: Actions::Action's members arrive, `start`/`done` included. + let implied: Vec<_> = r + .inherited_features(a, true) + .iter() + .filter_map(|&m| r.element_lookup_name(m)) + .collect(); + assert!( + implied.iter().any(|n| n == "start") && implied.iter().any(|n| n == "done"), + "expected start/done among implied-inherited features, got: {implied:?}" + ); + for m in r.inherited_features(a, true) { + assert!(r.is_library_element(m)); + } +} + +/// Conformance corner cases: imported memberships inherit, unrelated +/// same-name branches are both retained, and the OCL intersection +/// condition removes redefinition siblings. +#[cfg(feature = "json")] +#[test] +fn inherited_members_imports_and_redefinition_siblings() { + use sysmlv2_parser::json::ResolvedModel; + + // (1) A public import in the base re-exports through heritage. + let mut model = Model::new(); + model.add_source( + "i.sysml", + "package P { + part def Imported { attribute fromImport; } + part def Base { public import Imported::fromImport; } + part def Sub :> Base; + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let names: Vec<_> = r + .inherited_features(sub, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert_eq!(names, ["fromImport"], "public import must inherit"); + + // (1b) A private import must NOT inherit. + let mut model = Model::new(); + model.add_source( + "ip.sysml", + "package P { + part def Imported { attribute fromImport; } + part def Base { private import Imported::fromImport; } + part def Sub :> Base; + }", + ); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + assert!(r.inherited_features(sub, false).is_empty()); + + // (2) Same-name features of unrelated branches are both retained + // (name lookup is ambiguous; the memberships still inherit). + let mut model = Model::new(); + model.add_source( + "u.sysml", + "package P { + part def A { attribute x; } + part def B { attribute x; } + part def D :> B; + part def C :> A, D; + }", + ); + let mut r = ResolvedModel::build(&model); + let c = r.resolve_qualified("P::C").unwrap(); + let xs: Vec<_> = r + .inherited_features(c, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert_eq!(xs, ["x", "x"], "both unrelated x features inherit"); + + // (3) Intersection condition: owned `z :>> A::x` removes both the + // redefined `x` and the sibling `y :>> x` arriving from `B`. + let mut model = Model::new(); + model.add_source( + "s.sysml", + "package P { + part def A { attribute x; } + part def B :> A { attribute y :>> x; } + part def C :> B { attribute z :>> A::x; } + }", + ); + let mut r = ResolvedModel::build(&model); + let c = r.resolve_qualified("P::C").unwrap(); + let leftover: Vec<_> = r + .inherited_features(c, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert!( + leftover.is_empty(), + "y and x both removed by the intersection condition, got {leftover:?}" + ); + + // (4) Alias memberships inherit as memberships: `alias m for mass` + // in the base arrives on the subtype, navigable to its target. + let mut model = Model::new(); + model.add_source( + "a.sysml", + "package P { + part def Base { attribute mass; alias m for mass; } + part def Sub :> Base; + }", + ); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let memberships = r.inherited_memberships(sub, false); + let alias = memberships + .iter() + .copied() + .find(|&m| r.membership_is_alias(m)) + .expect("inherited alias membership"); + assert_eq!(r.membership_member_name(alias).as_deref(), Some("m")); + let mass = r.resolve_qualified("P::Base::mass").unwrap(); + assert_eq!(r.membership_member(alias), Some(mass)); + // The ordinary membership for `mass` is present too. + assert!( + memberships + .iter() + .any(|&m| !r.membership_is_alias(m) && r.membership_member(m) == Some(mass)) + ); +} + +/// Composition corner cases: nested re-export filter policy, +/// imported aliases, cross-branch redefiner independence, and the +/// heritage of imported scopes. +#[cfg(feature = "json")] +#[test] +fn inherited_members_import_policy_composition() { + use sysmlv2_parser::json::ResolvedModel; + + // (1) A nested public re-export keeps its own filter policy. + let mut model = Model::new(); + model.add_source( + "f.sysml", + "package P { + metadata def Safety; + package Lib { + part safe { @Safety; } + part plain; + } + package Reexport { public import Lib::*[@Safety]; } + part def Base { public import Reexport::*; } + part def Sub :> Base; + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let names: Vec<_> = r + .inherited_features(sub, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert!(names.contains(&"safe".to_string()), "{names:?}"); + assert!( + !names.contains(&"plain".to_string()), + "nested [@Safety] filter must hold through the re-export: {names:?}" + ); + + // (2) Aliases reached through a public import are enumerated. + let mut model = Model::new(); + model.add_source( + "a.sysml", + "package P { + package Lib { + part x; + alias a for x; + } + part def Base { public import Lib::*; } + part def Sub :> Base; + }", + ); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let memberships = r.inherited_memberships(sub, false); + let alias = memberships + .iter() + .copied() + .find(|&m| r.membership_is_alias(m)) + .expect("imported alias membership"); + assert_eq!(r.membership_member_name(alias).as_deref(), Some("a")); + let x = r.resolve_qualified("P::Lib::x").unwrap(); + assert_eq!(r.membership_member(alias), Some(x)); + + // (3) Redefiners of unrelated heritage branches never suppress one + // another; an owned redefiner still suppresses both. + let mut model = Model::new(); + model.add_source( + "b.sysml", + "package P { + part def A { attribute x; } + part def B :> A { attribute y :>> x; } + part def D :> A { attribute z :>> x; } + part def E :> D; + part def C :> B, E; + part def F :> B, E { attribute own :>> A::x; } + }", + ); + let mut r = ResolvedModel::build(&model); + let c = r.resolve_qualified("P::C").unwrap(); + let mut names: Vec<_> = r + .inherited_features(c, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + names.sort(); + assert_eq!(names, ["y", "z"], "both branch redefiners inherit"); + let f = r.resolve_qualified("P::F").unwrap(); + let leftover: Vec<_> = r + .inherited_features(f, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert!( + leftover.is_empty(), + "owned `own :>> A::x` suppresses x, y, and z: {leftover:?}" + ); + + // (4) Inherited members of an *imported* type resolve through the + // import — enumeration follows lookup's base arm. + let mut model = Model::new(); + model.add_source( + "h.sysml", + "package P { + part def Other { attribute deep; } + part def Mixin :> Other { attribute shallow; } + part def Base { public import Mixin::*; } + part def Sub :> Base; + }", + ); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("P::Sub").unwrap(); + let names: Vec<_> = r + .inherited_features(sub, false) + .iter() + .filter_map(|&m| r.element_name(m).map(str::to_string)) + .collect(); + assert!( + names.contains(&"shallow".to_string()) && names.contains(&"deep".to_string()), + "imported type's own + inherited members both arrive: {names:?}" + ); +} + +/// `include_implied = false` holds through imported type scopes too: a +/// base's `import T::*` contributes T's own members, not the members of +/// T's implied library bases. +#[cfg(feature = "json")] +#[test] +fn include_implied_false_holds_through_imported_type_scopes() { + use sysmlv2_parser::json::ResolvedModel; + let lib = sysmlv2_testkit::library_dir(); + if !lib.exists() { + eprintln!("skipping: corpus not present"); + return; + } + let mut model = Model::new(); + model.load_library_dir(&lib).unwrap(); + model.add_source( + "a.sysml", + "package Q { + part def T { attribute x; } + part def Base { public import T::*; } + part def Sub :> Base; + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let sub = r.resolve_qualified("Q::Sub").unwrap(); + let names = |r: &mut ResolvedModel, implied: bool| -> Vec { + let mut v: Vec = r + .inherited_memberships(sub, implied) + .iter() + .filter_map(|&m| r.membership_member_name(m)) + .collect(); + v.sort(); + v + }; + assert_eq!(names(&mut r, false), ["x"]); + let implied = names(&mut r, true); + assert!( + implied.contains(&"x".to_string()) && implied.len() > 1, + "T's implied bases contribute only when asked: {implied:?}" + ); +} + +/// Written heritage is consulted before implied library heritage — the +/// order `base_scopes` has always used, now made explicit by the +/// written/implied split. Where a written base and an implied Tables 31/32 +/// base both declare a member of one name with non-overlapping metaclasses, +/// lookup keeps the earlier candidate, so the written base's member wins. +#[cfg(feature = "json")] +#[test] +fn written_base_precedes_implied_library_base_in_lookup() { + use sysmlv2_parser::json::ResolvedModel; + let lib = sysmlv2_testkit::library_dir(); + if !lib.exists() { + eprintln!("skipping: corpus not present"); + return; + } + let mut model = Model::new(); + model.load_library_dir(&lib).unwrap(); + // `Actions::Action` (the implied base of every action definition) + // declares the action usage `start`; the written base declares an + // attribute of the same name. + model.add_source( + "p.sysml", + "package Q { + action def Base { attribute start; } + action def A :> Base { attribute again :>> start; } + }", + ); + let mut r = ResolvedModel::build(&model); + let again = r.resolve_qualified("Q::A::again").unwrap(); + let base = r.resolve_qualified("Q::Base").unwrap(); + let targets = r.redefinition_targets(again); + assert_eq!(targets.len(), 1, "{targets:?}"); + assert_eq!( + r.owner(targets[0]), + Some(base), + "the written base's member wins" + ); + assert_eq!(r.element_type(targets[0]), "AttributeUsage"); +} + +/// A chain-source transition (`first v.a`) still reports its source +/// through `transition_parts` now that the source membership is an +/// OwningMembership owning the chain feature. +#[cfg(feature = "json")] +#[test] +fn transition_parts_reads_a_chain_source() { + use sysmlv2_parser::json::ResolvedModel; + let mut model = Model::new(); + model.add_source( + "t.sysml", + "package P { + part def V { part a; } + state def S { + part v : V; + state s1; state s2; + transition t1 first s1 then s2; + transition t2 first v.a then s2; + } + }", + ); + assert!(!model.has_errors()); + let mut r = ResolvedModel::build(&model); + let t1 = r.resolve_qualified("P::S::t1").unwrap(); + let t2 = r.resolve_qualified("P::S::t2").unwrap(); + let s1 = r.resolve_qualified("P::S::s1").unwrap(); + assert_eq!(r.transition_parts(t1).source, Some(s1)); + let src = r.transition_parts(t2).source.expect("chain source"); + assert_eq!(r.element_type(src), "Feature"); + assert!( + r.owned_relationships(src) + .iter() + .any(|&x| r.element_type(x) == "FeatureChaining"), + "the source is the synthesized chain feature" + ); +} + +/// The declared multiplicity of an element is its own written clause, +/// read through the owner index the builder keeps for the table. +#[test] +fn declared_multiplicity_reads_the_element_s_own_clause() { + use sysmlv2_parser::json::ResolvedModel; + let mut model = Model::new(); + model.add_source( + "p.sysml", + "package P { + part def D; + part a : D[2..5]; + part bare : D; + part heir :>> a; + part many : D[*]; + }", + ); + let mut r = ResolvedModel::build(&model); + let [a, bare, heir, many] = + ["P::a", "P::bare", "P::heir", "P::many"].map(|qn| r.resolve_qualified(qn).unwrap()); + assert_eq!(r.declared_multiplicity(a), Some((2.0, 5.0))); + // Answers are stable across lookups and independent of the order. + assert_eq!(r.declared_multiplicity(many), Some((0.0, f64::INFINITY))); + assert_eq!(r.declared_multiplicity(a), Some((2.0, 5.0))); + // An element that declares none has none; inherited clauses are + // deliberately not walked. + assert_eq!(r.declared_multiplicity(bare), None); + assert_eq!(r.declared_multiplicity(heir), None); +} + +/// Elements added on top of a prepared library are indexed alongside the +/// library's own rows, and neither side shadows the other. +#[test] +fn declared_multiplicity_spans_a_prepared_library_and_its_model() { + use sysmlv2_parser::json::ResolvedModel; + let mut base = Model::new(); + base.add_library_source( + "lib.sysml", + "library package L { part def D; part shared : D[3..4]; }", + ); + let prepared = base.prepare_library().unwrap(); + let mut model = Model::new(); + prepared.install(&mut model).unwrap(); + model.add_source("p.sysml", "package P { part own : L::D[1..2]; }"); + let mut r = ResolvedModel::build(&model); + let own = r.resolve_qualified("P::own").unwrap(); + let shared = r.resolve_qualified("L::shared").unwrap(); + assert_eq!(r.declared_multiplicity(own), Some((1.0, 2.0))); + assert_eq!(r.declared_multiplicity(shared), Some((3.0, 4.0))); +} diff --git a/crates/sysmlv2-parser/tests/negative.rs b/crates/sysmlv2-parser/tests/negative.rs index a034a34..32ca325 100644 --- a/crates/sysmlv2-parser/tests/negative.rs +++ b/crates/sysmlv2-parser/tests/negative.rs @@ -14,6 +14,7 @@ //! Diagnostics come from the same stages as `sysmlv2 check` without //! `--lib`: parse diagnostics plus body-context validation. +use std::fmt::Write as _; use std::fs; use std::path::PathBuf; use sysmlv2_parser::diag::Severity; @@ -103,18 +104,19 @@ fn negative_corpus_diagnostics() { .find(|e| !e.matched && e.line == line && d.message.contains(&e.substring)); match claimed { Some(e) => e.matched = true, - None => report.push_str(&format!( - " {name}:{line}: unexpected error: {}\n", - d.message - )), + None => { + writeln!(report, " {name}:{line}: unexpected error: {}", d.message).unwrap(); + } } } for e in &expected { if !e.matched { - report.push_str(&format!( - " {name}:{}: expected error not produced: {}\n", + writeln!( + report, + " {name}:{}: expected error not produced: {}", e.line, e.substring - )); + ) + .unwrap(); } } } diff --git a/crates/sysmlv2-parser/tests/negative/flow_payloads.kerml b/crates/sysmlv2-parser/tests/negative/flow_payloads.kerml index 99002ec..37cac46 100644 --- a/crates/sysmlv2-parser/tests/negative/flow_payloads.kerml +++ b/crates/sysmlv2-parser/tests/negative/flow_payloads.kerml @@ -1,4 +1,4 @@ -// KerML has the same requirement after the 2026-05 grammar correction. +// KerML has the same requirement in the pinned grammar. package P { flow of; //~ ERROR a payload requires a type, specialization, or value flow of [1]; //~ ERROR expected a name diff --git a/crates/sysmlv2-parser/tests/opensysml.rs b/crates/sysmlv2-parser/tests/opensysml.rs new file mode 100644 index 0000000..14383c4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/opensysml.rs @@ -0,0 +1,144 @@ +//! Independent negative models, with explicit known gaps rather than a claim +//! that every diagnostic is the intended rejection. Two committed baselines +//! pin every file's stage diagnostics: one without a library (missing +//! dependencies stay unknown) and one against the full standard library +//! (the census the backlog plan quotes). Both run the stages of +//! `support/census.rs`, shared with the `opensysmlcheck` reporting example. + +#[path = "support/census.rs"] +mod census; + +use serde_json::{Value, json}; +use std::{collections::BTreeMap, fs, path::Path, path::PathBuf}; +use sysmlv2_parser::model::Model; + +fn root() -> PathBuf { + Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml") +} + +/// The pinned census: every provenance entry exists and nothing else does. +fn provenance_files() -> Vec { + let provenance: Value = + serde_json::from_str(&fs::read_to_string(root().join("provenance.json")).unwrap()).unwrap(); + let entries = provenance["files"].as_array().unwrap(); + assert_eq!( + entries.len(), + 462, + "fixture census changed; adjudicate the source pin" + ); + let mut files = Vec::new(); + sysmlv2_testkit::collect_files(&root(), &mut files); + assert_eq!( + files.len(), + entries.len(), + "fixture removed or added without provenance" + ); + entries + .iter() + .map(|e| e["file"].as_str().unwrap().to_string()) + .collect() +} + +fn negative_contracts() -> Value { + serde_json::from_str(include_str!("fixtures/opensysml/negative-contracts.json")).unwrap() +} + +/// Compare (or, under `UPDATE_OPENSYSML_BASELINE`, rewrite) a baseline +/// file. Improvements change the baseline too, so every difference is +/// adjudicated by hand. +fn gate(baseline: &str, actual: &BTreeMap) { + let path = root().join(baseline); + if std::env::var_os("UPDATE_OPENSYSML_BASELINE").is_some() { + fs::write(&path, serde_json::to_string_pretty(actual).unwrap() + "\n").unwrap(); + } + let expected: BTreeMap = + serde_json::from_str(&fs::read_to_string(&path).expect("missing adjudicated baseline")) + .unwrap(); + let changed: Vec<_> = actual + .iter() + .filter(|(file, value)| expected.get(*file) != Some(*value)) + .map(|(file, value)| format!("{file}: {value}")) + .collect(); + assert!( + changed.is_empty(), + "{baseline} changed; adjudicate improvements as well as regressions:\n{}", + changed.join("\n") + ); + assert_eq!(expected.len(), actual.len()); +} + +#[test] +fn opensysml_negative_diagnostic_baseline() { + let accepted = census::accepted_fixtures(&negative_contracts()); + let mut actual = BTreeMap::new(); + let mut unknown = 0; + for name in provenance_files() { + let source = fs::read_to_string(root().join(&name)).unwrap(); + let mut model = Model::new(); + model.add_source(&name, &source); + let rows = census::stage_diagnostics(&model); + let status = census::status( + &rows, + true, + accepted.contains(&name), + "unknown without library", + ); + if status == "unknown without library" { + unknown += 1; + } + actual.insert(name, json!({ "status": status, "diagnostics": rows })); + } + eprintln!( + "negative corpus without library: {} files, {unknown} unknown without library", + actual.len() + ); + gate("baseline.json", &actual); +} + +/// The full-library census: the same files against the standard library, +/// gated on a second baseline, plus every registered contract. +#[test] +fn opensysml_library_diagnostic_baseline() { + // One retained library graph installed into every model; parity with + // per-file resolution replay over these fixtures is gated by + // `tests/prepared_library.rs`. + let mut base = Model::new(); + base.load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + let prepared = base.prepare_library().unwrap(); + + let accepted = census::accepted_fixtures(&negative_contracts()); + let mut rows_by_file = BTreeMap::new(); + let mut actual = BTreeMap::new(); + let mut unknown = 0; + for name in provenance_files() { + let source = fs::read_to_string(root().join(&name)).unwrap(); + let mut model = Model::new(); + prepared.clone().install(&mut model).unwrap(); + model.add_source(&name, &source); + let rows = census::stage_diagnostics(&model); + let status = census::status(&rows, false, accepted.contains(&name), "unknown"); + if status == "unknown" { + unknown += 1; + } + actual.insert( + name.clone(), + json!({ "status": status, "diagnostics": rows }), + ); + rows_by_file.insert(name, rows); + } + eprintln!( + "negative corpus with library: {} files, {unknown} unknown", + actual.len() + ); + let static_contracts: Value = + serde_json::from_str(include_str!("fixtures/opensysml/static-contracts.json")).unwrap(); + let missing = + census::contract_failures(&rows_by_file, &static_contracts, &negative_contracts()); + assert!( + missing.is_empty(), + "intended-rule regressions: {}", + missing.join(", ") + ); + gate("baseline-library.json", &actual); +} diff --git a/crates/sysmlv2-parser/tests/parser.rs b/crates/sysmlv2-parser/tests/parser.rs index 22e0c4f..f15f5ff 100644 --- a/crates/sysmlv2-parser/tests/parser.rs +++ b/crates/sysmlv2-parser/tests/parser.rs @@ -807,6 +807,29 @@ fn constructor_and_metadata_access() { value_expr("x.metadata").kind, ExprKind::MetadataAccess { .. } )); + let ExprKind::MetadataAccess { target } = value_expr("P::Q::x.metadata").kind else { + panic!() + }; + assert_eq!(target.to_display_string(), "P::Q::x"); + // A left operand that is not an element reference is diagnosed, and the + // operand itself survives in the tree. + let Parse { unit, diagnostics } = parse_source("package P { attribute a = (1 + 2).metadata; }"); + assert!( + diagnostics + .iter() + .any(|d| d.message.contains("element reference")), + "{diagnostics:#?}" + ); + let MemberKind::Package(pkg) = &unit.members[0].kind else { + panic!() + }; + let MemberKind::Usage(u) = &pkg.body.as_ref().unwrap()[0].kind else { + panic!() + }; + assert!(matches!( + u.value.as_ref().unwrap().expr.kind, + ExprKind::Binary { .. } + )); } #[test] @@ -1051,10 +1074,24 @@ fn member_prefixed_target_succession_source_multiplicity() { panic!() }; assert!(source.multiplicity.is_some()); - assert!(matches!(&source.target, TargetRef::Chain(links) if links.is_empty())); + assert!(source.target.is_unspelled()); assert!(matches!(&target.target, TargetRef::Name(qn) if qn.to_display_string() == "next")); } +/// The reference of an end the text does not spell has a name of its own, +/// is recognised by it, and carries no span because it covers no text. +#[test] +fn an_unspelled_reference_is_named_and_spanless() { + let unspelled = TargetRef::unspelled(); + assert!(unspelled.is_unspelled()); + assert_eq!(unspelled.span(), sysmlv2_parser::Span::default()); + let spelled = first_usage("package P { connect a to b; }"); + let UsageDetail::Connector { ends } = &spelled.detail else { + panic!() + }; + assert!(ends.iter().all(|e| !e.target.is_unspelled())); +} + #[test] fn perform_and_event_forms() { let u = first_usage("package P { perform takePicture.focus; }"); @@ -1782,3 +1819,403 @@ fn spans_are_meaningful() { let m = &unit.members[0]; assert_eq!(m.span.slice(src), src.trim_end()); } + +// --------------------------------------------------------------------------- +// Member-start lookahead +// --------------------------------------------------------------------------- + +fn state_body(src: &str) -> Vec { + let body = package_body(src); + let MemberKind::Definition(d) = &body[0].kind else { + panic!("expected a state definition, got {:?}", body[0].kind) + }; + let MemberKind::Usage(s) = &d.body.as_ref().unwrap()[0].kind else { + panic!("expected a state usage") + }; + s.body.clone().expect("state body") +} + +/// The lookahead that tells an accept *node* from the accept-transition +/// shorthand balances braces, so a trigger carrying a body-expression +/// argument keeps its `then` target, and it scans the whole member, so a +/// trigger of any length does too. +#[test] +fn accept_transition_shorthand_keeps_its_target() { + let items = state_body( + "package P { + state def S { + state s1 { + accept sig when xs->exists { in x; x > 0 } then s2; + } + state s2; + } + }", + ); + assert_eq!(items.len(), 1, "{items:#?}"); + let MemberKind::Usage(t) = &items[0].kind else { + panic!("{:?}", items[0].kind) + }; + assert_eq!(t.kind, UsageKind::Transition); + let UsageDetail::Transition { + trigger, target, .. + } = &t.detail + else { + panic!() + }; + assert!(trigger.is_some() && target.is_some()); + + // A trigger far longer than any fixed scan window. + let guard = (0..250) + .map(|i| format!("a{i} > 0")) + .collect::>() + .join(" and "); + let items = state_body(&format!( + "package P {{ + state def S {{ + state s1 {{ + accept sig when {guard} then s2; + }} + state s2; + }} + }}" + )); + assert_eq!(items.len(), 1, "{items:#?}"); + let MemberKind::Usage(t) = &items[0].kind else { + panic!("{:?}", items[0].kind) + }; + assert_eq!(t.kind, UsageKind::Transition); + + // An accept node with a body is still a node, not a transition. + let items = state_body( + "package P { + state def S { + state s1 { + accept sig : Signal { assign x := 1; } + } + } + }", + ); + let MemberKind::Usage(a) = &items[0].kind else { + panic!("{:?}", items[0].kind) + }; + assert_eq!(a.kind, UsageKind::Accept); + assert!(a.body.is_some()); +} + +/// A `{` that follows a complete trigger or payload expression opens the +/// accept node's own body and ends the lookahead, so a following member +/// starting with `then`, `if` or `do` is neither consumed nor able to turn +/// the node into a transition shorthand. +#[test] +fn accept_node_body_ends_the_lookahead() { + fn action_body(src: &str) -> Vec { + let body = package_body(src); + let MemberKind::Usage(a) = &body[0].kind else { + panic!("expected an action usage, got {:?}", body[0].kind) + }; + a.body.clone().expect("action body") + } + + for trigger in ["via p", "at t1", "when c", ": Signal"] { + for tail in ["then b;", "if g then b;", "do b;"] { + let src = format!( + "package P {{ action a {{ accept sig {trigger} {{ }} {tail} action b; }} }}" + ); + let items = action_body(&src); + let MemberKind::Usage(node) = &items[0].kind else { + panic!("{src}: {:?}", items[0].kind) + }; + assert_eq!(node.kind, UsageKind::Accept, "{src}"); + assert!(node.body.is_some(), "{src}"); + // The tail and the following declaration both survive as their + // own members. + assert_eq!(items.len(), 3, "{src}: {items:#?}"); + } + } +} + +/// A trigger, a `via` clause and a payload's value are parsed as full +/// expressions, and a conditional is one of them: its `if` stands where an +/// operand is expected, so it opens the conditional rather than the guard +/// of the transition shorthand. The parenthesized and bare spellings +/// classify alike, and the guard that really is one still reads as a +/// guard. +#[test] +fn a_conditional_in_a_trigger_is_not_the_shorthands_guard() { + fn only_member(src: &str) -> Usage { + let items = state_body(src); + assert_eq!(items.len(), 1, "{src}: {items:#?}"); + let MemberKind::Usage(u) = &items[0].kind else { + panic!("{src}: {:?}", items[0].kind) + }; + u.clone() + } + + for trigger in [ + "when (if a ? b else c)", + "when if a ? b else c", + "when if a ? b else if c ? d else e", + "via if a ? p else q", + "when if g ? b else c", + ] { + let src = format!( + "package P {{ + state def S {{ + state s1 {{ + accept sig : Sig {trigger}; + }} + state s2; + }} + }}" + ); + assert_eq!(only_member(&src).kind, UsageKind::Accept, "{src}"); + } + + // The shorthand's guard is still a guard — after a payload, after a + // trigger expression, and after one that ends in a conditional. + for head in [ + "accept sig : Sig if g", + "accept sig when c if g", + "accept sig when if a ? b else c if g", + ] { + let src = format!( + "package P {{ + state def S {{ + state s1 {{ + {head} then s2; + }} + state s2; + }} + }}" + ); + let member = only_member(&src); + assert_eq!(member.kind, UsageKind::Transition, "{src}"); + let UsageDetail::Transition { guard, target, .. } = &member.detail else { + panic!("{src}: {:?}", member.detail) + }; + assert!(guard.is_some() && target.is_some(), "{src}"); + } +} + +/// The word-spelled operators take an operand the way their symbolic +/// spellings do, and an expression may spell an operand as a body. A +/// brace after one therefore opens that operand, not the accept node's +/// own body — so the scan reads on to the `then` beyond it and classifies +/// the member as the transition it is. +#[test] +fn a_brace_after_a_word_operator_is_an_operand() { + fn only_member(src: &str) -> Usage { + let items = state_body(src); + assert_eq!(items.len(), 1, "{src}: {items:#?}"); + let MemberKind::Usage(u) = &items[0].kind else { + panic!("{src}: {:?}", items[0].kind) + }; + u.clone() + } + + fn state(member: &str) -> String { + format!( + "package P {{ + state def S {{ + state s1 {{ + {member} + }} + state s2; + }} + }}" + ) + } + + for expr in [ + "a and { b }", + "a or { b }", + "a xor { b }", + "a implies { b }", + "not { b }", + ] { + let src = state(&format!("accept sig : Sig when {expr} then s2;")); + let member = only_member(&src); + assert_eq!(member.kind, UsageKind::Transition, "{src}"); + let UsageDetail::Transition { + trigger, target, .. + } = &member.detail + else { + panic!("{src}: {:?}", member.detail) + }; + assert!(trigger.is_some() && target.is_some(), "{src}"); + + // Without the tail the same head is the node itself, and its + // own body still reads as a body. + let src = state(&format!("accept sig : Sig when {expr};")); + assert_eq!(only_member(&src).kind, UsageKind::Accept, "{src}"); + let src = state(&format!("accept sig : Sig when {expr} {{ action q; }}")); + let member = only_member(&src); + assert_eq!(member.kind, UsageKind::Accept, "{src}"); + assert!(member.body.is_some(), "{src}"); + } +} + +/// The lookahead stops at the member it is classifying, so a body holding +/// many accept members costs time linear in its size rather than +/// quadratic — including when those members are malformed, which is when +/// a scan looking for a balanced terminator would run away. +/// +/// Measured in tokens read rather than in wall-clock time: the count is +/// exactly the work the scan does, and does not depend on the machine. +/// +/// A member that never closes its brace nests a body per member, so the +/// probe runs on a thread with room for the nesting bound itself — the +/// count it reads is kept per thread, so the parsing has to happen there +/// too. +#[test] +fn accept_lookahead_is_linear_in_the_body_size() { + std::thread::Builder::new() + .stack_size(64 * 1024 * 1024) + .spawn(accept_lookahead_probe) + .unwrap() + .join() + .unwrap(); +} + +fn accept_lookahead_probe() { + fn lookahead_tokens(member: &str, count: usize) -> u64 { + let members = (0..count) + .map(|i| member.replace('#', &i.to_string())) + .collect::>() + .join(" "); + let src = format!("package P {{ action a {{ {members} }} }}"); + sysmlv2_parser::parser::take_accept_lookahead_tokens(); + let _ = parse_source(&src); + sysmlv2_parser::parser::take_accept_lookahead_tokens() + } + + for member in [ + // Well formed, and each shape of unbalanced opener: a member that + // never closes its bracket, its parenthesis, or its brace. + "accept sig# via p { }", + "accept sig# when (x;", + "accept sig# when x[1;", + "accept sig# when { x;", + ] { + let small = lookahead_tokens(member, 1_000); + let large = lookahead_tokens(member, 4_000); + assert!( + large <= small * 5, + "{member:?}: 4000 members read {large} lookahead tokens \ + against {small} for 1000" + ); + } + + // A well-formed member's classification reads its own tokens and no + // more; a malformed one stops at its terminator all the same. + for (member, ceiling) in [ + ("accept sig# via p { }", 8), + ("accept sig# when (x;", 8), + ("accept sig# when x[1;", 8), + ] { + let per_member = lookahead_tokens(member, 1_000) / 1_000; + assert!( + per_member <= ceiling, + "{member:?} read {per_member} lookahead tokens per member" + ); + } +} + +/// Nested `else action { … }` levels are each parsed once: the branch is +/// decided by lookahead instead of by parsing a whole subtree and rolling +/// back, which cost one full re-parse of everything below per level. +#[test] +fn nested_else_action_bodies_parse_in_linear_time() { + const DEPTH: usize = 8; + const INNER_MEMBERS: usize = 3000; + let innermost = (0..INNER_MEMBERS) + .map(|i| format!("part p{i};")) + .collect::>() + .join(" "); + let mut nested = format!("if c {{ }} else action {{ {innermost} }}"); + for _ in 0..DEPTH { + nested = format!("if c {{ }} else action {{ {nested} }}"); + } + let src = format!("package P {{ action a {{ {nested} }} }}"); + let start = std::time::Instant::now(); + let body = package_body(&src); + assert!( + start.elapsed() < std::time::Duration::from_secs(3), + "{DEPTH} nested else-action levels took {:?}", + start.elapsed() + ); + + // The nesting is still what it says: each level is an if-node whose + // else branch is an anonymous action body holding the next one. + let MemberKind::Usage(action) = &body[0].kind else { + panic!("{:?}", body[0].kind) + }; + let mut members = action.body.clone().expect("action body"); + let mut level = 0; + loop { + let MemberKind::Usage(node) = &members[0].kind else { + panic!("{:?}", members[0].kind) + }; + assert_eq!(node.kind, UsageKind::IfNode); + let UsageDetail::IfNode { else_body, .. } = &node.detail else { + panic!() + }; + let else_body = else_body.as_ref().expect("else branch"); + assert_eq!(else_body.kind, UsageKind::Action); + members = else_body.body.clone().expect("else action body"); + level += 1; + if members.len() == INNER_MEMBERS { + break; + } + } + assert_eq!(level, DEPTH + 1); +} + +/// A declared nested if-node after `else` is still recognised through its +/// action head. +#[test] +fn else_action_declaration_before_if_is_a_nested_node() { + let body = package_body("package P { action a { if c { } else action alt if d { } } }"); + let MemberKind::Usage(action) = &body[0].kind else { + panic!() + }; + let members = action.body.as_ref().unwrap(); + let MemberKind::Usage(node) = &members[0].kind else { + panic!() + }; + let UsageDetail::IfNode { else_body, .. } = &node.detail else { + panic!() + }; + let alt = else_body.as_ref().expect("else branch"); + assert_eq!(alt.kind, UsageKind::IfNode); + assert_eq!(alt.declaration.id.name.as_ref().unwrap().value, "alt"); +} + +/// Syntax-tree nodes stay small. Every member of a body, every usage and +/// every expression is stored by value in a `Vec` and moved through the +/// parser's call chain, so one oversized payload — a multiplicity's two +/// expressions, an accept node's payload part — is paid for by every node +/// of that kind in the file and by every stack frame that carries one. +/// Ceilings are for a 64-bit target and leave a little room; a real +/// increase should be a deliberate one. +#[test] +fn syntax_tree_nodes_stay_small() { + use std::mem::size_of; + for (name, size, ceiling) in [ + ("Member", size_of::(), 576), + ("MemberKind", size_of::(), 552), + ("Usage", size_of::(), 544), + ("UsageDetail", size_of::(), 96), + ("Definition", size_of::(), 288), + ("Expr", size_of::(), 80), + ("Multiplicity", size_of::(), 144), + ("FeatureDeclaration", size_of::(), 352), + ("ConnectorEnd", size_of::(), 88), + ("PayloadPart", size_of::(), 120), + ] { + assert!( + size <= ceiling, + "{name} is {size} bytes, over its {ceiling}-byte ceiling" + ); + } +} diff --git a/crates/sysmlv2-parser/tests/prepared_library.rs b/crates/sysmlv2-parser/tests/prepared_library.rs new file mode 100644 index 0000000..dcae2d7 --- /dev/null +++ b/crates/sysmlv2-parser/tests/prepared_library.rs @@ -0,0 +1,352 @@ +//! The prepared path must preserve graph identity, diagnostics and evaluation. +use std::sync::Arc; +use sysmlv2_parser::{ + check, + json::{self, ResolvedModel}, + model::Model, + prepared::PreparedLibrary, +}; +fn diags(model: &Model) -> Vec<(usize, String, String, u32, u32)> { + let mut r = ResolvedModel::build(model); + check::validate_model_with(&mut r, model) + .into_iter() + .chain(check::validate_semantics_with(&mut r, model)) + .map(|(u, d)| { + ( + u, + format!("{:?}", d.severity), + d.message, + d.span.start, + d.span.end, + ) + }) + .collect() +} +fn parity(library: &[(&str, &str)], users: &[(&str, &str)]) { + let mut base = Model::new(); + for (n, s) in library { + base.add_library_source(*n, s); + } + let prepared = base.prepare_library().unwrap(); + let bytes = prepared.to_bytes(42).unwrap(); + let prepared = Arc::new(PreparedLibrary::from_bytes(&bytes, 42).expect("snapshot decodes")); + let bytes = prepared.to_bytes(42).unwrap(); + let mut cold = Model::new(); + for (n, s) in library { + cold.add_library_source(*n, s); + } + let mut warm = Model::new(); + prepared.clone().install(&mut warm).unwrap(); + for (n, s) in users { + cold.add_source(*n, s); + warm.add_source(*n, s); + } + for _ in 0..2 { + assert_eq!( + json::model_to_compact_json(&cold), + json::model_to_compact_json(&warm), + "user graph" + ); + assert_eq!( + json::library_to_compact_json(&cold), + json::library_to_compact_json(&warm), + "library graph" + ); + assert_eq!(diags(&cold), diags(&warm), "diagnostics"); + } + assert_eq!( + prepared.to_bytes(42).unwrap(), + bytes, + "models must not mutate their shared snapshot" + ); +} +#[test] +fn prepared_graph_handles_inheritance_chains_aliases_filters_and_user_completion() { + let lib = [( + "lib.kerml", + "package L { datatype Number; class A { feature x : Number; } class B :> A { feature :>> x; } alias C for B; }", + )]; + for src in [ + "package U { private import L::*; feature a : C; feature x chains a.x; }", + "package U { private import L::*[true]; feature a : B { feature :>> x; } feature b : A; binding a.x = b.x; }", + "package L { class A; } package U { feature a : L::A; }", + "package U { private import Missing::*; feature x : Missing; }", + ] { + parity(&lib, &[("user.kerml", src)]); + } + parity( + &[("lib.kerml", "package L { class A :> Later; }")], + &[( + "user.kerml", + "class Later { feature x; } package U { feature a : L::A; feature y chains a.x; }", + )], + ); + parity( + &[( + "lib.kerml", + "package Other { class X { feature x; } } package L { class A :> X; }", + )], + &[( + "user.kerml", + "private import Other::*; package U { feature a : L::A; feature x chains a.x; }", + )], + ); + parity( + &[], + &[("user.sysml", "package U { part def A; part a : A; }")], + ); + // An unnamed root feature contributes its inferred name as well. + parity( + &[("lib.kerml", "package L { feature f :> x; }")], + &[("user.kerml", "package P { feature x; } feature :>> P::x;")], + ); + // A missing implicit library root can be supplied by the user as well. + parity( + &[("lib.sysml", "package L { part def A; }")], + &[( + "user.sysml", + "package Parts { part def Part { attribute x; } } package U { part a : L::A; attribute y = a.x; }", + )], + ); +} +#[test] +fn prepared_cache_rejects_stale_corrupt_and_truncated_data() { + let mut model = Model::new(); + model.add_library_source("l.sysml", "package L { attribute x = 1.25; }"); + let prepared = model.prepare_library().unwrap(); + let bytes = prepared.to_bytes(19).unwrap(); + assert!(PreparedLibrary::from_bytes(&bytes, 19).is_some()); + assert!(PreparedLibrary::from_bytes(&bytes, 20).is_none()); + for i in (0..bytes.len()).step_by((bytes.len() / 31).max(1)) { + assert!(PreparedLibrary::from_bytes(&bytes[..i], 19).is_none()); + let mut bad = bytes.clone(); + bad[i] ^= 1; + assert!(PreparedLibrary::from_bytes(&bad, 19).is_none()); + } + let mut recording = Model::new(); + prepared.clone().install(&mut recording).unwrap(); + recording.record_library_cache(); + ResolvedModel::build(&recording); + let legacy = recording + .take_recorded_library_cache() + .expect("explicit recording overrides preparation"); + recording.set_library_cache(legacy); + assert!(check::validate_model(&recording).is_empty()); + let mut occupied = Model::new(); + occupied.add_source("user.sysml", "package U;"); + assert!(prepared.clone().install(&mut occupied).is_err()); + assert!(PreparedLibrary::build(&occupied).is_err()); + let mut warm = Model::new(); + prepared.install(&mut warm).unwrap(); + warm.add_library_source("extra.sysml", "package Extra { part def X; }"); + warm.add_source("user.sysml", "package U { part x : Extra::X; }"); + assert!( + check::validate_model(&warm).is_empty(), + "adding libraries invalidates the prepared prefix" + ); +} +/// The snapshot's integrity trailer must be a hash fixed by this crate, +/// not one a toolchain is free to change between releases: a changed hash +/// would reject every snapshot on disk with no version to explain it. +/// Recomputing it here independently pins that. +#[test] +fn prepared_snapshot_trailer_is_a_fixed_hash() { + use sysmlv2_parser::libcache::TOOLKIT_BUILD; + let mut model = Model::new(); + model.add_library_source("l.sysml", "package L { attribute x = 1.25; }"); + let bytes = model.prepare_library().unwrap().to_bytes(19).unwrap(); + // Header: magic, the build identity, a newline, the content key, the + // trailer, then the payload the trailer covers. + let payload_at = bytes + .windows(TOOLKIT_BUILD.len()) + .position(|w| w == TOOLKIT_BUILD.as_bytes()) + .expect("the snapshot names the build that wrote it") + + TOOLKIT_BUILD.len() + + 1 + + 16; + let recorded = u64::from_le_bytes(bytes[payload_at - 8..payload_at].try_into().unwrap()); + // FNV-1a, 64-bit — the hash the resolution cache writes too. + let mut hash: u64 = 0xcbf2_9ce4_8422_2325; + for &byte in &bytes[payload_at..] { + hash ^= u64::from(byte); + hash = hash.wrapping_mul(0x100_0000_01b3); + } + assert_eq!(recorded, hash); +} + +#[test] +fn prepared_official_and_apollo_graphs_and_diagnostics_match_fresh_builds() { + let library = sysmlv2_testkit::library_dir(); + if !library.exists() { + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + let prepared = base.prepare_library().unwrap(); + let bytes = prepared.to_bytes(91).unwrap(); + let prepared = Arc::new( + PreparedLibrary::from_bytes(&bytes, 91).expect("complete standard library decodes"), + ); + for corpus in [ + "spec-refs/SysML-v2-Release/sysml/src", + "spec-refs/apollo-11-sysml-v2", + ] { + let path = sysmlv2_testkit::workspace_root().join(corpus); + if !path.is_dir() { + continue; + } + let mut paths = Vec::new(); + sysmlv2_testkit::collect_files(&path, &mut paths); + paths.sort(); + for reverse in [false, true] { + if reverse { + paths.reverse(); + } + let mut cold = Model::new(); + cold.load_library_dir(&library).unwrap(); + let mut warm = Model::new(); + prepared.clone().install(&mut warm).unwrap(); + for p in &paths { + let source = std::fs::read_to_string(p).unwrap(); + cold.add_source(p.display().to_string(), &source); + warm.add_source(p.display().to_string(), &source); + } + assert_eq!( + json::model_to_compact_json(&cold), + json::model_to_compact_json(&warm), + "{corpus}, reverse={reverse}" + ); + assert_eq!(diags(&cold), diags(&warm), "{corpus}, reverse={reverse}"); + } + } +} + +#[test] +fn prepared_root_level_imports_stay_on_the_prepared_path_for_the_standard_library() { + let library = sysmlv2_testkit::library_dir(); + if !library.exists() { + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + let bytes = base.prepare_library().unwrap().to_bytes(17).unwrap(); + let prepared = Arc::new(PreparedLibrary::from_bytes(&bytes, 17).unwrap()); + for source in [ + "private import ScalarValues::*; package P { attribute x : Real = 1; }", + "package P { attribute x : ScalarValues::Real = 1; } dependency D from P to ScalarValues;", + ] { + let mut cold = Model::new(); + cold.load_library_dir(&library).unwrap(); + cold.add_source("user.sysml", source); + let mut warm = Model::new(); + prepared.clone().install(&mut warm).unwrap(); + warm.add_source("user.sysml", source); + assert_eq!(diags(&cold), diags(&warm), "{source}"); + assert_eq!( + json::model_to_compact_json(&cold), + json::model_to_compact_json(&warm), + "{source}" + ); + // Joint resolution would have reconstructed every library file. + assert_eq!( + warm.loaded_library_unit_count(), + 0, + "{source}: the prepared graph must be reused" + ); + } +} + +#[test] +fn prepared_evaluation_preserves_units_calls_and_redefined_values() { + let library = sysmlv2_testkit::library_dir(); + if !library.exists() { + return; + } + let mut cold = Model::new(); + cold.load_library_dir(&library).unwrap(); + let prepared = PreparedLibrary::build(&cold).unwrap(); + let bytes = prepared.to_bytes(5).unwrap(); + let prepared = Arc::new(PreparedLibrary::from_bytes(&bytes, 5).unwrap()); + let mut warm = Model::new(); + prepared.install(&mut warm).unwrap(); + let source = "package U { + private import ScalarValues::*; private import SI::*; + calc def Twice { in x : Real; return result : Real = x * 2; } + attribute distance = 1 [km] + 500 [m]; attribute answer = Twice(3); + part def A { attribute x : Real = 2; } + part a : A { attribute :>> x = 5; } attribute value = a.x; + }"; + cold.add_source("user.sysml", source); + warm.add_source("user.sysml", source); + let mut a = ResolvedModel::build(&cold); + let mut b = ResolvedModel::build(&warm); + for name in ["U::distance", "U::answer", "U::value"] { + let expected = a.evaluate_qualified(name).unwrap(); + let actual = b.evaluate_qualified(name).unwrap(); + assert_eq!(format!("{expected:?}"), format!("{actual:?}"), "{name}"); + } + let cold_x = a.resolve_qualified("U::A::x").unwrap(); + let warm_x = b.resolve_qualified("U::A::x").unwrap(); + assert_eq!( + format!("{:?}", a.references_to(cold_x)), + format!("{:?}", b.references_to(warm_x)) + ); +} + +#[test] +fn prepared_negative_diagnostics_match_resolution_replay() { + let library = sysmlv2_testkit::library_dir(); + if !library.exists() { + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let bytes = base.prepare_library().unwrap().to_bytes(61).unwrap(); + let prepared = Arc::new(PreparedLibrary::from_bytes(&bytes, 61).unwrap()); + let mut fixtures = Vec::new(); + sysmlv2_testkit::collect_files( + &std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml"), + &mut fixtures, + ); + fixtures.sort(); + assert_eq!(fixtures.len(), 462); + for path in fixtures { + let source = std::fs::read_to_string(&path).unwrap(); + let mut replay = Model::new(); + replay.load_library_dir(&library).unwrap(); + replay.set_library_cache(cache.clone()); + let mut warm = Model::new(); + prepared.clone().install(&mut warm).unwrap(); + replay.add_source(path.display().to_string(), &source); + warm.add_source(path.display().to_string(), &source); + assert_eq!(diags(&replay), diags(&warm), "{}", path.display()); + } +} + +#[test] +fn prepared_connector_featuring_preserves_chain_and_one_hop_accessibility() { + let library = [("lib.sysml", "package L { part def D; }")]; + let declarations = "package P { + part def A { part x : L::D; } + part def B { part y : L::D; } + action def Steps { action firstStep; action lastStep; } + }"; + for connector in [ + "part def C { part a : A; connect a.x to B::y; }", + "part def C { part a : A; part b : B; connect a.x to b.y; }", + "part def C { part a : A; connect a.missing to B::y; }", + "part sys { action run : Steps; succession first run.firstStep then run.lastStep; }", + "part def C { part a : A; }", + ] { + let user = format!("package U {{ private import P::*; {connector} }}"); + for sources in [ + [("defs.sysml", declarations), ("user.sysml", user.as_str())], + [("user.sysml", user.as_str()), ("defs.sysml", declarations)], + ] { + parity(&library, &sources); + } + } +} diff --git a/crates/sysmlv2-parser/tests/query.rs b/crates/sysmlv2-parser/tests/query.rs index 9df4a08..2453c4f 100644 --- a/crates/sysmlv2-parser/tests/query.rs +++ b/crates/sysmlv2-parser/tests/query.rs @@ -227,6 +227,41 @@ fn element_qualified_names() { assert_eq!(r.element_qualified_name(root_pkg).as_deref(), Some("Demo")); } +#[test] +fn qualified_names_include_effective_names_of_redefined_ancestors() { + let mut r = resolved( + "package P { + part def Tank { attribute mass = 1; } + part base { part tank : Tank; part : Tank; part 'fuel tank' : Tank; } + part actual :> base { + part :>> tank { attribute :>> mass = 2; } + part :>> spare; + part :>> 'fuel tank'; + } + ref part :> actual; + part { part child; } + }", + ); + for name in [ + "P::actual::tank", + "P::actual::tank::mass", + "P::actual::spare", + "P::actual::'fuel tank'", + ] { + let element = r.resolve_qualified(name).expect(name); + let id = r.element_id(element); + assert_eq!(r.element_qualified_name(element).as_deref(), Some(name)); + let again = r.resolve_qualified(name).unwrap(); + assert_eq!(r.element_id(again), id); + } + let child = r + .elements_of_metaclass("PartUsage") + .into_iter() + .find(|e| r.element_name(*e) == Some("child")) + .unwrap(); + assert_eq!(r.element_qualified_name(child), None); +} + /// Classification follows semantic-metadata implied specializations: an /// element annotated with a `SemanticMetadata` subtype conforms to the /// metadata's `baseType` value — for annotated *definitions* as well as diff --git a/crates/sysmlv2-parser/tests/refs.rs b/crates/sysmlv2-parser/tests/refs.rs index 15b99b4..cf3305a 100644 --- a/crates/sysmlv2-parser/tests/refs.rs +++ b/crates/sysmlv2-parser/tests/refs.rs @@ -348,7 +348,7 @@ fn owner_chain_reaches(r: &mut ResolvedModel, from: ElementRef, to: ElementRef) #[test] fn provenance_records_owner_and_chain_root() { - // The M29a0 classification scenario: references to `Engine::mass` + // The classification scenario: references to `Engine::mass` // divide into (a) a site internal to the definition body (`margin`'s // value), (b) a site reached through the usage (`engine.mass` — chain // root = the usage), and (c) an outside reference through the @@ -426,3 +426,41 @@ fn provenance_records_owner_and_chain_root() { assert_eq!(usage_sites[0].chain_root, None); assert!(owner_chain_reaches(&mut r, usage_sites[0].owner, total)); } + +#[test] +fn inherited_member_sites_do_not_take_the_base_resolution_walks() { + // Resolving `other` inside `Sub` fills Sub's base cache first, which + // resolves `Thing` through P's import. That walk belongs to the + // `:> Thing` site alone: the redefinition site is reached through + // inheritance, not through the import, and a base cache filled by a + // later lookup (a prepared library rebuilds its caches under the + // user's lookups) must not change what a site records. + let src = "package Lib { part def Thing { part other : Other; } part def Other; } +package P { private import Lib::*; part def Sub :> Thing { part :>> other; } }"; + let mut r = resolved(src); + let import = r + .reference_sites() + .iter() + .find(|s| s.kind == "importedNamespace") + .expect("import site") + .owner; + let thing = r.resolve_qualified("Lib::Thing").expect("resolves"); + let other = r.resolve_qualified("Lib::Thing::other").expect("resolves"); + + let spec = r.references_to(thing); + assert_eq!(spec.len(), 1, "{spec:?}"); + assert_eq!( + spec[0].via_imports, + [(import, sysmlv2_parser::json::AccessMode::Any)], + "the specialization resolved through the import, lexically" + ); + + let redefinition = r.references_to(other); + assert_eq!(redefinition.len(), 1, "{redefinition:?}"); + assert_eq!(redefinition[0].kind, "redefinedFeature"); + assert!( + redefinition[0].via_imports.is_empty(), + "{:?}", + redefinition[0].via_imports + ); +} diff --git a/crates/sysmlv2-parser/tests/roundtrip.rs b/crates/sysmlv2-parser/tests/roundtrip.rs index 25604b0..25bf22b 100644 --- a/crates/sysmlv2-parser/tests/roundtrip.rs +++ b/crates/sysmlv2-parser/tests/roundtrip.rs @@ -7,7 +7,7 @@ #![cfg(feature = "json")] use std::fs; -use sysmlv2_parser::ast::Dialect; +use sysmlv2_parser::ast::{Dialect, MemberKind, UsageDetail, UsageKind}; use sysmlv2_parser::json::to_compact_json; use sysmlv2_parser::lift::from_compact_json; use sysmlv2_parser::parser::{Parse, parse_kerml_source, parse_source}; @@ -73,14 +73,13 @@ fn corpus_json_roundtrip() { /// Full-form leg of the round-trip gate: lifting a model's *full* JSON /// must print exactly what the compact leg prints. The full form /// materializes derived properties (`memberElement`, `memberName`, …) -/// that the lift must ignore — 2026-07-17: view `filter` clauses and +/// that the lift must ignore — view `filter` clauses and /// positional invocation arguments regressed exactly there. /// /// One measured loss is normalized away: associations are `isSufficient` -/// at the model level whatever the text spells (INTEROP.md adjudication, -/// 2026-07-16), so the full form cannot recover a KerML `assoc all` -/// keyword — the lift canonicalizes it off, and the comparison drops it -/// from the reference too. +/// at the model level whatever the text spells (see INTEROP.md), so the +/// full form cannot recover a KerML `assoc all` keyword — the lift +/// canonicalizes it off, and the comparison drops it from the reference too. fn drop_assoc_all(text: &str) -> String { text.replace("assoc all ", "assoc ") .replace("assoc struct all ", "assoc struct ") @@ -544,3 +543,476 @@ fn lift_with_names_keeps_lambda_parameter_references_relative() { "JSON changed across the named lift: {text}" ); } + +/// A payload whose ownership pointers loop (`A` owns `B`, whose membership +/// owns `A` again) is refused instead of returning a partial model; +/// an expression element that nests itself is caught the same way. +#[test] +fn cyclic_ownership_payload_lifts_with_an_error() { + use serde_json::json; + let cyclic = json!([ + {"@id": "root", "@type": "Namespace", "ownedRelationship": [{"@id": "m0"}]}, + {"@id": "m0", "@type": "OwningMembership", "owningRelatedElement": {"@id": "root"}, + "ownedRelatedElement": [{"@id": "a"}]}, + {"@id": "a", "@type": "Package", "declaredName": "A", "owningRelationship": {"@id": "m0"}, + "ownedRelationship": [{"@id": "m1"}]}, + {"@id": "m1", "@type": "OwningMembership", "owningRelatedElement": {"@id": "a"}, + "ownedRelatedElement": [{"@id": "b"}]}, + {"@id": "b", "@type": "Package", "declaredName": "B", "owningRelationship": {"@id": "m1"}, + "ownedRelationship": [{"@id": "m2"}]}, + {"@id": "m2", "@type": "OwningMembership", "owningRelatedElement": {"@id": "b"}, + "ownedRelatedElement": [{"@id": "a"}]}, + ]); + let Err(sysmlv2_parser::lift::LiftError::Incomplete { errors }) = from_compact_json(&cyclic) + else { + panic!("a cycle must refuse the document") + }; + assert!(errors.iter().any(|e| e.contains("cycle")), "{errors:?}"); + + let self_nested = json!([ + {"@id": "root", "@type": "Namespace", "ownedRelationship": [{"@id": "m0"}]}, + {"@id": "m0", "@type": "OwningMembership", "owningRelatedElement": {"@id": "root"}, + "ownedRelatedElement": [{"@id": "x"}]}, + {"@id": "x", "@type": "AttributeUsage", "declaredName": "x", "owningRelationship": {"@id": "m0"}, + "ownedRelationship": [{"@id": "fv"}]}, + {"@id": "fv", "@type": "FeatureValue", "owningRelatedElement": {"@id": "x"}, + "ownedRelatedElement": [{"@id": "e"}]}, + {"@id": "e", "@type": "FeatureReferenceExpression", "owningRelationship": {"@id": "fv"}, + "ownedRelationship": [{"@id": "em"}]}, + {"@id": "em", "@type": "Membership", "owningRelatedElement": {"@id": "e"}, + "ownedRelatedElement": [{"@id": "e"}]}, + ]); + let Err(sysmlv2_parser::lift::LiftError::Incomplete { errors }) = + from_compact_json(&self_nested) + else { + panic!("a cycle must refuse the document") + }; + assert!(errors.iter().any(|e| e.contains("cycle")), "{errors:?}"); +} + +/// Nested packages `depth` levels deep, as compact interchange JSON. +fn nested_packages(depth: usize) -> serde_json::Value { + use serde_json::json; + let mut elements = vec![json!({ + "@id": "root", "@type": "Namespace", "ownedRelationship": [{"@id": "m0"}] + })]; + let mut owner = "root".to_string(); + for i in 0..depth { + let membership = format!("m{i}"); + let package = format!("p{i}"); + let mut element = json!({ + "@id": package, "@type": "Package", "declaredName": format!("P{i}"), + "owningRelationship": {"@id": membership} + }); + if i + 1 < depth { + element["ownedRelationship"] = json!([{"@id": format!("m{}", i + 1)}]); + } + elements.push(json!({ + "@id": membership, "@type": "OwningMembership", + "owningRelatedElement": {"@id": owner}, "ownedRelatedElement": [{"@id": package}] + })); + elements.push(element); + owner = package; + } + serde_json::Value::Array(elements) +} + +/// The names of the nested-package chain a lift produced, outermost +/// first — read without recursion, so the reader never costs more stack +/// than the chain it is checking. +fn package_chain(unit: &sysmlv2_parser::ast::SourceUnit) -> Vec<&str> { + use sysmlv2_parser::ast::{Member, MemberKind, Package}; + fn sole_package(members: &[Member]) -> Option<&Package> { + match members { + [only] => match &only.kind { + MemberKind::Package(package) => Some(package), + _ => None, + }, + _ => None, + } + } + let mut names = Vec::new(); + let mut level = sole_package(&unit.members); + while let Some(package) = level { + names.push(package.id.name.as_ref().map_or("", |n| n.value.as_str())); + level = package.body.as_deref().and_then(sole_package); + } + names +} + +/// Ownership nesting is bounded: a chain far past the limit is refused +/// without exhausting the caller's stack; a chain within the limit lifts +/// completely. +#[test] +fn deep_ownership_chain_lifts_without_overflowing() { + use sysmlv2_parser::lift::MAX_LIFT_DEPTH; + // Each package level costs two lift steps: its membership and the + // package itself. + let levels = MAX_LIFT_DEPTH / 2; + let Err(sysmlv2_parser::lift::LiftError::Incomplete { errors }) = + from_compact_json(&nested_packages(10_000)) + else { + panic!("an over-budget document must not return a partial AST") + }; + assert!( + errors.iter().any(|e| e.contains("deeper than")), + "{errors:?}" + ); + + // A chain that fits lifts completely, and the whole-list name map + // walks it too. + let within = nested_packages(levels - 1); + let lifted = from_compact_json(&within).expect("well-formed"); + assert!(lifted.errors.is_empty(), "{:?}", lifted.errors); + assert_eq!(package_chain(&lifted.unit).len(), levels - 1); + let names = sysmlv2_parser::lift::document_name_map(&within); + assert_eq!( + names.get("p3").map(Vec::len), + Some(4), + "P3 sits four segments below the root" + ); +} + +/// One naming rule, several representations: an unnamed feature is named +/// by the feature it redefines, references, or chains to. The lift reads +/// that rule off payload JSON (for the qualified names a cross-document +/// reference prints), the full form derives it over its own element maps +/// (for `name` and `memberName`), and the id derivation runs it as a +/// fixpoint (for named id segments). Feed the same shapes through all +/// three and they must answer the same. +#[test] +fn the_effective_name_rule_agrees_across_its_implementations() { + let source = "package P { + part def D { attribute mass; attribute count; } + part p : D { + attribute :>> mass = 1; + attribute :>> count = 2; + } + part q : D { + attribute :>> mass = 3; + } + }"; + let compact = to_compact_json(&parse(source, Dialect::Sysml).unit); + let elements = compact.as_array().expect("a flat element array"); + + // The anonymous redefining attributes, by the id the payload gives + // them, with the name each is expected to be findable by. + let anonymous: Vec<(&str, String)> = elements + .iter() + .filter(|e| e["@type"] == "AttributeUsage" && e["declaredName"].as_str().is_none()) + .map(|e| { + let redefined = e["ownedRelationship"] + .as_array() + .expect("owned relationships") + .iter() + .filter_map(|r| elements.iter().find(|x| x["@id"] == r["@id"])) + .find(|r| r["@type"] == "Redefinition") + .expect("a redefinition"); + let target = redefined["redefinedFeature"]["@id"] + .as_str() + .expect("an in-document target"); + let name = elements + .iter() + .find(|x| x["@id"] == target) + .expect("the redefined attribute")["declaredName"] + .as_str() + .expect("a declared name") + .to_string(); + (e["@id"].as_str().expect("an id"), name) + }) + .collect(); + assert_eq!(anonymous.len(), 3, "three anonymous redefiners"); + + // The lift's reading: the last segment of the whole-list name map. + let lifted_names = sysmlv2_parser::lift::document_name_map(&compact); + // The full form's reading: the materialized `name` property. + let full = sysmlv2_parser::full::from_compact_value( + compact.clone(), + &std::collections::HashMap::new(), + true, + ); + let full_elements = full.as_array().expect("a flat element array"); + // The id derivation's reading: the named segment of the path. + let paths = sysmlv2_parser::ids::segment_paths(&compact, &|_| None).expect("well-formed"); + + for (id, expected) in anonymous { + assert_eq!( + lifted_names.get(id).and_then(|segments| segments.last()), + Some(&expected), + "the lift names {id}" + ); + let full_element = full_elements + .iter() + .find(|e| e["@id"] == id) + .expect("the same element in the full form"); + assert_eq!( + full_element["name"].as_str(), + Some(expected.as_str()), + "the full form names {id}" + ); + let index = elements + .iter() + .position(|e| e["@id"] == id) + .expect("payload order"); + let (_, path) = paths[index].as_ref().expect("a reachable element"); + assert_eq!( + path.rsplit('/').next(), + Some(format!("::{expected}").as_str()), + "the id derivation names {id} — {path}" + ); + } +} + +/// Remove the element `id` and everything it owns from a compact-form +/// element array. +fn remove_subtree(arr: &mut Vec, id: &str) { + let mut pending = vec![id.to_string()]; + while let Some(id) = pending.pop() { + let Some(i) = arr.iter().position(|e| e["@id"] == id.as_str()) else { + continue; + }; + let el = arr.remove(i); + for key in ["ownedRelationship", "ownedRelatedElement"] { + if let Some(children) = el[key].as_array() { + pending.extend( + children + .iter() + .filter_map(|c| c["@id"].as_str().map(str::to_owned)), + ); + } + } + } +} + +/// A binding connector with a single end (a partial document: the other +/// end's membership is missing) lifts with an error entry, and prints text +/// that parses: the notation spells a binding's ends as a pair and has no +/// form for one, so the end is left unspelled rather than printed as +/// `bind a;`, which does not parse. +/// +/// What is lost, pinned below so it is not lost silently: the SysML +/// grammar requires the `bind` clause after the `binding` keyword, so +/// nothing in that dialect spells a binding whose ends are not a pair — +/// the binding does not survive, and re-lifting the printed text gives an +/// ordinary usage rather than a connector. What does survive is the +/// member, as its declaration alone, so the name, the short name and the +/// typing come through; the end comes with it, spelled as an `end ::> …;` +/// body member; and a connector with nothing declared at all prints `ref` +/// rather than a bare terminator. +#[test] +fn one_ended_binding_keeps_the_member_it_cannot_spell() { + let src = "package P { part def B; part a; part b; binding bd : B bind a = b; }"; + let text = print_one_ended_binding(src); + let member = text + .lines() + .map(str::trim) + .find(|l| l.contains("bd")) + .unwrap_or_else(|| panic!("{text}")); + assert!(member.starts_with(" bd : "), "{text}"); + assert!( + !member.contains("binding") && !member.contains("bind "), + "{text}" + ); + let reparsed = parse_source(&text); + assert!( + reparsed.diagnostics.is_empty(), + "{text}: {:#?}", + reparsed.diagnostics + ); + let MemberKind::Package(p) = &reparsed.unit.members[0].kind else { + panic!("{:?}", reparsed.unit.members[0].kind) + }; + let kept = p + .body + .as_ref() + .unwrap() + .iter() + .find_map(|m| match &m.kind { + MemberKind::Usage(u) + if u.declaration.id.name.as_ref().map(|n| n.value.as_str()) == Some("bd") => + { + Some(u) + } + _ => None, + }) + .expect("the member survives"); + assert_eq!( + kept.kind, + UsageKind::Default, + "the binding is not spelled, the member is" + ); + assert_eq!(end_members(kept), 1, "the end survives: {text}"); + + // With nothing declared there is no head, and a member whose whole + // text is a body does not parse, so the keyword-less usage spells + // itself out — indented where it belongs, with its end kept. + let text = print_one_ended_binding("package P { part a; part b; bind a = b; part z; }"); + assert!(text.contains("\n ref {\n"), "{text}"); + let reparsed = parse_source(&text); + assert!( + reparsed.diagnostics.is_empty(), + "{text}: {:#?}", + reparsed.diagnostics + ); + let MemberKind::Package(p) = &reparsed.unit.members[0].kind else { + panic!("{:?}", reparsed.unit.members[0].kind) + }; + let kept = p + .body + .as_ref() + .unwrap() + .iter() + .find_map(|m| match &m.kind { + MemberKind::Usage(u) if u.kind == UsageKind::Ref => Some(u), + _ => None, + }) + .expect("the member survives"); + assert_eq!(end_members(kept), 1, "the end survives: {text}"); +} + +/// How many of a usage's body members are ends. +fn end_members(u: &sysmlv2_parser::ast::Usage) -> usize { + u.body + .iter() + .flatten() + .filter(|m| matches!(&m.kind, MemberKind::Usage(e) if e.prefix.is_end)) + .count() +} + +/// Lift `src`, drop one of its binding's two ends, and print what is left. +fn print_one_ended_binding(src: &str) -> String { + let mut json = to_compact_json(&parse_source(src).unit); + let arr = json.as_array_mut().unwrap(); + let types: std::collections::HashMap = arr + .iter() + .map(|e| { + ( + e["@id"].as_str().unwrap().to_owned(), + e["@type"].as_str().unwrap().to_owned(), + ) + }) + .collect(); + let binding = arr + .iter() + .position(|e| e["@type"] == "BindingConnectorAsUsage") + .expect("binding element"); + let rels = arr[binding]["ownedRelationship"].as_array_mut().unwrap(); + let ends: Vec = rels + .iter() + .filter_map(|r| r["@id"].as_str()) + .filter(|id| types[*id] == "EndFeatureMembership") + .map(str::to_owned) + .collect(); + assert_eq!(ends.len(), 2, "{types:#?}"); + let dropped = ends[1].clone(); + rels.retain(|r| r["@id"] != dropped.as_str()); + remove_subtree(arr, &dropped); + + let lifted = from_compact_json(&json).unwrap(); + assert!( + lifted + .errors + .iter() + .any(|e| e.contains("binding connector") && e.contains("1 end(s)")), + "{:?}", + lifted.errors + ); + let text = print_source(&lifted.unit); + // The `bind` clause, wherever it sits: a declared binding spells the + // keyword and the declaration before it. + let bind_line = |text: &str| { + text.lines() + .map(str::trim) + .find(|l| l.starts_with("bind ") || l.contains(" bind ")) + .map(str::to_owned) + }; + assert!(bind_line(&text).is_none(), "{text}"); + // The one-ended usage is no longer a binding detail: the invariant + // that a binding detail has two ends holds for lifted trees. + let MemberKind::Package(p) = &lifted.unit.members[0].kind else { + panic!("{:?}", lifted.unit.members[0].kind) + }; + let usage = p + .body + .as_ref() + .unwrap() + .iter() + .find_map(|m| match &m.kind { + MemberKind::Usage(u) if u.kind == UsageKind::Binding => Some(u), + _ => None, + }) + .expect("binding usage"); + assert!(matches!(&usage.detail, UsageDetail::Connector { ends } if ends.len() == 1)); + // Lifting the intact document still yields the two-ended binding. + let intact = from_compact_json(&to_compact_json(&parse_source(src).unit)).unwrap(); + assert!(intact.errors.is_empty(), "{:?}", intact.errors); + let intact_text = print_source(&intact.unit); + let line = bind_line(&intact_text).unwrap_or_else(|| panic!("{intact_text}")); + assert!( + line.contains(" = ") && line.ends_with("b;"), + "{intact_text}" + ); + text +} + +/// Long expressions use the parser's expression budget independently of +/// structural nesting. Compact and full form must retain every operand. +#[test] +fn expression_budget_roundtrips_without_changing_operands() { + sysmlv2_parser::parser::on_parsing_stack( + "expression-roundtrip", + |e| panic!("cannot reserve parsing stack: {e}"), + || { + for operators in [399, sysmlv2_parser::parser::MAX_EXPR_OPERATORS as usize] { + let expression = vec!["1"; operators + 1].join(" + "); + let source = format!("attribute a = {expression};\n"); + let parsed = parse_source(&source); + assert!(parsed.diagnostics.is_empty(), "{:?}", parsed.diagnostics); + let compact = to_compact_json(&parsed.unit); + let full = sysmlv2_parser::full::to_full_json(&parsed.unit); + assert_eq!( + compact.as_array().unwrap().len(), + full.as_array().unwrap().len() + ); + for json in [&compact, &full] { + let lifted = from_compact_json(json).unwrap_or_else(|e| panic!("{e}")); + assert!(lifted.errors.is_empty(), "{:?}", lifted.errors); + let reparsed = parse_source(&print_source(&lifted.unit)); + assert!( + reparsed.diagnostics.is_empty(), + "{:?}", + reparsed.diagnostics + ); + assert_eq!(to_compact_json(&reparsed.unit), compact); + } + } + }, + ); +} + +/// Full-form enrichment retains owned elements even when no source model +/// can represent them. The array-level fallback must not delete a payload. +#[test] +fn full_form_preserves_elements_the_lifter_cannot_reconstruct() { + let parsed = parse_source("attribute a = 1 + 2;"); + let mut compact = to_compact_json(&parsed.unit); + for element in compact.as_array_mut().unwrap() { + if element["@type"] == "LiteralInteger" && element["value"] == 1 { + element["@type"] = "Expression".into(); + element["declaredName"] = "foreignExpression".into(); + element.as_object_mut().unwrap().remove("value"); + } + } + let full = sysmlv2_parser::full::from_compact_value(compact.clone(), &Default::default(), true); + for element in compact.as_array().unwrap() { + let output = full + .as_array() + .unwrap() + .iter() + .find(|e| e["@id"] == element["@id"]) + .expect("every input element survives full-form enrichment"); + assert_eq!(output["@type"], element["@type"]); + assert_eq!(output["declaredName"], element["declaredName"]); + assert_eq!(output["ownedRelationship"], element["ownedRelationship"]); + } +} diff --git a/crates/sysmlv2-parser/tests/spelling.rs b/crates/sysmlv2-parser/tests/spelling.rs new file mode 100644 index 0000000..3c3d5c4 --- /dev/null +++ b/crates/sysmlv2-parser/tests/spelling.rs @@ -0,0 +1,149 @@ +//! Reserved words used as names. The model's qualified name follows the +//! specification's `escapedName` derivation (KerML 8.3.2.1: a name with +//! the *form* of a basic name is returned as-is), which the pilot +//! implementation applies literally and which the normative library ids +//! hash — `ControlFunctions::if`, not `ControlFunctions::'if'`. That +//! spelling is a model property, not parseable text: the textual +//! notation refuses a bare reserved word (KerML 8.2.2.6), so reference +//! text quotes it. These gates pin both sides. + +use sysmlv2_parser::ids::derive_ids; +use sysmlv2_parser::json::{ResolvedModel, library_element_name_map, model_to_compact_json}; +use sysmlv2_parser::model::Model; + +/// Every declared name is a SysML reserved word (`as` is reserved in +/// both dialects, `part`/`action`/`view` in SysML only). +const RESERVED: &str = "package 'part' {\n \ + part def 'action';\n \ + part 'view' : 'action';\n \ + part 'if' : 'action' {\n attribute 'as' = 1;\n }\n}\n"; + +fn model(src: &str) -> Model { + let mut model = Model::new(); + let unit = model.add_source("t.sysml", src); + assert!( + unit.diagnostics.is_empty(), + "test source must parse cleanly: {:?}", + unit.diagnostics[0] + ); + model +} + +#[test] +fn qualified_names_keep_reserved_words_bare_like_the_pilot() { + let mut r = ResolvedModel::build(&model(RESERVED)); + let view = r + .resolve_qualified("'part'::'view'") + .expect("quoted lookup"); + assert_eq!( + r.element_qualified_name(view).as_deref(), + Some("part::view") + ); + // Lookup accepts either spelling of a canonical name. + assert_eq!(r.resolve_qualified("part::view"), Some(view)); + let as_ = r.resolve_qualified("part::if::as").expect("bare lookup"); + assert_eq!( + r.element_qualified_name(as_).as_deref(), + Some("part::if::as") + ); +} + +#[test] +fn reference_spelling_quotes_reserved_words() { + let mut r = ResolvedModel::build(&model(RESERVED)); + let view = r.resolve_qualified("part::view").unwrap(); + assert_eq!( + r.element_reference_spelling(view).as_deref(), + Some("'part'::'view'") + ); + let as_ = r.resolve_qualified("part::if::as").unwrap(); + assert_eq!( + r.element_reference_spelling(as_).as_deref(), + Some("'part'::'if'::'as'") + ); + // Anonymous elements have neither. + let anon = r + .user_elements() + .find(|&e| r.element_type(e) == "FeatureValue") + .expect("the value's owning membership"); + assert_eq!(r.element_qualified_name(anon), None); + assert_eq!(r.element_reference_spelling(anon), None); +} + +/// Graph-derived ids (IDS.md) hash `escape_name` segments — the bare +/// reserved word — and must not move with the reference spelling. The +/// constants were computed before reference spelling existed. +#[test] +fn graph_derived_ids_are_unchanged_by_reference_spelling() { + let model = model(RESERVED); + let mut r = ResolvedModel::build(&model); + let pinned = [ + ("part::view", "effad461-6a16-542b-b395-69f9df3dba79"), + ("part::if", "5eac2530-a9a9-5f44-a399-4f00704747b3"), + ("part::if::as", "7ac80c17-5317-52bb-bb5d-70abfcfbc4f9"), + ]; + for (qn, id) in pinned { + let e = r.resolve_qualified(qn).unwrap(); + assert_eq!(r.element_id(e).to_string(), id, "{qn}"); + } + // The value-side derivation agrees with the builder's assignment. + let compact = model_to_compact_json(&model); + let derived = derive_ids(&compact, &|s| panic!("unexpected external {s}")).unwrap(); + let elements = compact.as_array().unwrap(); + let mut checked = 0; + for (e, d) in elements.iter().zip(derived) { + if let Some(d) = d { + assert_eq!(e["@id"].as_str().unwrap(), d.to_string()); + checked += 1; + } + } + assert!(checked >= 8, "{checked} derived ids"); +} + +/// Normative library ids (KerML 9.1) hash the bare spelling: these are +/// the `elementId`s the pilot implementation publishes in its XMI for +/// three reserved-word-named library elements. +#[test] +fn library_ids_hash_the_bare_reserved_word() { + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .expect("library"); + // Elements only: the map with memberships holds a second entry per + // member (`…/owningMembership`) under the same segments. + let names = library_element_name_map(&model); + let id_of = |segments: &[&str]| -> Option { + names + .iter() + .find(|(_, s)| s.iter().map(String::as_str).eq(segments.iter().copied())) + .map(|(id, _)| id.clone()) + }; + assert_eq!( + id_of(&["ControlFunctions", "if"]).as_deref(), + Some("396c01c4-4dc9-5cf6-8e62-742903a68137") + ); + assert_eq!( + id_of(&["BaseFunctions", "all"]).as_deref(), + Some("f53a4d1a-b2da-5806-af64-2877e7bc4014") + ); + assert_eq!( + id_of(&["SysML", "Systems", "ViewDefinition", "view"]).as_deref(), + Some("8d771b7d-7b73-55dc-9a62-d5236a482081") + ); + let mut r = ResolvedModel::build(&model); + let e = r + .resolve_qualified("ControlFunctions::'if'") + .expect("library function"); + assert_eq!( + r.element_qualified_name(e).as_deref(), + Some("ControlFunctions::if") + ); + assert_eq!( + r.element_reference_spelling(e).as_deref(), + Some("ControlFunctions::'if'") + ); + assert_eq!( + r.element_id(e).to_string(), + "396c01c4-4dc9-5cf6-8e62-742903a68137" + ); +} diff --git a/crates/sysmlv2-parser/tests/static_rules.rs b/crates/sysmlv2-parser/tests/static_rules.rs new file mode 100644 index 0000000..3be2a78 --- /dev/null +++ b/crates/sysmlv2-parser/tests/static_rules.rs @@ -0,0 +1,790 @@ +//! Intended-rule regressions: a diagnostic elsewhere in a negative fixture +//! cannot satisfy this gate. Every rejection has a legal nearby model. +use std::{fs, path::Path}; +use sysmlv2_parser::{check, json::ResolvedModel, model::Model}; + +#[test] +fn structural_rules_have_legal_counterparts() { + let cases = [ + ( + "validateTriggerInvocationActionWhenArgument.sysml", + "level : Integer", + "level : Boolean", + ), + ( + "validateTriggerInvocationActionAtArgument.sysml", + "delay : DurationValue", + "delay : Time::TimeInstantValue", + ), + ( + "validateTriggerInvocationActionAfterArgument.sysml", + "after 5", + "after 5 [SI::s]", + ), + ( + "validateTransitionUsageTriggerActions.sysml", + "entry action init", + "state init", + ), + ( + "validateTransitionUsageSuccession.sysml", + "part p : PD", + "state p", + ), + ( + "validateTransitionFeatureMembershipGuardExpression.sysml", + "if \"yes\"", + "if true", + ), + ("validateSendActionUsageReceiver.sysml", "to p", "via p"), + ( + "validateSendActionUsagePayloadArgument.sysml", + "send to d", + "send new D() to d", + ), + ( + "validateOperatorExpressionCastConformance.kerml", + "ScalarValues::String", + "ScalarValues::Integer", + ), + ( + "validateMergeNodeOutgoingSuccessions.sysml", + "first m then d;", + "", + ), + ( + "validateMergeNodeIncomingSuccessions.sysml", + "first [1] a", + "first [0..1] a", + ), + ( + "validateJoinNodeOutgoingSuccessions.sysml", + "first j then d;", + "", + ), + ( + "validateForkNodeIncomingSuccessions.sysml", + "first b then f;", + "", + ), + ( + "validateFeatureChainExpressionFeatureConformance.kerml", + "class N", + "feature N", + ), + ( + "validateElementFilterMembershipIsModelLevelEvaluable.sysml", + "Sum(1) == 1", + "1 == 1", + ), + ( + "validateElementFilterMembershipIsBoolean.kerml", + "filter 1", + "filter true", + ), + ( + "validateDecisionNodeOutgoingSuccessions.sysml", + "then [1] b", + "then [0..1] b", + ), + ( + "validateDecisionNodeIncomingSuccessions.sysml", + "first b then d;", + "", + ), + ( + "validateControlNodeOutgoingSuccessions.sysml", + "[0..1] j", + "[1] j", + ), + ( + "validateControlNodeIncomingSuccessions.sysml", + "[0..1] f", + "[1] f", + ), + ( + "validateAssignmentActionUsageReferentIsTimeVarying.sysml", + "attribute def K", + "part def K", + ), + ( + "validateAssignmentActionUsageReferent.sysml", + "part def D; action def A {", + "action def A { attribute D : ScalarValues::Integer;", + ), + ( + "validateSubsettingFeaturingTypes.kerml", + "class B {", + "class B specializes A {", + ), + ( + "validateSpecializationSpecificNotConjugated.subset.kerml", + "feature g ~ f", + "feature g : A", + ), + ( + "validateSpecializationSpecificNotConjugated.kerml", + "class B ~ A", + "class B", + ), + ( + "validateFlowEndImplicitSubsetting.sysml", + "a::o to b::i", + "a.o to b.i", + ), + ( + "validateFlowEndImplicitSubsetting.kerml", + "a::o to b::i", + "a.o to b.i", + ), + ( + "validateFlowEndSubsetting.kerml", + "A::o to B::i", + "a.o to b.i", + ), + ( + "validateFeatureHasType.kerml", + "class D", + "feature D : ScalarValues::Integer", + ), + ("validateFeatureCrossFeatureType.kerml", "bx : X", "bx : A"), + ( + "validateFeatureChainingFeatureConformance.kerml", + "class A {", + "class A specializes B {", + ), + ( + "validateCrossSubsettingCrossingFeature.kerml", + "crosses p", + "", + ), + ( + "validateConnectorRelatedFeatures.sysml", + "connection {", + "abstract connection {", + ), + ( + "validateClassifierDefaultSupertype.kerml", + "class D", + "struct D", + ), + ( + "validateBindingConnectorTypeConformance.subject.sysml", + "subject n : ID", + "subject n : PD", + ), + ( + "validateBindingConnectorTypeConformance.satisfy.sysml", + "item i : ID", + "item i : PD", + ), + ( + "validateBindingConnectorTypeConformance.result.kerml", + "return r : D", + "return r : C", + ), + ( + "validateBindingConnectorTypeConformance.kerml", + "ScalarValues::String", + "ScalarValues::Integer", + ), + ( + "validateBindingConnectorIsBinary.kerml", + "end feature e references z;", + "", + ), + ( + "validateAssociationBinarySpecialization.kerml", + "end c : C;", + "", + ), + ("validateFeatureValueOverriding.kerml", "= 1", "default = 1"), + ("validateFeatureValueOverriding.sysml", "= 1", "default = 1"), + ( + "validateFeatureEndFeatureMultiplicity.kerml", + "[0..*]", + "[1]", + ), + ("validateMetadataFeatureBody.kerml", "z = 1", "x = 1"), + ( + "validateMetadataFeatureAnnotatedElement.kerml", + "KerML::Feature", + "KerML::Class", + ), + ( + "validateOperatorExpressionBracketOperator.kerml", + "xs[1]", + "xs#(1)", + ), + ( + "validatePortDefinitionOwnedUsagesNotComposite.sysml", + "part p : D", + "ref part p : D", + ), + ( + "validatePortUsageNestedUsagesNotComposite.sysml", + "part x : D", + "ref part x : D", + ), + ( + "validatePortUsageIsReference.sysml", + "variant port a", + "variant ref port a", + ), + ( + "validateViewDefinitionOnlyOnvViewRendering.sysml", + "render rendering r2 : R;", + "", + ), + ( + "validateViewUsageOnlyOneRendering.sysml", + "render rendering r2 : R;", + "", + ), + ("validateInterfaceDefinitionEnd.sysml", "part", "port"), + ( + "validateInterfaceUsageEnd.sysml", + "end part ::> fuel", + "end port ::> inPort", + ), + ( + "validateRequirementVerificationMembershipOwningType.sysml", + "requirement def Q { verify requirement r : R; }", + "verification def V { objective Q { verify requirement r : R; } }", + ), + ( + "validateConstructorExpressionNoDuplicateFeatureRedefinition.kerml", + "x = t, x = t", + "x = t", + ), + ( + "validateInvocationExpressionInstantiatedType.kerml", + "class A;", + "function A;", + ), + ( + "validateInstantiationExpressionInstantiatedType.kerml", + "package Q;", + "class Q;", + ), + ( + "validateFeatureReferenceExpressionReferentIsFeature.kerml", + "= A", + "= true", + ), + ("validateOperatorExpressionQuantity.sysml", "[3]", "[SI::m]"), + ( + "validateBehaviorSpecialization.kerml", + "struct S;", + "behavior S;", + ), + ( + "validateClassSpecialization.kerml", + "datatype D;", + "class D;", + ), + ( + "validateDataTypeSpecialization.kerml", + "class C;", + "datatype C;", + ), + ( + "validateStructureSpecialization.kerml", + "behavior B;", + "struct B;", + ), + ( + "validateOwnedUnioningNotOne.kerml", + "unions A", + "unions A, B", + ), + ( + "validateOwnedIntersectingNotOne.kerml", + "intersects A", + "intersects A, B", + ), + ( + "validateOwnedDifferencingNotOne.kerml", + "differences A", + "differences A, B", + ), + ( + "validateTypeUnioningTypesNotSelf.kerml", + "unions D, A", + "unions A, B", + ), + ( + "validateTypeIntersectingTypesNotSelf.kerml", + "intersects D, A", + "intersects A, B", + ), + ( + "validateTypeDifferencingTypesNotSelf.kerml", + "differences D, A", + "differences A, B", + ), + ("validateFeatureIsVariable.kerml", "datatype D", "class D"), + ( + "validateFeaturePortionNotVariable.kerml", + "portion var", + "portion", + ), + ( + "validateFeatureValueIsInitial.kerml", + "feature f", + "var feature f", + ), + ( + "validateFeatureConstantIsVariable.sysml", + "attribute def", + "part def", + ), + ( + "validateOccurrenceUsageIndividualDefinition.sysml", + ": I1, I2", + ": I1", + ), + ( + "validateOccurrenceUsageIndividualUsage.sysml", + "part def D", + "individual part def D", + ), + ( + "validateOccurrenceUsageIsPortion.sysml", + "snapshot part", + "part", + ), + ( + "validatePerformActionUsageReference.sysml", + "part d : D", + "action d", + ), + ( + "validateExhibitStateUsageReference.sysml", + "action a : Act", + "state a", + ), + ( + "validateIncludeUseCaseUsageReference.sysml", + "part d : D", + "use case d", + ), + ( + "validateSatisfyRequirementUsageReference.sysml", + "part x : D", + "requirement x", + ), + ( + "validateAssertConstraintUsageReference.sysml", + "part x : D", + "constraint x", + ), + ( + "validateEventOccurrenceUsageReferent.sysml", + "attribute a : ScalarValues::Real", + "part a", + ), + ( + "validateLibraryPackageNotStandard.kerml", + "standard library", + "library", + ), + ( + "validateMetadataFeatureMetadataNotAbstract.kerml", + "abstract metaclass", + "metaclass", + ), + ( + "validateFeatureOwnedReferenceSubsetting.kerml", + "references a references b", + "references a", + ), + ( + "validateFeatureOwnedCrossSubsetting.kerml", + "crosses a.x crosses a.y", + "crosses a.x", + ), + ( + "validateFeatureChainingFeatureNotOne.kerml", + "chains a;", + "chains a.b;", + ), + ( + "validateFeatureChainingFeaturesNotSelf.kerml", + "chains a.b", + "chains a.a", + ), + ( + "validateFunctionResultExpressionMembership.kerml", + "specializes F1, F2", + "specializes F1", + ), + ( + "validateExpressionResultExpressionMembership.kerml", + ": F1, F2", + ": F1", + ), + ( + "validateFunctionResultParameterMembership.kerml", + "return r2 : ScalarValues::Integer;", + "", + ), + ( + "validateExpressionResultParameterMembership.kerml", + "return r2 : ScalarValues::Integer;", + "", + ), + ( + "validateTypeOwnedMultiplicity.kerml", + "multiplicity m2 [2];", + "", + ), + ( + "validateStateDefinitionSubactionKind.sysml", + "entry; do; exit; entry;", + "entry; do; exit;", + ), + ( + "validateStateUsageSubactionKind.sysml", + "entry; entry;", + "entry;", + ), + ( + "validateStateDefinitionParallelSubactions.sysml", + "parallel", + "", + ), + ("validateStateUsageParallelSubactions.sysml", "parallel", ""), + ( + "validateControlNodeOwningType.sysml", + "constraint def C", + "action def C", + ), + ( + "validateRedefinitionDirectionConformance.kerml", + "out feature y", + "in feature y", + ), + ( + "validateRedefinitionEndConformance.kerml", + "feature c redefines", + "end feature c redefines", + ), + ( + "validateRedefinitionFeaturingTypes.kerml", + "feature y redefines x;", + "class C { feature y redefines x; }", + ), + ( + "validateSubsettingConstantConformance.kerml", + "var feature b", + "const feature b", + ), + ( + "validateSubsettingUniquenessConformance.kerml", + " nonunique", + "", + ), + ("validateAssociationEndTypes.kerml", "a : A, B", "a : A"), + ( + "validateAssociationRelatedTypes.kerml", + "end a : T;", + "end a : T; end b : T;", + ), + ]; + let library = sysmlv2_testkit::library_dir(); + assert!(library.is_dir()); + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml/probes"); + let contracts: serde_json::Value = + serde_json::from_str(include_str!("fixtures/opensysml/static-contracts.json")).unwrap(); + let contracts = contracts["contracts"].as_array().unwrap(); + assert_eq!(contracts.len(), cases.len()); + let mut failures = Vec::new(); + for (file, from, to) in cases { + let contract = contracts + .iter() + .find(|c| c["fixture"] == file) + .expect("registered rule contract"); + let source = fs::read_to_string(root.join(file)).unwrap(); + assert!(source.contains(from), "{file}: missing mutation {from}"); + let rule = file.split('.').next().unwrap(); + let tag = format!("[{rule}]"); + for (negative, source) in [(true, source.clone()), (false, source.replace(from, to))] { + let source = if !negative + && file == "validateTransitionFeatureMembershipGuardExpression.sysml" + { + source.replace("if 1 then", "if true then") + } else { + source + }; + let source = if !negative && file == "validateFeatureCrossFeatureType.kerml" { + source.replace("ax : A", "ax : B") + } else { + source + }; + // The set-operation legal neighbors need a second distinct operand. + let source = if !negative && file.contains("TypesNotSelf") + || !negative && file.starts_with("validateOwned") + { + source.replace("class A;", "class A; class B;") + } else { + source + }; + let mut model = Model::new(); + model.load_library_dir(&library).unwrap(); + model.set_library_cache(cache.clone()); + let unit = model.add_source(file, &source); + assert!( + unit.diagnostics.is_empty(), + "{file}: {:?}", + unit.diagnostics + ); + let mut r = ResolvedModel::build(&model); + let diagnostics = check::validate_semantics_with(&mut r, &model); + if negative && !diagnostics.iter().any(|(_, d)| d.message.contains(&tag)) { + failures.push(format!("{file}: missing intended rule: {diagnostics:?}")); + } + if negative { + for (_, d) in diagnostics.iter().filter(|(_, d)| d.message.contains(&tag)) { + assert_eq!( + format!("{:?}", d.severity), + contract["severity"].as_str().unwrap(), + "{file}: diagnostic category" + ); + assert!( + d.span.start < d.span.end && d.span.end <= source.len() as u32, + "{file}: invalid diagnostic span: {d:?}" + ); + assert!( + d.span.start as usize >= source.find("package").unwrap_or(0), + "{file}: diagnostic points into fixture comments: {d:?}" + ); + } + } + let mut diagnostics = diagnostics; + if !negative { + diagnostics.extend(check::validate_model_with(&mut r, &model)); + } + if !negative && !diagnostics.is_empty() { + failures.push(format!("{file}: legal neighbor rejected: {diagnostics:?}")); + } + } + } + assert!(failures.is_empty(), "{}", failures.join("\n")); +} + +#[test] +fn chains_and_static_contracts_preserve_edges_across_replay_and_file_order() { + use sysmlv2_parser::json::model_to_compact_json; + let types = "package Types { class A { feature b : ScalarValues::Integer = 1; } }"; + let uses = "package Uses { + feature a : Types::A; feature b : ScalarValues::Boolean; + feature c chains a.b; + feature incomplete chains a.missing; + feature text : ScalarValues::String; + binding incomplete = text; + class D specializes Types::A { feature redefines b = 2; } + }"; + let mut baseline = None; + for reverse in [false, true] { + let build = |cache| { + let mut m = Model::new(); + m.load_library_dir(&sysmlv2_testkit::library_dir()).unwrap(); + if let Some(cache) = cache { + m.set_library_cache(cache); + } else { + m.record_library_cache(); + } + let files = if reverse { + [("uses.kerml", uses), ("types.kerml", types)] + } else { + [("types.kerml", types), ("uses.kerml", uses)] + }; + for (name, src) in files { + assert!(m.add_source(name, src).diagnostics.is_empty()); + } + m + }; + let cold = build(None); + let mut r = ResolvedModel::build(&cold); + let diags = check::validate_semantics_with(&mut r, &cold); + assert_eq!(diags.len(), 1, "{diags:?}"); + assert!( + diags[0] + .1 + .message + .contains("[validateFeatureValueOverriding]") + ); + let diagnostics: Vec<_> = diags + .iter() + .map(|(u, d)| (cold.units()[*u].name.clone(), d.span, d.message.clone())) + .collect(); + if let Some(baseline) = &baseline { + assert_eq!(baseline, &diagnostics); + } else { + baseline = Some(diagnostics.clone()); + } + let cache = cold.take_recorded_library_cache().unwrap(); + let warm = build(Some(cache)); + let mut r = ResolvedModel::build(&warm); + let warm_diags: Vec<_> = check::validate_semantics_with(&mut r, &warm) + .iter() + .map(|(u, d)| (warm.units()[*u].name.clone(), d.span, d.message.clone())) + .collect(); + assert_eq!(diagnostics, warm_diags); + let graph = model_to_compact_json(&cold); + assert_eq!(graph, model_to_compact_json(&warm)); + let elements = graph.as_array().unwrap(); + let named = |name: &str, ty: &str| { + elements + .iter() + .find(|e| e["declaredName"] == name && e["@type"] == ty) + .unwrap() + }; + let a_type = named("A", "Class"); + let member_rel = &a_type["ownedRelationship"].as_array().unwrap()[0]["@id"]; + let nested_b = elements + .iter() + .find(|e| e["declaredName"] == "b" && e["owningRelationship"]["@id"] == *member_rel) + .unwrap(); + let c = named("c", "Feature"); + let rel_id = &c["ownedRelationship"].as_array().unwrap()[1]["@id"]; + let link = elements.iter().find(|e| e["@id"] == *rel_id).unwrap(); + assert_eq!( + link["chainingFeature"]["@id"], nested_b["@id"], + "chain member captured the lexical Boolean feature" + ); + } +} + +#[test] +fn metadata_values_and_nested_members_require_model_level_contracts() { + let sources = [ + ( + "package P { metaclass M { feature x : ScalarValues::Integer; } + class C { feature runtime : ScalarValues::Integer; @M { x = runtime; } } }", + Some("validateMetadataFeatureBody"), + ), + ( + "package P { metaclass M { feature x { feature y : ScalarValues::Integer; } } + class C { @M { x { z = 1; } } } }", + Some("validateMetadataFeatureBody"), + ), + ( + "package P { metaclass M { feature x { feature y : ScalarValues::Integer; } } + class C { @M { x { y = 1; } } } }", + None, + ), + ("package P { feature x; feature y; binding x = y; }", None), + ( + "package P { class A; feature x : A; feature y : Missing; binding x = y; }", + None, + ), + ]; + for (source, expected) in sources { + let mut model = Model::new(); + model + .load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + assert!( + model + .add_source("contracts.kerml", source) + .diagnostics + .is_empty() + ); + let diags = check::validate_semantics(&model); + if let Some(rule) = expected { + assert!( + diags.iter().any(|(_, d)| d.message.contains(rule)), + "{source}: {diags:?}" + ); + } else { + assert!(diags.is_empty(), "{source}: {diags:?}"); + } + } +} + +#[test] +fn additional_negative_contracts_have_legal_counterparts() { + let contracts: serde_json::Value = + serde_json::from_str(include_str!("fixtures/opensysml/negative-contracts.json")).unwrap(); + let library = sysmlv2_testkit::library_dir(); + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let root = Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml"); + let mut failures = Vec::new(); + for c in contracts["contracts"].as_array().unwrap() { + let name = c["fixture"].as_str().unwrap(); + let source = fs::read_to_string(root.join(name)).unwrap(); + let tag = format!("[{}]", c["rule"].as_str().unwrap()); + let from = c["from"].as_str().unwrap(); + assert!(source.contains(from)); + let mut legal = source.replace(from, c["to"].as_str().unwrap()); + if let Some(from) = c["extra_from"].as_str() { + legal = legal.replace(from, c["extra_to"].as_str().unwrap()); + } + for (negative, source) in [(true, source), (false, legal)] { + let mut m = Model::new(); + m.load_library_dir(&library).unwrap(); + m.set_library_cache(cache.clone()); + let unit = m.add_source(name, &source); + assert!( + unit.diagnostics.is_empty(), + "{name}: {:?}", + unit.diagnostics + ); + let mut r = ResolvedModel::build(&m); + let mut diags = check::validate_semantics_with(&mut r, &m); + if c["verdict"] == "accepted" { + if !diags.is_empty() { + failures.push(format!( + "{name}: accepted enum-restriction model: {diags:?}" + )); + } + } else if negative { + if !diags.iter().any(|(_, d)| { + d.message.contains(&tag) + && format!("{:?}", d.severity) == c["severity"].as_str().unwrap() + && d.span.start < d.span.end + }) { + failures.push(format!("{name}: missing {tag}: {diags:?}")); + } + } else { + diags.extend(check::validate_model_with(&mut r, &m)); + if !diags.is_empty() { + failures.push(format!("{name}: legal counterpart: {diags:?}")); + } + } + } + } + assert!(failures.is_empty(), "{}", failures.join("\n")); +} + +#[test] +fn standalone_typing_participates_in_binding_conformance() { + let source = + "package P { class A; class B; feature x; feature y : B; typing x : A; binding x = y; }"; + for (bad, source) in [ + (true, source.to_owned()), + (false, source.replace("y : B", "y : A")), + ] { + let mut m = Model::new(); + assert!(m.add_source("typing.kerml", &source).diagnostics.is_empty()); + let diags = check::validate_semantics(&m); + assert_eq!( + diags.iter().any(|(_, d)| d + .message + .contains("[validateBindingConnectorTypeConformance]")), + bad, + "{diags:?}" + ); + } +} diff --git a/crates/sysmlv2-parser/tests/support/census.rs b/crates/sysmlv2-parser/tests/support/census.rs new file mode 100644 index 0000000..f547edd --- /dev/null +++ b/crates/sysmlv2-parser/tests/support/census.rs @@ -0,0 +1,141 @@ +//! Shared stage runner for the external negative-fixture census. The +//! gated baseline tests (`tests/opensysml.rs`) and the reporting example +//! (`examples/opensysmlcheck.rs`) include this file, so both run exactly +//! the same stages and classify a file by the same rule. Referential +//! findings are always recorded under their own stage; whether they can +//! make a file *diagnosed* depends on the mode: without a library they +//! are missing dependencies (a file with nothing else stays unknown), +//! with the library they are findings like any other (a private-member +//! reference is rejected by exactly that stage). Contracts are satisfied +//! only by tagged rows, which the referential stage never produces. +#![allow(dead_code)] + +use serde_json::{Value, json}; +use std::collections::BTreeMap; +use sysmlv2_parser::{check, json::ResolvedModel, model::Model}; + +/// Stage names in pipeline order. A parse error ends the pipeline; +/// the three model stages run only on a clean parse. +pub const STAGES: [&str; 4] = ["parse", "structure", "referential", "semantics"]; + +/// Run every stage over the one user unit of `model` (library units may +/// precede it) and return `{stage, severity, message, start, end}` rows. +pub fn stage_diagnostics(model: &Model) -> Vec { + let (index, unit) = model + .units() + .iter() + .enumerate() + .find(|(_, u)| !u.is_library) + .expect("one user unit"); + let mut rows = Vec::new(); + let mut record = |stage: &str, d: &sysmlv2_parser::Diagnostic| { + rows.push(json!({ + "stage": stage, + "severity": format!("{:?}", d.severity), + "message": d.message, + "start": d.span.start, + "end": d.span.end, + })); + }; + for d in &unit.diagnostics { + record("parse", d); + } + if !unit.diagnostics.is_empty() { + return rows; + } + for d in check::validate(&unit.unit) { + record("structure", &d); + } + let mut resolved = ResolvedModel::build(model); + for (u, d) in check::validate_model_with(&mut resolved, model) { + if u == index { + record("referential", &d); + } + } + for (u, d) in check::validate_semantics_with(&mut resolved, model) { + if u == index { + record("semantics", &d); + } + } + rows +} + +/// True when no stage produced a row — or, when `ignore_referential` +/// (the no-library mode), no stage other than the referential one. +pub fn is_unknown(rows: &[Value], ignore_referential: bool) -> bool { + rows.iter() + .all(|d| ignore_referential && d["stage"] == "referential") +} + +/// The baseline status of a file: `accepted (adjudicated)` for a +/// registered acceptance that is unknown, `unknown_label` for any other +/// unknown file, `diagnostic baseline` otherwise. +pub fn status( + rows: &[Value], + ignore_referential: bool, + accepted: bool, + unknown_label: &str, +) -> String { + match (is_unknown(rows, ignore_referential), accepted) { + (true, true) => "accepted (adjudicated)".to_string(), + (true, false) => unknown_label.to_string(), + (false, _) => "diagnostic baseline".to_string(), + } +} + +/// Fixtures whose registered acceptance verdict applies (no rejection +/// expected). +pub fn accepted_fixtures(negative_contracts: &Value) -> Vec { + negative_contracts["contracts"] + .as_array() + .unwrap() + .iter() + .filter(|c| c["verdict"] == "accepted") + .map(|c| c["fixture"].as_str().unwrap().to_string()) + .collect() +} + +/// A row satisfies a rejection contract when it carries the rule tag, +/// the registered category, and a nonempty span. +fn satisfies(rows: &[Value], rule: &str, severity: &Value) -> bool { + let tag = format!("[{rule}]"); + rows.iter().any(|d| { + d["message"].as_str().is_some_and(|m| m.contains(&tag)) + && d["severity"] == *severity + && d["start"].as_u64() < d["end"].as_u64() + }) +} + +/// Registered contracts that the full-library rows do not satisfy: probe +/// contracts by fixture name under `probes/`, negative contracts by their +/// own path, an `accepted` verdict requiring no rejection at all. +pub fn contract_failures( + rows: &BTreeMap>, + static_contracts: &Value, + negative_contracts: &Value, +) -> Vec { + let mut missing = Vec::new(); + for c in static_contracts["contracts"].as_array().unwrap() { + let name = format!("probes/{}", c["fixture"].as_str().unwrap()); + let ok = rows + .get(&name) + .is_some_and(|r| satisfies(r, c["rule"].as_str().unwrap(), &c["severity"])); + if !ok { + missing.push(name); + } + } + for c in negative_contracts["contracts"].as_array().unwrap() { + let name = c["fixture"].as_str().unwrap(); + let ok = rows.get(name).is_some_and(|r| { + if c["verdict"] == "accepted" { + is_unknown(r, false) + } else { + satisfies(r, c["rule"].as_str().unwrap(), &c["severity"]) + } + }); + if !ok { + missing.push(name.to_string()); + } + } + missing +} diff --git a/crates/sysmlv2-parser/tests/xmi_audit.rs b/crates/sysmlv2-parser/tests/xmi_audit.rs index bc56a0a..f2bb434 100644 --- a/crates/sysmlv2-parser/tests/xmi_audit.rs +++ b/crates/sysmlv2-parser/tests/xmi_audit.rs @@ -35,8 +35,8 @@ use testkit::xmi_props::{XMI_DERIVED, XMI_HAS_DEFAULT, XMI_OPTIONAL, XmiProp}; /// properties (KerML 10.4: `@type` = metaclass, `@id` = elementId). const BOOKKEEPING: [&str; 2] = ["@type", "@id"]; -#[test] -fn normative_validation_rule_inventory_and_implemented_registry() { +/// Every `validate…` rule the pinned metamodel XMI declares. +fn pinned_rules() -> BTreeSet { let root = testkit::workspace_root(); let mut rules = BTreeSet::new(); for file in ["spec-refs/KerML.xmi", "spec-refs/SysML.xmi"] { @@ -54,12 +54,21 @@ fn normative_validation_rule_inventory_and_implemented_registry() { } } } + rules +} + +#[test] +fn normative_validation_rule_inventory_and_implemented_registry() { + let rules = pinned_rules(); assert_eq!( rules.len(), 180, "the pinned normative validation-rule inventory changed; classify the delta" ); - for implemented in sysmlv2_parser::check::IMPLEMENTED_NORMATIVE_VALIDATION_RULES { + for implemented in sysmlv2_parser::check::IMPLEMENTED_NORMATIVE_VALIDATION_RULES + .iter() + .chain(sysmlv2_parser::check::IMPLEMENTED_NORMATIVE_SEMANTIC_RULES) + { assert!( rules.contains(*implemented), "implemented rule `{implemented}` is not present in the pinned XMI" @@ -67,6 +76,77 @@ fn normative_validation_rule_inventory_and_implemented_registry() { } } +/// A finding that reports a named rule carries the identifier as a +/// field, so a consumer never has to read it back out of the message, +/// and the identifier it carries is the one the pinned metamodel spells. +/// Where a rule reached this implementation under a different spelling, +/// the message keeps that spelling and only the field is normalized. +#[test] +fn semantic_findings_carry_the_rule_they_report() { + use sysmlv2_parser::{check, json::ResolvedModel}; + let rules = pinned_rules(); + let implemented: BTreeSet<&str> = check::IMPLEMENTED_NORMATIVE_SEMANTIC_RULES + .iter() + .copied() + .collect(); + let library = sysmlv2_testkit::library_dir(); + if !library.is_dir() { + eprintln!("skipping: corpus not present"); + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + // One prepared library, shared by every probe build. + let prepared = base.prepare_library().unwrap(); + let probes = + std::path::Path::new(env!("CARGO_MANIFEST_DIR")).join("tests/fixtures/opensysml/probes"); + let mut coded = 0usize; + for entry in std::fs::read_dir(&probes).unwrap() { + let path = entry.unwrap().path(); + let name = path.file_name().unwrap().to_str().unwrap().to_string(); + if !name.ends_with(".sysml") && !name.ends_with(".kerml") { + continue; + } + let source = std::fs::read_to_string(&path).unwrap(); + let mut model = Model::new(); + prepared.clone().install(&mut model).unwrap(); + model.add_source(&name, &source); + let mut r = ResolvedModel::build(&model); + for (_, d) in check::validate_semantics_with(&mut r, &model) { + let spelled = d + .message + .strip_suffix(']') + .and_then(|head| head.rsplit_once(" [")) + .map(|(_, rule)| rule) + .filter(|rule| rule.starts_with("validate")); + let Some(spelled) = spelled else { + assert!( + d.code.is_none(), + "{name}: a finding naming no rule carries a code: {d:?}" + ); + continue; + }; + let code = d + .code + .unwrap_or_else(|| panic!("{name}: finding reports `{spelled}` with no code")); + assert!( + code == spelled || (rules.contains(code) && !rules.contains(spelled)), + "{name}: code `{code}` differs from the message's `{spelled}` \ + without being the pinned spelling of it" + ); + if rules.contains(code) { + assert!( + implemented.contains(code), + "{name}: rule `{code}` is reported and pinned, but missing \ + from the implemented-rule registry" + ); + } + coded += 1; + } + } + assert!(coded > 100, "the probe sweep reported only {coded} rules"); +} + /// Documented omissions: required or coverage-expected properties the /// compact emitter deliberately never spells, each with its reason. const OMISSIONS: [(&str, &str, &str); 3] = [ @@ -86,9 +166,9 @@ const OMISSIONS: [(&str, &str, &str); 3] = [ ( "ConjugatedPortTyping", "conjugatedPortDefinition", - "TRACKED GAP (INTEROP.md 'Known gaps'): the implicit `~P` \ - ConjugatedPortDefinition element is not modeled yet — conjugated \ - typings carry the metaclass but reference the base definition", + "TRACKED GAP (INTEROP.md 'Known gaps'): the compact owner-side \ + property remains omitted; the implicit `~P` element and the \ + full-form owner-side property are emitted", ), ]; diff --git a/crates/sysmlv2-py/Cargo.toml b/crates/sysmlv2-py/Cargo.toml index 22f2d8e..67f13b2 100644 --- a/crates/sysmlv2-py/Cargo.toml +++ b/crates/sysmlv2-py/Cargo.toml @@ -17,10 +17,10 @@ name = "sysmlv2" crate-type = ["cdylib", "rlib"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } -sysmlv2-transform = { path = "../sysmlv2-transform", version = "0.6.0" } -sysmlv2-viz = { path = "../sysmlv2-viz", version = "0.6.0" } -sysmlv2-lsp = { path = "../sysmlv2-lsp", version = "0.6.0" } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } +sysmlv2-transform = { path = "../sysmlv2-transform", version = "0.9.0" } +sysmlv2-viz = { path = "../sysmlv2-viz", version = "0.9.0" } +sysmlv2-lsp = { path = "../sysmlv2-lsp", version = "0.9.0" } serde_json.workspace = true -pyo3 = { version = "0.23", features = ["abi3-py39"] } +pyo3 = { version = "0.29", features = ["abi3-py39"] } diff --git a/crates/sysmlv2-py/README.md b/crates/sysmlv2-py/README.md index 3817a34..950a100 100644 --- a/crates/sysmlv2-py/README.md +++ b/crates/sysmlv2-py/README.md @@ -21,6 +21,10 @@ json_out = payload.to_compact_json() Element and reference handles belong to one committed state of the session; a successful commit invalidates them (methods raise on stale handles) — re-resolve after committing. -`Session.to_plantuml(view=…)` renders any of seven PlantUML views (structure tree, interconnection, state, action, sequence, use case, mixed) with options for notes, metadata, inherited members, colors, and clickable source hyperlinks; `sysmlv2.check(sources)` runs the CLI's validation pipeline in-process. +Everything the module raises derives from `sysmlv2.Error`, so `except sysmlv2.Error` catches the toolkit's failures and nothing else. A refusal — an argument the toolkit cannot use, a handle from a superseded session state, an edit naming a read-only library element, an edit whose commit would change what an untouched reference denotes — is `sysmlv2.RefusedError`, which derives from `sysmlv2.Error` and from `ValueError`, so `except ValueError` keeps catching every refusal it caught before. + +`Session.to_plantuml(view=…)` renders any of seven PlantUML views (structure tree, interconnection, state, action, sequence, use case, mixed) with options for notes, metadata, inherited members, colors, and clickable source hyperlinks; `sysmlv2.check(sources, lib=None)` runs parse and structural checks in-process, adding referential and semantic checks when `lib` is supplied (a path string or a `pathlib.Path`); it releases the interpreter lock while it runs — a library-backed check takes seconds — so other threads keep going. It does not include the CLI’s unused-private-import analysis. See [the checking API](../../SDK.md#8-checking-models). + +Every call parses on the thread that makes it, which this module neither creates nor resizes. The parser bounds how deeply a source may nest — 128 levels of braces — and that bound assumes a stack large enough to descend that far; a thread that has less overflows on input the parser accepts, and a stack overflow ends the interpreter rather than raising anything catchable. Sources written by hand never come close (the published example and library models nest ten levels), machine-generated ones can: for those, raise `threading.stack_size(16 * 1024 * 1024)` before the thread that will parse. [The tour](../../SDK.md#deeply-nested-sources) shows one way to run a call there and get its result — or its exception — back. Build from source with [maturin](https://maturin.rs): `maturin develop` in `crates/sysmlv2-py/`. A worked tour with real outputs lives in `SDK.md` at the repository root. diff --git a/crates/sysmlv2-py/src/lib.rs b/crates/sysmlv2-py/src/lib.rs index 86d06cf..386fcc2 100644 --- a/crates/sysmlv2-py/src/lib.rs +++ b/crates/sysmlv2-py/src/lib.rs @@ -4,24 +4,124 @@ //! Rust session, so the workspace gates (round-trip, semantic identity, //! splice minimality) apply identically. //! -//! Handle discipline: [`Element`] and [`Reference`] handles are minted +//! Handle discipline: `Element` and `Reference` handles are minted //! against one committed state of a session (a *generation*). A //! successful commit bumps the generation and invalidates outstanding //! handles — using one afterwards raises `ValueError` instead of //! silently denoting the wrong element. +//! +//! Thread discipline: every call parses on the interpreter's own thread, +//! which this binding does not create and cannot resize. The parser +//! bounds how deeply input may nest, and that bound assumes a stack of +//! `sysmlv2_parser::parser::MAX_NESTING_STACK_BYTES`; below it, input +//! the parser accepts overflows the stack, which ends the interpreter +//! outright rather than raising. The toolkit's own entry points reserve +//! that stack for themselves; a caller who may open deeply nested +//! sources does the same by raising `threading.stack_size` and calling +//! from a thread of its own (`SDK.md` shows it). use pyo3::IntoPyObjectExt; -use pyo3::exceptions::{PyRuntimeError, PyValueError}; +use pyo3::exceptions::{PyException, PyRuntimeError, PyValueError}; use pyo3::prelude::*; -use pyo3::types::{PyBytes, PyList, PyTuple}; +use pyo3::sync::PyOnceLock; +use pyo3::types::{PyBytes, PyDict, PyList, PyTuple, PyType}; use sysmlv2_model::eval::Value as EvalValue; use sysmlv2_model::json::{ElementRef, RefSite}; use sysmlv2_syntax::parser::parse_expression; -use sysmlv2_transform::{Session as TSession, TransformError}; +use sysmlv2_transform::Session as TSession; + +pyo3::create_exception!( + sysmlv2, + Error, + PyException, + "Base class of every exception this package raises, so `except sysmlv2.Error` catches all of them and nothing else." +); + +/// Build a subclass of [`Error`] that also derives from one of the +/// interpreter's own exceptions, so a caller's existing `except` clause +/// keeps working while `except sysmlv2.Error` starts to. Two bases are +/// what a class statement expresses and what the type constructor takes; +/// a statically declared exception carries only one, which is why these +/// are built here rather than declared. +fn derived_class<'py>( + py: Python<'py>, + name: &str, + builtin: &Bound<'py, PyType>, + doc: &str, +) -> PyResult> { + let namespace = PyDict::new(py); + namespace.set_item("__module__", "sysmlv2")?; + namespace.set_item("__doc__", doc)?; + let bases = PyTuple::new(py, [py.get_type::(), builtin.clone()])?; + Ok(py + .get_type::() + .call1((name, bases, namespace))? + .cast_into::()? + .unbind()) +} + +/// `sysmlv2.RefusedError`, built on first use: a refusal is recognizable +/// as this package's and is still caught by the `except ValueError` the +/// binding has always documented. +static REFUSED: PyOnceLock> = PyOnceLock::new(); + +fn refused_class(py: Python<'_>) -> PyResult> { + let cls = REFUSED.get_or_try_init(py, || { + derived_class( + py, + "RefusedError", + &py.get_type::(), + "The toolkit declined the operation: an argument it cannot use, \ + a handle minted against a superseded session state, or an edit \ + whose commit would change what an untouched reference denotes.", + ) + })?; + Ok(cls.bind(py).clone()) +} + +/// `sysmlv2.FailedError`, built on first use. Operations that could not +/// be carried out raised `RuntimeError` before this package had an +/// exception of its own, so that base is kept: `except RuntimeError` +/// around a session call still catches what it used to. +static FAILED: PyOnceLock> = PyOnceLock::new(); + +fn failed_class(py: Python<'_>) -> PyResult> { + let cls = FAILED.get_or_try_init(py, || { + derived_class( + py, + "FailedError", + &py.get_type::(), + "The toolkit could not carry the operation out: a source it \ + could not read, a model it could not build, or an expression \ + it could not evaluate.", + ) + })?; + Ok(cls.bind(py).clone()) +} + +/// The toolkit declined the request: `sysmlv2.RefusedError`. +fn refused(e: E) -> PyErr { + let message = e.to_string(); + Python::attach(|py| match refused_class(py) { + Ok(cls) => PyErr::from_type(cls, message), + // The class could not be built, which is itself the failure. + Err(err) => err, + }) +} + +/// The toolkit could not carry the request out: `sysmlv2.FailedError`. +fn failed(e: E) -> PyErr { + let message = e.to_string(); + Python::attach(|py| match failed_class(py) { + Ok(cls) => PyErr::from_type(cls, message), + // The class could not be built, which is itself the failure. + Err(err) => err, + }) +} /// An opaque handle to one element of a session's resolved model. -#[pyclass(frozen)] +#[pyclass(frozen, from_py_object)] #[derive(Clone)] struct Element { e: ElementRef, @@ -47,8 +147,70 @@ impl Element { } } +/// A derived-property target outside the model (see `Session.derived`): +/// an element of an unloaded library or a foreign payload by its +/// interchange id, or a reference that never resolved by its spelling. +#[pyclass(frozen, get_all, from_py_object)] +#[derive(Clone)] +struct OutsideReference { + id: Option, + spelling: Option, +} + +#[pymethods] +impl OutsideReference { + fn __repr__(&self) -> String { + match (&self.id, &self.spelling) { + (Some(id), _) => format!(""), + (None, Some(s)) => format!(""), + _ => "".to_string(), + } + } +} + +fn fidelity_name(f: sysmlv2_model::json::Derives) -> &'static str { + use sysmlv2_model::json::Derives; + match f { + Derives::NotDeclared => "not-declared", + Derives::NotComputed => "not-computed", + Derives::Passthrough => "passthrough", + Derives::Exact => "exact", + } +} + +fn closure_policy_name(p: sysmlv2_model::json::ClosurePolicy) -> &'static str { + use sysmlv2_model::json::ClosurePolicy; + match p { + ClosurePolicy::Passthrough => "passthrough", + ClosurePolicy::Closure { + include_implied: false, + } => "closure", + ClosurePolicy::Closure { + include_implied: true, + } => "closure-implied", + } +} + +fn parse_closure_policy(name: &str) -> PyResult { + use sysmlv2_model::json::ClosurePolicy; + Ok(match name { + "passthrough" => ClosurePolicy::Passthrough, + "closure" => ClosurePolicy::Closure { + include_implied: false, + }, + "closure-implied" => ClosurePolicy::Closure { + include_implied: true, + }, + other => { + return Err(PyValueError::new_err(format!( + "unknown closure policy {other:?}: passthrough, closure or closure-implied" + ))); + } + }) +} + /// One resolved reference site (see `Session.references`). -#[pyclass(frozen)] +#[pyclass(frozen, from_py_object)] #[derive(Clone)] struct Reference { site: RefSite, @@ -216,7 +378,7 @@ impl EditBatch { impl EditBatch { fn guard(&self, gen: u64) -> PyResult<()> { if gen != self.gen { - return Err(PyValueError::new_err( + return Err(refused( "stale handle: it belongs to a different session state", )); } @@ -235,10 +397,6 @@ struct Session { gen: u64, } -fn runtime(e: E) -> PyErr { - PyRuntimeError::new_err(e.to_string()) -} - impl Session { fn mint(&self, e: ElementRef) -> Element { Element { e, gen: self.gen } @@ -246,7 +404,7 @@ impl Session { fn guard(&self, gen: u64) -> PyResult<()> { if gen != self.gen { - return Err(PyValueError::new_err( + return Err(refused( "stale handle: the session was edited since it was minted \ (re-resolve after commit)", )); @@ -254,13 +412,26 @@ impl Session { Ok(()) } - fn value_to_py(&self, py: Python<'_>, v: &EvalValue) -> PyResult { + fn value_to_py(&self, py: Python<'_>, v: &EvalValue) -> PyResult> { match v { EvalValue::Boolean(b) => b.into_py_any(py), EvalValue::Integer(i) => i.into_py_any(py), - EvalValue::Rational(f) => f.into_py_any(py), + // Exact numbers stay exact: integers beyond the machine + // range as `int`, other rationals as `fractions.Fraction`. + EvalValue::Rational(r) => { + let (n, d) = r.to_string_parts(); + let int = py.import("builtins")?.getattr("int")?; + let n = int.call1((n,))?; + if r.is_integer() { + return Ok(n.unbind()); + } + let d = int.call1((d,))?; + let fraction = py.import("fractions")?.getattr("Fraction")?; + Ok(fraction.call1((n, d))?.unbind()) + } + EvalValue::Real(f) => f.into_py_any(py), EvalValue::String(s) => s.into_py_any(py), - EvalValue::Element(e) | EvalValue::Unbound(e) => { + EvalValue::Element(e) | EvalValue::Unbound(e) | EvalValue::UnboundMember(e) => { Ok(Py::new(py, self.mint(*e))?.into_any()) } // An indeterminate result (an operation over an unbound @@ -300,7 +471,7 @@ impl Session { let paths: Vec = paths.into_iter().map(std::path::PathBuf::from).collect(); Ok(Session { - inner: TSession::open(&paths).map_err(runtime)?, + inner: TSession::open(&paths).map_err(failed)?, gen: 0, }) } @@ -309,7 +480,7 @@ impl Session { #[staticmethod] fn from_sources(sources: Vec<(String, String)>) -> PyResult { Ok(Session { - inner: TSession::from_sources(sources).map_err(runtime)?, + inner: TSession::from_sources(sources).map_err(failed)?, gen: 0, }) } @@ -323,13 +494,13 @@ impl Session { #[pyo3(signature = (json, lib = None))] fn from_interchange_json(json: &str, lib: Option<&str>) -> PyResult { let value: serde_json::Value = - serde_json::from_str(json).map_err(|e| PyValueError::new_err(e.to_string()))?; + serde_json::from_str(json).map_err(|e| refused(e.to_string()))?; Ok(Session { inner: TSession::from_interchange_json_with_library( &value, lib.map(std::path::Path::new), ) - .map_err(runtime)?, + .map_err(failed)?, gen: 0, }) } @@ -341,7 +512,7 @@ impl Session { fn from_compact_cbor(data: &[u8], lib: Option<&str>) -> PyResult { Ok(Session { inner: TSession::from_compact_cbor_with_library(data, lib.map(std::path::Path::new)) - .map_err(runtime)?, + .map_err(failed)?, gen: 0, }) } @@ -351,7 +522,7 @@ impl Session { fn load_library(&mut self, dir: &str) -> PyResult<()> { self.inner .load_library(std::path::Path::new(dir)) - .map_err(runtime)?; + .map_err(failed)?; self.gen += 1; Ok(()) } @@ -368,7 +539,7 @@ impl Session { /// Evaluate an ad-hoc KerML query expression at the root namespace /// (closed-world `istype`, `ownedMember(x)` / `ownedFeature(x)` /// reflection — the `sysmlv2 query` semantics). - fn query(&mut self, py: Python<'_>, expr: &str) -> PyResult { + fn query(&mut self, py: Python<'_>, expr: &str) -> PyResult> { let parsed = parse_expression(expr); let Some(ast) = parsed.expr else { let msg = parsed @@ -376,29 +547,153 @@ impl Session { .first() .map(|d| d.message.clone()) .unwrap_or_else(|| "not an expression".into()); - return Err(PyValueError::new_err(msg)); + return Err(refused(msg)); }; let root = self.inner.resolved().root_scope(); - let value = self.inner.resolved().query(root, &ast).map_err(runtime)?; + let value = self.inner.resolved().query(root, &ast).map_err(failed)?; self.value_to_py(py, &value) } /// Evaluate `e`'s bound feature value. - fn evaluate(&mut self, py: Python<'_>, e: &Element) -> PyResult { + fn evaluate(&mut self, py: Python<'_>, e: &Element) -> PyResult> { self.guard(e.gen)?; - let value = self.inner.resolved().evaluate(e.e).map_err(runtime)?; + let value = self.inner.resolved().evaluate(e.e).map_err(failed)?; self.value_to_py(py, &value) } + // ---- derived properties (the spec-name read API) ---- + + /// The derived property `name` of `e`, by its specification name + /// (`"ownedFeature"`, `"owningNamespace"`, `"name"`, …): `None` for a + /// null single value, a `bool` or `str`, an `Element`, a `list` of + /// elements or of strings; a target outside the model comes back as + /// an `OutsideReference` (its id, or the spelling that never + /// resolved). Raises `KeyError` when the element's metaclass does + /// not declare the property as derived (an owned property is read + /// with the property accessors) and `NotImplementedError` when the + /// toolkit does not compute it yet; `derives` tells in advance. + fn derived(&mut self, py: Python<'_>, e: &Element, name: &str) -> PyResult> { + use sysmlv2_model::json::{Derived, DerivedValue, Reference}; + self.guard(e.gen)?; + let reference = |this: &Self, py: Python<'_>, r: Reference| -> PyResult> { + match r { + Reference::Element(x) => Ok(Py::new(py, this.mint(x))?.into_any()), + Reference::External(id) => Ok(Py::new( + py, + OutsideReference { + id: Some(id.to_string()), + spelling: None, + }, + )? + .into_any()), + Reference::Unresolved(spelling) => Ok(Py::new( + py, + OutsideReference { + id: None, + spelling: Some(spelling), + }, + )? + .into_any()), + _ => Err(pyo3::exceptions::PyRuntimeError::new_err( + "unsupported reference shape from a newer toolkit", + )), + } + }; + match self.inner.resolved().derived(e.e, name) { + Derived::NotDeclared => Err(pyo3::exceptions::PyKeyError::new_err(format!( + "{name} is not a derived property of {}", + self.inner.resolved().element_type(e.e) + ))), + Derived::NotComputed => Err(pyo3::exceptions::PyNotImplementedError::new_err(format!( + "{name} is not computed by this toolkit yet" + ))), + Derived::Value(v) => match v { + DerivedValue::Null => Ok(py.None()), + DerivedValue::Bool(b) => b.into_py_any(py), + DerivedValue::Str(s) => s.into_py_any(py), + DerivedValue::Strings(ss) => ss.into_py_any(py), + DerivedValue::Element(x) => Ok(Py::new(py, self.mint(x))?.into_any()), + DerivedValue::Elements(xs) => { + let items: Vec = xs.into_iter().map(|x| self.mint(x)).collect(); + items.into_py_any(py) + } + DerivedValue::Reference(r) => reference(self, py, r), + DerivedValue::References(rs) => { + let mut items: Vec> = Vec::with_capacity(rs.len()); + for r in rs { + items.push(reference(self, py, r)?); + } + items.into_py_any(py) + } + _ => Err(pyo3::exceptions::PyRuntimeError::new_err( + "unsupported derived value shape from a newer toolkit", + )), + }, + } + } + + /// What `derived` answers for `name` on elements of `metaclass`, + /// decided without a model: `"not-declared"`, `"not-computed"`, + /// `"passthrough"` (the owned side of an inheritance-aware property + /// until the closure policy is on) or `"exact"`. + #[staticmethod] + fn derives(metaclass: &str, name: &str) -> &'static str { + fidelity_name(sysmlv2_model::json::derives(metaclass, name)) + } + + /// Whether the abstract syntax owns `name` on `metaclass` (an owned + /// property is read with the property accessors, never with + /// `derived`). + #[staticmethod] + fn is_owned_property(metaclass: &str, name: &str) -> bool { + sysmlv2_model::json::is_owned_property(metaclass, name) + } + + /// Every derived property name `derived` can answer on some + /// metaclass. + #[staticmethod] + fn computed_names() -> Vec<&'static str> { + sysmlv2_model::json::computed_names().collect() + } + + /// The closure policy `derived` answers under: `"passthrough"` (the + /// default — the owned side of the inheritance-aware properties), + /// `"closure"` (their specification definition over the inherited and + /// imported memberships) or `"closure-implied"` (the same, with the + /// implied library heritage). + fn closure_policy(&mut self) -> &'static str { + closure_policy_name(self.inner.resolved().closure_policy()) + } + + /// Set the closure policy (see `closure_policy`). + fn set_closure_policy(&mut self, policy: &str) -> PyResult<()> { + let policy = parse_closure_policy(policy)?; + self.inner.resolved().set_closure_policy(policy); + Ok(()) + } + // ---- navigation ---- - /// The element's qualified name (None for anonymous elements). + /// The element's qualified name (None for anonymous elements): the + /// specification's derivation, in which a reserved word used as a + /// name stays bare (`part::view`). A model property, not source + /// text — splice `reference_spelling` into generated text instead. fn qualified_name(&mut self, e: &Element) -> PyResult> { self.guard(e.gen)?; Ok(self.inner.resolved().element_qualified_name(e.e)) } - /// The element's declared name. + /// The element's qualified name spelled as reference text that + /// re-parses in either dialect: reserved words and non-basic names + /// quoted (`'part'::'view'` where `qualified_name` is `part::view`). + /// None for anonymous elements. + fn reference_spelling(&mut self, e: &Element) -> PyResult> { + self.guard(e.gen)?; + Ok(self.inner.resolved().element_reference_spelling(e.e)) + } + + /// The element's declared name; the specification's `name` (an + /// unnamed feature named by what it redefines) is `derived(e, "name")`. fn name(&mut self, e: &Element) -> PyResult> { self.guard(e.gen)?; Ok(self.inner.resolved().element_name(e.e).map(str::to_string)) @@ -560,7 +855,7 @@ impl Session { /// qualified name: `[(input id, session id)]`. fn id_map_from(&mut self, json: &str) -> PyResult> { let value: serde_json::Value = - serde_json::from_str(json).map_err(|e| PyValueError::new_err(e.to_string()))?; + serde_json::from_str(json).map_err(|e| refused(e.to_string()))?; Ok(self .inner .id_map_from(&value) @@ -579,10 +874,7 @@ impl Session { /// counts. When anything was respelled the session rebuilt: /// outstanding handles go stale. fn minimize_qualifications(&mut self) -> PyResult<(usize, usize)> { - let report = self - .inner - .minimize_qualifications() - .map_err(|e| PyRuntimeError::new_err(e.to_string()))?; + let report = self.inner.minimize_qualifications().map_err(refused)?; if report.respelled > 0 { self.gen += 1; } @@ -605,6 +897,34 @@ impl Session { let ops = std::mem::take(&mut batch.ops); // Consumed: a batch cannot be committed twice. batch.gen = u64::MAX; + // A library unit's text is not part of the session, so an op + // that would have to splice one is refused by name here, before + // the splice planner reaches for source it does not hold. + for op in &ops { + let read_only = match op { + Op::Rename(e, _) + | Op::SetFeatureValue(e, _) + | Op::InsertMember(e, _) + | Op::Remove(e) + | Op::ExtractDefinition(e, _) + | Op::InlineDefinition(e) => self + .inner + .resolved() + .is_library_element(*e) + .then(|| self.inner.resolved().element_qualified_name(*e)), + // `retarget` rewrites the site, not what the site will + // denote: a library element is a legitimate new target. + Op::Retarget(site, _) => (self.inner.source(site.unit).is_none()) + .then(|| self.inner.resolved().element_qualified_name(site.target)), + Op::InsertTopLevel(..) => None, + }; + if let Some(name) = read_only { + return Err(refused(format!( + "library elements are read-only: {}", + name.as_deref().unwrap_or("an anonymous element") + ))); + } + } let mut builder = self.inner.edit(); for op in &ops { match op { @@ -634,16 +954,9 @@ impl Session { } } } - let report = builder.commit().map_err(|e| match e { - TransformError::InvalidName(_) - | TransformError::InvalidExpression { .. } - | TransformError::InvalidMember { .. } - | TransformError::UnknownUnit(_) - | TransformError::ExtractIneligible { .. } - | TransformError::InlineIneligible { .. } - | TransformError::NameTaken { .. } => PyValueError::new_err(e.to_string()), - other => PyRuntimeError::new_err(other.to_string()), - })?; + // Every way a commit can fail is a refusal: the batch was + // rejected at plan time or rolled back at verification. + let report = builder.commit().map_err(refused)?; self.gen += 1; Ok(CommitReport { id_map: report @@ -710,7 +1023,7 @@ impl Session { "case" => sysmlv2_viz::View::Case, "mixed" => sysmlv2_viz::View::Mixed, other => { - return Err(PyValueError::new_err(format!( + return Err(refused(format!( "unknown view: {other} (expected tree, interconnection, state, action, sequence, case, or mixed)" ))); } @@ -720,7 +1033,7 @@ impl Session { Some("polyline") => sysmlv2_viz::LineStyle::Polyline, Some("ortho") => sysmlv2_viz::LineStyle::Ortho, Some(other) => { - return Err(PyValueError::new_err(format!( + return Err(refused(format!( "unknown line style: {other} (expected polyline or ortho)" ))); } @@ -730,28 +1043,26 @@ impl Session { self.inner .resolved() .resolve_qualified(name) - .ok_or_else(|| PyValueError::new_err(format!("element not found: {name}")))?, + .ok_or_else(|| refused(format!("element not found: {name}")))?, ), None => None, }; - let opts = sysmlv2_viz::VizOptions { - direction: if horizontal { + let opts = sysmlv2_viz::VizOptions::default() + .with_direction(if horizontal { sysmlv2_viz::Direction::LeftToRight } else { sysmlv2_viz::Direction::TopToBottom - }, - show_values, - view, - show_notes, - show_metadata, - show_inherited, - show_lib, - show_imported, - line_style, - std_color, - link_template, - roots: None, - }; + }) + .with_show_values(show_values) + .with_view(view) + .with_show_notes(show_notes) + .with_show_metadata(show_metadata) + .with_show_inherited(show_inherited) + .with_show_lib(show_lib) + .with_show_imported(show_imported) + .with_line_style(line_style) + .with_std_color(std_color) + .with_link_template(link_template); Ok(sysmlv2_viz::plantuml(self.inner.resolved(), root, &opts)) } @@ -768,6 +1079,11 @@ struct Finding { /// `"error"` or `"warning"`. #[pyo3(get)] severity: String, + /// `"parse"`, `"context"`, `"referential"` or `"semantic"`: the + /// pipeline stage that produced the finding. Only `"parse"` findings + /// keep a unit out of a session. + #[pyo3(get)] + stage: String, #[pyo3(get)] message: String, /// Unit name of the source the finding is in (as passed to `check`). @@ -798,11 +1114,22 @@ impl Finding { /// Model problems come back as [`Finding`]s — a broken parse is a /// finding, not an exception. Exceptions are reserved for operational /// failures (unreadable library directory). +/// +/// The inputs are owned, so the check itself runs with the interpreter +/// released: a library-backed check takes seconds, and other threads +/// keep running for the whole of it. +// Owned: borrowed arguments cannot cross into a released interpreter. +#[allow(clippy::needless_pass_by_value)] #[pyfunction] #[pyo3(signature = (sources, lib = None))] -fn check(sources: Vec<(String, String)>, lib: Option<&str>) -> PyResult> { - let findings = sysmlv2_transform::check_sources(&sources, lib.map(std::path::Path::new)) - .map_err(runtime)?; +fn check( + py: Python<'_>, + sources: Vec<(String, String)>, + lib: Option, +) -> PyResult> { + let findings = py + .detach(|| sysmlv2_transform::check_sources(&sources, lib.as_deref())) + .map_err(failed)?; Ok(findings .into_iter() .map(|f| Finding { @@ -810,6 +1137,7 @@ fn check(sources: Vec<(String, String)>, lib: Option<&str>) -> PyResult "error".to_string(), sysmlv2_transform::Severity::Warning => "warning".to_string(), }, + stage: f.stage.as_str().to_string(), message: f.message, unit: f.unit, line: f.line, @@ -875,7 +1203,7 @@ impl LspServer { /// them) — relay them exactly like `handle`'s output. fn set_workspace(&mut self, units: Vec<(String, String)>) -> PyResult> { self.inner.set_workspace_sources(units); - self.inner.take_outbound().map_err(runtime) + self.inner.take_outbound().map_err(failed) } /// Handle one JSON-RPC message string (a request or a @@ -883,7 +1211,7 @@ impl LspServer { /// in order, each a JSON-RPC string. The first message of a /// session must be an `initialize` request. fn handle(&mut self, msg: &str) -> PyResult> { - self.inner.handle(msg).map_err(runtime) + self.inner.handle(msg).map_err(failed) } /// Drop cached navigation sessions after a host-side engine @@ -892,7 +1220,7 @@ impl LspServer { /// refresh requests to relay, like `set_workspace`. fn invalidate_sessions(&mut self) -> PyResult> { self.inner.invalidate_sessions(); - self.inner.take_outbound().map_err(runtime) + self.inner.take_outbound().map_err(failed) } /// Set whether evaluated-value inlay hints that restate the @@ -900,7 +1228,7 @@ impl LspServer { /// Returns the refresh requests to relay, like `set_workspace`. fn set_hide_redundant_value_hints(&mut self, on: bool) -> PyResult> { self.inner.set_hide_redundant_value_hints(on); - self.inner.take_outbound().map_err(runtime) + self.inner.take_outbound().map_err(failed) } /// Set whether accepting a unit completion inside an untyped @@ -923,16 +1251,29 @@ fn set_unit_spelling_expansion(on: bool) { /// SysML v2 / KerML toolkit: sessions over textual models or interchange /// JSON, KerML-expression queries, and verified span-splice /// transformations. +/// +/// Every call parses on the thread that makes it, which this module +/// neither creates nor resizes. The parser bounds how deeply a source may +/// nest, and that bound assumes a stack large enough to descend that far; +/// a thread that has less overflows on input the parser accepts, and a +/// stack overflow ends the interpreter rather than raising anything +/// catchable. Sources written by hand never come close. For +/// machine-generated ones, raise `threading.stack_size` to 16 MiB before +/// the thread that will parse — the tour in `SDK.md` shows it. #[pymodule] fn sysmlv2(m: &Bound<'_, PyModule>) -> PyResult<()> { m.add("__version__", env!("CARGO_PKG_VERSION"))?; m.add_class::()?; m.add_class::()?; + m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; m.add_class::()?; + m.add("Error", m.py().get_type::())?; + m.add("RefusedError", refused_class(m.py())?)?; + m.add("FailedError", failed_class(m.py())?)?; m.add_function(wrap_pyfunction!(check, m)?)?; m.add_function(wrap_pyfunction!(set_unit_spelling_expansion, m)?)?; Ok(()) diff --git a/crates/sysmlv2-py/tests/smoke.py b/crates/sysmlv2-py/tests/smoke.py index a9592e5..91b8c0f 100644 --- a/crates/sysmlv2-py/tests/smoke.py +++ b/crates/sysmlv2-py/tests/smoke.py @@ -1,5 +1,6 @@ """Smoke test of the sysmlv2 Python binding — the whole public surface.""" import json +import pathlib import sysmlv2 DEMO = """package Defs { @@ -37,6 +38,42 @@ assert len(s.elements_of_metaclass("PartDefinition")) == 3 assert not s.is_library_element(wheel) +# --- derived properties by specification name --- +assert [s.name(f) for f in s.derived(vehicle, "ownedFeature")] == ["front", "spare", "count"] +assert s.derived(vehicle, "name") == "Vehicle" +assert s.derived(vehicle, "shortName") is None +assert s.derived(front, "owningType") == vehicle +assert s.derived(front, "type") == [wheel] +assert sysmlv2.Session.derives("PartUsage", "ownedFeature") == "exact" +assert sysmlv2.Session.derives("PartUsage", "feature") == "passthrough" +assert sysmlv2.Session.derives("PartUsage", "declaredName") == "not-declared" +assert sysmlv2.Session.is_owned_property("PartUsage", "declaredName") +assert "owningNamespace" in sysmlv2.Session.computed_names() +try: + s.derived(vehicle, "declaredName") + assert False, "an owned property is not derived" +except KeyError: + pass +try: + s.derived(front, "mayTimeVary") + assert False, "not computed yet" +except NotImplementedError: + pass +# A target outside the model, and the closure policy's effect. +s2 = sysmlv2.Session.from_sources([("o.sysml", "package O { part w : Missing; part def A { part x; } part def B :> A; }")]) +w = s2.resolve("O::w") +[outside] = s2.derived(w, "type") +assert isinstance(outside, sysmlv2.OutsideReference) and outside.spelling == "Missing" and outside.id is None +b = s2.resolve("O::B") +assert s2.derived(b, "feature") == [] +assert s2.closure_policy() == "passthrough" +s2.set_closure_policy("closure") +assert s2.closure_policy() == "closure" +assert [s2.name(f) for f in s2.derived(b, "feature")] == ["x"] +s2.edit([{"op": "moveMember", "target": "O::w", "index": 0}]) +assert s2.closure_policy() == "closure" +s2.set_closure_policy("passthrough") + # --- find-usages --- refs = s.references(wheel) assert len(refs) == 3, refs @@ -48,6 +85,15 @@ assert [s.name(e) for e in q] == ["front", "spare"], q assert s.query("Rig::Vehicle::count + 1") == 3 assert s.query("2 ** 10") == 1024 +# Exact arithmetic: decimals are rationals, integers are unbounded, and +# only transcendental results are floats. +from fractions import Fraction +assert s.query("0.1 + 0.2") == Fraction(3, 10) +assert s.query("0.1 + 0.2 == 0.3") is True +assert s.query("1 / 3") == Fraction(1, 3) +assert s.query("2.5 * 2") == 5 and isinstance(s.query("2.5 * 2"), int) +assert s.query("2 ** 200") == 2 ** 200 +assert isinstance(s.query("sqrt(2)"), float) count = s.resolve("Rig::Vehicle::count") assert s.evaluate(count) == 2 @@ -90,7 +136,7 @@ try: t.commit(bad) raise AssertionError("shadow capture must raise") -except RuntimeError as e: +except sysmlv2.RefusedError as e: assert "would resolve to" in str(e), e assert t.resolve("P::Q::U") is not None # rolled back @@ -126,15 +172,26 @@ assert "Missing" not in r2.units()[0][2] # the opt-out stays lossy # --- error surfaces --- +# Everything the package raises is a sysmlv2.Error; a refusal is also a +# ValueError, which is what callers caught before the base class existed. +assert issubclass(sysmlv2.RefusedError, sysmlv2.Error) +assert issubclass(sysmlv2.RefusedError, ValueError) +assert not issubclass(sysmlv2.Error, ValueError) +assert sysmlv2.Error.__module__ == sysmlv2.RefusedError.__module__ == "sysmlv2" try: s2.query("1 +") raise AssertionError("bad expression must raise") -except ValueError: - pass +except ValueError as e: + assert isinstance(e, sysmlv2.RefusedError), type(e) +try: + s2.to_plantuml(element="Nope::Gone") + raise AssertionError("unknown element must raise") +except sysmlv2.Error as e: + assert "element not found" in str(e), e # --- check: the CLI check pipeline as a library call --- bad = sysmlv2.check([("bad.sysml", "package Bad {\n part p : ;\n}")]) -assert bad and bad[0].severity == "error" +assert bad and bad[0].severity == "error" and bad[0].stage == "parse" assert (bad[0].unit, bad[0].line, bad[0].col) == ("bad.sysml", 2, 12) assert sysmlv2.check([("ok.sysml", "package Ok { part def A; part a : A; }")]) == [] @@ -215,7 +272,7 @@ rf.commit(b) assert rf.source(0) == RIG # inline(extract(usage)) is byte-identical -# explicit name, and named refusals surface as ValueError +# explicit name, and named refusals surface as sysmlv2.RefusedError rf2 = sysmlv2.Session.from_sources([("rig.sysml", RIG)]) b = rf2.edit() b.extract_definition(rf2.resolve("Rig::engine"), name="Motor") @@ -245,6 +302,49 @@ assert any("import now unused" in f for f in report.findings), report.findings assert "private import Defs::*;" in imp.source(1) # reported, not removed +# --- library elements are read-only --- +# Their declarations live in units the session does not hold, so an edit +# naming one is refused before anything is spliced. Needs the standard +# library checkout; skipped without it. +LIBRARY = pathlib.Path(__file__).resolve().parents[3] / "spec-refs/SysML-v2-Release/sysml.library" +if LIBRARY.is_dir(): + lb = sysmlv2.Session.from_sources( + [("u.sysml", "package U {\n attribute def A;\n attribute x : A;\n}\n")] + ) + lb.load_library(str(LIBRARY)) + real = lb.resolve("ScalarValues::Real") + assert lb.is_library_element(real) + for stage in ( + lambda b: b.rename(real, "Reel"), + lambda b: b.remove(real), + lambda b: b.insert_member(real, "attribute q;"), + lambda b: b.set_feature_value(real, "1"), + lambda b: b.extract_definition(real), + lambda b: b.inline_definition(real), + ): + batch = lb.edit() + stage(batch) + try: + lb.commit(batch) + raise AssertionError("editing a library element must raise") + except sysmlv2.RefusedError as e: + assert "read-only" in str(e) and "ScalarValues::Real" in str(e), e + # `check` accepts the library as a path object as well as a string, + # and reports the same findings either way. + typo = [("t.sysml", "package T {\n part p : Nope;\n}\n")] + by_path = [repr(f) for f in sysmlv2.check(typo, LIBRARY)] + assert by_path == [repr(f) for f in sysmlv2.check(typo, str(LIBRARY))] + assert any("Nope" in line for line in by_path), by_path + + # Retargeting a user site *to* a library element stays legal. + site = next(r for r in lb.references(lb.resolve("U::A")) if r.kind == "type") + batch = lb.edit() + batch.retarget(site, real) + lb.commit(batch) + assert "attribute x : ScalarValues::Real;" in lb.units()[0][2] +else: + print("smoke: no standard library checkout — library refusals not exercised") + assert tuple(int(x) for x in sysmlv2.__version__.split(".")) >= (0, 1, 0) print("smoke: all assertions passed") diff --git a/crates/sysmlv2-solve/Cargo.toml b/crates/sysmlv2-solve/Cargo.toml index ae47e4b..dac16ab 100644 --- a/crates/sysmlv2-solve/Cargo.toml +++ b/crates/sysmlv2-solve/Cargo.toml @@ -12,8 +12,8 @@ repository.workspace = true include = ["src/**", "Cargo.toml"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } [dev-dependencies] sysmlv2-testkit.workspace = true diff --git a/crates/sysmlv2-solve/examples/solvestats.rs b/crates/sysmlv2-solve/examples/solvestats.rs index 888d166..d8e1df1 100644 --- a/crates/sysmlv2-solve/examples/solvestats.rs +++ b/crates/sysmlv2-solve/examples/solvestats.rs @@ -35,7 +35,7 @@ fn main() { valid += 1; println!( "VALID: {} — {:?} ({})", - model.units()[s.unit].name, + model.unit(s.unit).name, s.name, s.element_type ); @@ -44,7 +44,7 @@ fn main() { unsat += 1; println!( "UNSAT: {} — {:?} ({})", - model.units()[s.unit].name, + model.unit(s.unit).name, s.name, s.element_type ); @@ -54,7 +54,7 @@ fn main() { let vals: Vec = w.iter().map(|(n, v)| format!("{n} = {v}")).collect(); println!( "sat: {} — {:?} e.g. {}", - model.units()[s.unit].name, + model.unit(s.unit).name, s.name, vals.join(", ") ); @@ -63,6 +63,8 @@ fn main() { unknown += 1; *reasons.entry(m.clone()).or_default() += 1; } + // A conclusion this tally does not know would go uncounted. + Some(other) => panic!("unhandled solve conclusion: {other:?}"), } } println!( diff --git a/crates/sysmlv2-solve/examples/unknowns.rs b/crates/sysmlv2-solve/examples/unknowns.rs index a97b542..3ff3897 100644 --- a/crates/sysmlv2-solve/examples/unknowns.rs +++ b/crates/sysmlv2-solve/examples/unknowns.rs @@ -22,7 +22,7 @@ fn main() { if let Some(SolveOutcome::Unknown(reason)) = &s.solve { by_reason.entry(reason.clone()).or_default().push(format!( "{} — {:?}", - model.units()[s.unit].name, + model.unit(s.unit).name, s.name )); } diff --git a/crates/sysmlv2-solve/src/ival.rs b/crates/sysmlv2-solve/src/ival.rs index 98ef441..5ff1721 100644 --- a/crates/sysmlv2-solve/src/ival.rs +++ b/crates/sysmlv2-solve/src/ival.rs @@ -5,212 +5,366 @@ //! boolean, or an enum-literal set — and terms evaluate to domains that //! **contain every value the term can take** when each variable ranges //! over its domain. That containment is the soundness invariant all of -//! interval propagation rests on: real endpoints round *outward* at every inexact -//! operation, integer endpoints saturate, and anything the evaluator -//! cannot bound tightly widens (never narrows). +//! interval propagation rests on: real endpoints are exact rationals (so +//! the propagatable operations — `+ − × ÷` — never round at all), integer +//! endpoints saturate, and anything the evaluator cannot bound tightly +//! widens (never narrows). The one place a real endpoint is ever moved is +//! the size cap in [`Ival::new`], which widens an endpoint whose exact +//! fraction has grown past a bit budget to a nearby double — outward, so +//! the enclosure stays sound and a bound spelled by a decimal literal +//! (`0.8`, `1.1`) stays exactly that literal. //! //! Empty domains are first-class: an empty operand makes every result //! empty, and (in propagation) a variable contracted to empty proves the //! asserted constraint set unsatisfiable. +use std::cmp::Ordering; + +use sysmlv2_model::rational::Rational; + use crate::term::{EnumSort, Op, Sort, Term}; -/// Round toward −∞ / +∞ by one ulp — applied to every real endpoint -/// that may have rounded, so intervals only ever widen. A *lower* -/// endpoint that overflowed to `+∞` clamps to `f64::MAX` instead -/// (mirrored in [`up`]): letting the degenerate point `[+∞, +∞]` form -/// would make a later `∞ − ∞` produce NaN — which would read as EMPTY, -/// a fabricated unsat proof. Clamping only ever moves a lower bound -/// down (an upper bound up), so it stays sound. -fn dn(x: f64) -> f64 { - if x == f64::INFINITY { - f64::MAX - } else if x.is_finite() { - x.next_down() - } else { - x +// ---------------------------------------------------------------- reals + +/// A real endpoint: an exact rational, or an infinity. Derived ordering +/// is the numeric order (`NegInf < Fin(_) < PosInf`, rationals by value). +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +pub(crate) enum Ext { + NegInf, + Fin(Rational), + PosInf, +} + +/// Bit budget for one exact endpoint. Fixpoint iteration over exact +/// fractions can grow numerators and denominators without bound long +/// before the progress epsilon stops it; past this size an endpoint is +/// widened to a nearby double, which is exact again and small. +const MAX_ENDPOINT_BITS: u64 = 1024; + +impl Ext { + pub fn zero() -> Ext { + Ext::Fin(Rational::zero()) + } + + /// The exact value of a double: infinities map to the infinite + /// endpoints; `None` for NaN, which carries no ordering information. + pub fn from_f64(f: f64) -> Option { + if f.is_nan() { + None + } else if f == f64::INFINITY { + Some(Ext::PosInf) + } else if f == f64::NEG_INFINITY { + Some(Ext::NegInf) + } else { + Rational::from_f64(f).map(Ext::Fin) + } + } + + pub fn is_zero(&self) -> bool { + matches!(self, Ext::Fin(r) if r.is_zero()) + } + + fn is_finite(&self) -> bool { + matches!(self, Ext::Fin(_)) + } + + /// Sign relative to zero. + fn sign(&self) -> Ordering { + match self { + Ext::NegInf => Ordering::Less, + Ext::PosInf => Ordering::Greater, + Ext::Fin(r) => { + if r.is_negative() { + Ordering::Less + } else if r.is_zero() { + Ordering::Equal + } else { + Ordering::Greater + } + } + } + } + + fn inf_with_sign(s: Ordering) -> Ext { + match s { + Ordering::Less => Ext::NegInf, + Ordering::Greater => Ext::PosInf, + Ordering::Equal => Ext::zero(), + } + } + + pub fn neg(&self) -> Ext { + match self { + Ext::NegInf => Ext::PosInf, + Ext::PosInf => Ext::NegInf, + Ext::Fin(r) => Ext::Fin(r.neg()), + } + } + + /// Exact sum. Interval arithmetic never adds opposite infinities + /// (lower endpoints are `NegInf`/finite, upper ones finite/`PosInf`, + /// and empties are handled before any arithmetic); should it ever + /// happen, the result is the *lower* infinity, which only widens. + pub fn add(&self, o: &Ext) -> Ext { + match (self, o) { + (Ext::Fin(a), Ext::Fin(b)) => Ext::Fin(a.add(b)), + (Ext::NegInf, _) | (_, Ext::NegInf) => Ext::NegInf, + _ => Ext::PosInf, + } + } + + pub fn sub(&self, o: &Ext) -> Ext { + self.add(&o.neg()) + } + + /// Exact product. An exactly-zero factor makes the product exactly + /// zero even against an infinite factor (the finite factor *is* zero, + /// so every product is zero). + pub fn mul(&self, o: &Ext) -> Ext { + if self.is_zero() || o.is_zero() { + return Ext::zero(); + } + match (self, o) { + (Ext::Fin(a), Ext::Fin(b)) => Ext::Fin(a.mul(b)), + _ => { + let s = if self.sign() == o.sign() { + Ordering::Greater + } else { + Ordering::Less + }; + Ext::inf_with_sign(s) + } + } + } + + /// Exact quotient for a nonzero divisor: a zero dividend or an + /// infinite divisor gives an exact zero, an infinite dividend gives + /// the signed infinity. + pub fn div(&self, o: &Ext) -> Ext { + debug_assert!( + !o.is_zero(), + "interval division by an exactly-zero endpoint" + ); + if self.is_zero() || !o.is_finite() { + return Ext::zero(); + } + match (self, o) { + (Ext::Fin(a), Ext::Fin(b)) => Ext::Fin(a.div(b).expect("non-zero divisor")), + _ => { + let s = if self.sign() == o.sign() { + Ordering::Greater + } else { + Ordering::Less + }; + Ext::inf_with_sign(s) + } + } + } + + fn min(self, o: Ext) -> Ext { + if o < self { o } else { self } + } + + fn max(self, o: Ext) -> Ext { + if o > self { o } else { self } } } -fn up(x: f64) -> f64 { - if x == f64::NEG_INFINITY { - -f64::MAX - } else if x.is_finite() { - x.next_up() - } else { - x + +/// Widen an oversized lower endpoint down to a nearby double (exact +/// again, and small); anything within budget passes through unchanged. +fn cap_lo(e: Ext) -> Ext { + match &e { + Ext::Fin(r) if r.bits() > MAX_ENDPOINT_BITS => { + let f = r.to_f64(); + if f == f64::NEG_INFINITY { + return Ext::NegInf; + } + // `f` is the nearest double, possibly above the value: the + // double below it is certainly not above. + Ext::from_f64(f.next_down()).unwrap_or(Ext::NegInf) + } + _ => e, } } -// ---------------------------------------------------------------- reals +/// [`cap_lo`] for an upper endpoint, widening upward. +fn cap_hi(e: Ext) -> Ext { + match &e { + Ext::Fin(r) if r.bits() > MAX_ENDPOINT_BITS => { + let f = r.to_f64(); + if f == f64::INFINITY { + return Ext::PosInf; + } + Ext::from_f64(f.next_up()).unwrap_or(Ext::PosInf) + } + _ => e, + } +} -/// A closed real interval `[lo, hi]` (endpoints may be ±∞; never NaN). -/// Empty is canonical `[+∞, −∞]`. -#[derive(Clone, Copy, Debug, PartialEq)] +/// A closed real interval `[lo, hi]` with exact endpoints (which may be +/// ±∞). Empty is canonical `[+∞, −∞]`. +#[derive(Clone, Debug, PartialEq)] pub(crate) struct Ival { - pub lo: f64, - pub hi: f64, + pub lo: Ext, + pub hi: Ext, } impl Ival { - pub const TOP: Ival = Ival { - lo: f64::NEG_INFINITY, - hi: f64::INFINITY, - }; - pub const EMPTY: Ival = Ival { - lo: f64::INFINITY, - hi: f64::NEG_INFINITY, - }; + /// All of ℝ. + pub fn top() -> Ival { + Ival { + lo: Ext::NegInf, + hi: Ext::PosInf, + } + } - pub fn new(lo: f64, hi: f64) -> Ival { - if lo.is_nan() || hi.is_nan() { - // NaN carries no ordering information: the only sound domain - // is ⊤ — canonicalizing to EMPTY would turn an arithmetic - // artifact into a false unsat proof. - return Ival::TOP; + /// The empty interval. + pub fn empty() -> Ival { + Ival { + lo: Ext::PosInf, + hi: Ext::NegInf, } + } + + /// `[lo, hi]`, empty when `lo > hi`. Oversized endpoints are widened + /// outward to a nearby double (see [`MAX_ENDPOINT_BITS`]). + pub fn new(lo: Ext, hi: Ext) -> Ival { + let lo = cap_lo(lo); + let hi = cap_hi(hi); if lo <= hi { Ival { lo, hi } } else { - Ival::EMPTY + Ival::empty() } } - pub fn point(x: f64) -> Ival { - Ival::new(x, x) + /// The exact value of two doubles as an interval; a NaN endpoint + /// carries no ordering information, so the only sound domain is ⊤ + /// (canonicalizing to empty would turn an arithmetic artifact into a + /// false unsat proof). + #[cfg(test)] + pub fn from_f64(lo: f64, hi: f64) -> Ival { + match (Ext::from_f64(lo), Ext::from_f64(hi)) { + (Some(lo), Some(hi)) => Ival::new(lo, hi), + _ => Ival::top(), + } } - pub fn is_empty(self) -> bool { + pub fn point(x: Rational) -> Ival { + Ival::new(Ext::Fin(x.clone()), Ext::Fin(x)) + } + + pub fn is_empty(&self) -> bool { self.lo > self.hi } - pub fn contains(self, x: f64) -> bool { - self.lo <= x && x <= self.hi + pub fn contains(&self, x: &Ext) -> bool { + self.lo <= *x && *x <= self.hi + } + + pub fn contains_rational(&self, x: &Rational) -> bool { + match (&self.lo, &self.hi) { + (Ext::PosInf, _) | (_, Ext::NegInf) => false, + _ => { + let above_lo = match &self.lo { + Ext::NegInf => true, + Ext::Fin(l) => l <= x, + Ext::PosInf => false, + }; + let below_hi = match &self.hi { + Ext::PosInf => true, + Ext::Fin(h) => x <= h, + Ext::NegInf => false, + }; + above_lo && below_hi + } + } + } + + pub fn contains_zero(&self) -> bool { + self.contains(&Ext::zero()) } - pub fn intersect(self, o: Ival) -> Ival { - Ival::new(self.lo.max(o.lo), self.hi.min(o.hi)) + pub fn intersect(&self, o: &Ival) -> Ival { + Ival::new( + self.lo.clone().max(o.lo.clone()), + self.hi.clone().min(o.hi.clone()), + ) } - pub fn hull(self, o: Ival) -> Ival { + pub fn hull(&self, o: &Ival) -> Ival { if self.is_empty() { - return o; + return o.clone(); } if o.is_empty() { - return self; + return self.clone(); } - Ival::new(self.lo.min(o.lo), self.hi.max(o.hi)) + Ival::new( + self.lo.clone().min(o.lo.clone()), + self.hi.clone().max(o.hi.clone()), + ) } - pub fn add(self, o: Ival) -> Ival { + pub fn add(&self, o: &Ival) -> Ival { if self.is_empty() || o.is_empty() { - return Ival::EMPTY; + return Ival::empty(); } - Ival::new(dn(self.lo + o.lo), up(self.hi + o.hi)) + Ival::new(self.lo.add(&o.lo), self.hi.add(&o.hi)) } - pub fn sub(self, o: Ival) -> Ival { + pub fn sub(&self, o: &Ival) -> Ival { if self.is_empty() || o.is_empty() { - return Ival::EMPTY; + return Ival::empty(); } - Ival::new(dn(self.lo - o.hi), up(self.hi - o.lo)) + Ival::new(self.lo.sub(&o.hi), self.hi.sub(&o.lo)) } - pub fn neg(self) -> Ival { + pub fn neg(&self) -> Ival { if self.is_empty() { - return Ival::EMPTY; + return Ival::empty(); } - Ival::new(-self.hi, -self.lo) + Ival::new(self.hi.neg(), self.lo.neg()) } - pub fn mul(self, o: Ival) -> Ival { + /// Exact product: the hull of the four endpoint products. + pub fn mul(&self, o: &Ival) -> Ival { if self.is_empty() || o.is_empty() { - return Ival::EMPTY; - } - // min/max over the four endpoint products, each rounded outward - // individually. `0 × ∞` reads as an exact 0 (the finite factor - // is exactly zero, so every product is zero) — and a zero - // product from a zero factor stays exact, so multiplying by a - // literal 0 keeps a point interval. - let pd = |a: f64, b: f64| { - if a == 0.0 || b == 0.0 { 0.0 } else { dn(a * b) } - }; - let pu = |a: f64, b: f64| { - if a == 0.0 || b == 0.0 { 0.0 } else { up(a * b) } - }; - let lo = [ - pd(self.lo, o.lo), - pd(self.lo, o.hi), - pd(self.hi, o.lo), - pd(self.hi, o.hi), - ] - .into_iter() - .fold(f64::INFINITY, f64::min); - let hi = [ - pu(self.lo, o.lo), - pu(self.lo, o.hi), - pu(self.hi, o.lo), - pu(self.hi, o.hi), - ] - .into_iter() - .fold(f64::NEG_INFINITY, f64::max); + return Ival::empty(); + } + let products = [ + self.lo.mul(&o.lo), + self.lo.mul(&o.hi), + self.hi.mul(&o.lo), + self.hi.mul(&o.hi), + ]; + let lo = products.iter().cloned().fold(Ext::PosInf, Ext::min); + let hi = products.into_iter().fold(Ext::NegInf, Ext::max); Ival::new(lo, hi) } - /// Real division. A divisor interval containing 0 widens to the hull - /// of the two half-line quotients (possibly all of ℝ) — sound, never - /// empty-by-accident. - pub fn div(self, o: Ival) -> Ival { + /// Real division. A divisor interval containing 0 widens to all of ℝ + /// — sound, never empty-by-accident (SMT total division makes `x/0` + /// an unconstrained value). + pub fn div(&self, o: &Ival) -> Ival { if self.is_empty() || o.is_empty() { - return Ival::EMPTY; - } - if o.lo > 0.0 || o.hi < 0.0 { - // Endpoint quotients rounded outward individually; an - // exactly-zero dividend endpoint (or an infinite divisor) - // gives an exact 0. - let qd = |a: f64, b: f64| { - if a == 0.0 || b.is_infinite() { - 0.0 - } else { - dn(a / b) - } - }; - let qu = |a: f64, b: f64| { - if a == 0.0 || b.is_infinite() { - 0.0 - } else { - up(a / b) - } - }; - let lo = [ - qd(self.lo, o.lo), - qd(self.lo, o.hi), - qd(self.hi, o.lo), - qd(self.hi, o.hi), - ] - .into_iter() - .fold(f64::INFINITY, f64::min); - let hi = [ - qu(self.lo, o.lo), - qu(self.lo, o.hi), - qu(self.hi, o.lo), - qu(self.hi, o.hi), - ] - .into_iter() - .fold(f64::NEG_INFINITY, f64::max); + return Ival::empty(); + } + if o.lo.sign() == Ordering::Greater || o.hi.sign() == Ordering::Less { + let quotients = [ + self.lo.div(&o.lo), + self.lo.div(&o.hi), + self.hi.div(&o.lo), + self.hi.div(&o.hi), + ]; + let lo = quotients.iter().cloned().fold(Ext::PosInf, Ext::min); + let hi = quotients.into_iter().fold(Ext::NegInf, Ext::max); return Ival::new(lo, hi); } - if self.contains(0.0) || (o.lo == 0.0 && o.hi == 0.0) { - // 0/0 possible, or divisor is exactly {0}: no information - // (SMT total division makes x/0 an unconstrained value). - return Ival::TOP; - } - // Divisor straddles 0: hull of the strictly-positive and - // strictly-negative parts — unbounded on both sides. - Ival::TOP + Ival::top() } // Certainly-true / certainly-false comparisons. - pub fn lt(self, o: Ival) -> Tri { + pub fn lt(&self, o: &Ival) -> Tri { if self.is_empty() || o.is_empty() { return Tri::Empty; } @@ -223,7 +377,7 @@ impl Ival { } } - pub fn le(self, o: Ival) -> Tri { + pub fn le(&self, o: &Ival) -> Tri { if self.is_empty() || o.is_empty() { return Tri::Empty; } @@ -236,7 +390,7 @@ impl Ival { } } - pub fn eq(self, o: Ival) -> Tri { + pub fn eq(&self, o: &Ival) -> Tri { if self.is_empty() || o.is_empty() { return Tri::Empty; } @@ -253,7 +407,7 @@ impl Ival { // ------------------------------------------------------------- integers /// A closed integer interval over saturating `i128`. Empty is canonical -/// `[MAX, MIN]`. +/// `[MAX, MIN]`; the saturated endpoints `MIN`/`MAX` read as unbounded. #[derive(Clone, Copy, Debug, PartialEq)] pub(crate) struct IntIval { pub lo: i128, @@ -357,19 +511,23 @@ impl IntIval { IntIval::new(lo, hi) } - /// The enclosing real interval. A small integer (`|i| < 2^53`) casts to - /// `f64` exactly and its endpoint stays sharp — the common case of a - /// literal bound like `10`; only a cast that actually loses precision - /// rounds outward, keeping the enclosure sound. + /// The enclosing real interval: exact, with the saturated endpoints + /// reading as unbounded. pub fn to_ival(self) -> Ival { if self.is_empty() { - return Ival::EMPTY; + return Ival::empty(); } - let round_out = |i: i128, out: fn(f64) -> f64| { - let f = i as f64; - if f as i128 == i { f } else { out(f) } + let lo = if self.lo == i128::MIN { + Ext::NegInf + } else { + Ext::Fin(Rational::from_integer(self.lo)) + }; + let hi = if self.hi == i128::MAX { + Ext::PosInf + } else { + Ext::Fin(Rational::from_integer(self.hi)) }; - Ival::new(round_out(self.lo, dn), round_out(self.hi, up)) + Ival::new(lo, hi) } } @@ -476,62 +634,96 @@ impl Tri { } } -/// A set of enum-literal positions (bitset; enum sorts are small). -#[derive(Clone, Copy, Debug, PartialEq)] +/// A set of enum-literal positions: a bit vector with one bit per +/// literal, unbounded in width. Trailing zero words are trimmed, so two +/// sets with the same members compare equal whatever width they were +/// built at, and a missing word reads as zero. +#[derive(Clone, Debug, PartialEq)] pub(crate) struct EnumSet { - pub bits: u128, + words: Vec, } impl EnumSet { - /// All `n` literals. Sorts wider than 128 literals do not occur (the - /// translator interns real model enums); saturate to full-set = ⊤. + const WORD: usize = u64::BITS as usize; + + fn trimmed(mut words: Vec) -> EnumSet { + while words.last() == Some(&0) { + words.pop(); + } + EnumSet { words } + } + + /// All `n` literals. pub fn all(n: usize) -> EnumSet { - if n >= 128 { - EnumSet { bits: u128::MAX } - } else { - EnumSet { - bits: (1u128 << n) - 1, - } + let mut words = vec![u64::MAX; n / Self::WORD]; + if !n.is_multiple_of(Self::WORD) { + words.push((1u64 << (n % Self::WORD)) - 1); } + EnumSet::trimmed(words) } + /// The single literal at position `i`. pub fn point(i: usize) -> EnumSet { - EnumSet { - bits: 1u128 << (i % 128), - } + let mut words = vec![0; i / Self::WORD + 1]; + words[i / Self::WORD] = 1 << (i % Self::WORD); + EnumSet { words } } - pub fn is_empty(self) -> bool { - self.bits == 0 + pub fn is_empty(&self) -> bool { + self.words.is_empty() } - pub fn contains(self, i: usize) -> bool { - i < 128 && self.bits & (1u128 << i) != 0 + pub fn contains(&self, i: usize) -> bool { + self.words + .get(i / Self::WORD) + .is_some_and(|w| w & (1 << (i % Self::WORD)) != 0) } - pub fn intersect(self, o: EnumSet) -> EnumSet { - EnumSet { - bits: self.bits & o.bits, - } + pub fn intersect(&self, o: &EnumSet) -> EnumSet { + EnumSet::trimmed( + self.words + .iter() + .zip(&o.words) + .map(|(a, b)| a & b) + .collect(), + ) } - pub fn hull(self, o: EnumSet) -> EnumSet { - EnumSet { - bits: self.bits | o.bits, + pub fn hull(&self, o: &EnumSet) -> EnumSet { + let (long, short) = if self.words.len() >= o.words.len() { + (self, o) + } else { + (o, self) + }; + let mut words = long.words.clone(); + for (w, s) in words.iter_mut().zip(&short.words) { + *w |= s; } + EnumSet { words } } - pub fn is_point(self) -> bool { - self.bits.count_ones() == 1 + /// The members of `self` that are not in `o`. + pub fn minus(&self, o: &EnumSet) -> EnumSet { + EnumSet::trimmed( + self.words + .iter() + .enumerate() + .map(|(k, a)| a & !o.words.get(k).copied().unwrap_or(0)) + .collect(), + ) } - pub fn eq(self, o: EnumSet) -> Tri { + pub fn is_point(&self) -> bool { + self.words.iter().map(|w| w.count_ones()).sum::() == 1 + } + + pub fn eq(&self, o: &EnumSet) -> Tri { if self.is_empty() || o.is_empty() { return Tri::Empty; } if self.intersect(o).is_empty() { Tri::False - } else if self.is_point() && o.is_point() && self.bits == o.bits { + } else if self.is_point() && o.is_point() && self == o { Tri::True } else { Tri::Both @@ -543,7 +735,7 @@ impl EnumSet { /// The domain of a term or variable. `Str` is opaque: string variables /// carry no interval structure, so every string fact stays `Both`. -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq)] pub(crate) enum Dom { R(Ival), I(IntIval), @@ -554,7 +746,7 @@ pub(crate) enum Dom { } impl Dom { - pub fn is_empty(self) -> bool { + pub fn is_empty(&self) -> bool { match self { Dom::R(v) => v.is_empty(), Dom::I(v) => v.is_empty(), @@ -565,56 +757,39 @@ impl Dom { } /// The enclosing real interval of a numeric domain. - fn as_ival(self) -> Option { + fn as_ival(&self) -> Option { match self { - Dom::R(v) => Some(v), + Dom::R(v) => Some(v.clone()), Dom::I(v) => Some(v.to_ival()), _ => None, } } - fn as_tri(self) -> Option { + fn as_tri(&self) -> Option { match self { - Dom::B(t) => Some(t), + Dom::B(t) => Some(*t), _ => None, } } pub fn hull(self, o: Dom) -> Dom { match (self, o) { - (Dom::R(a), Dom::R(b)) => Dom::R(a.hull(b)), + (Dom::R(a), Dom::R(b)) => Dom::R(a.hull(&b)), (Dom::I(a), Dom::I(b)) => Dom::I(a.hull(b)), (Dom::B(a), Dom::B(b)) => Dom::B(a.hull(b)), - (Dom::E(s, a), Dom::E(t, b)) if s == t => Dom::E(s, a.hull(b)), + (Dom::E(s, a), Dom::E(t, b)) if s == t => Dom::E(s, a.hull(&b)), (Dom::Str, Dom::Str) => Dom::Str, // Mixed numeric kinds hull as reals; anything else has no // common structure — ⊤ of the real line is the widest thing // we can say (such terms are sort errors upstream anyway). (a, b) => match (a.as_ival(), b.as_ival()) { - (Some(x), Some(y)) => Dom::R(x.hull(y)), - _ => Dom::R(Ival::TOP), + (Some(x), Some(y)) => Dom::R(x.hull(&y)), + _ => Dom::R(Ival::top()), }, } } } -/// Parse a [`Term::RealLit`] rendering back to its value. The renderer -/// (`real_from_f64`) writes the f64's exact binary expansion — `num.0`, -/// `(/ num.0 den.0)` with `den` a power of two, possibly inside -/// `(- …)` — so numerator and denominator are exact in f64 and the -/// division reproduces the original value exactly. -fn real_lit(s: &str) -> Option { - let s = s.trim(); - if let Some(body) = s.strip_prefix("(- ").and_then(|r| r.strip_suffix(')')) { - return real_lit(body).map(|v| -v); - } - if let Some(body) = s.strip_prefix("(/ ").and_then(|r| r.strip_suffix(')')) { - let (n, d) = body.split_once(' ')?; - return Some(n.trim().parse::().ok()? / d.trim().parse::().ok()?); - } - s.parse::().ok() -} - /// Forward (bottom-up) evaluation of a term over variable domains: the /// result contains every value the term can take with each variable in /// its domain. Unknown shapes widen to ⊤ of their kind — never narrow. @@ -622,27 +797,29 @@ pub(crate) fn eval_term(t: &Term, doms: &[Dom]) -> Dom { match t { Term::BoolLit(b) => Dom::B(Tri::point(*b)), Term::IntLit(i) => Dom::I(IntIval::point(*i)), - Term::RealLit(s) => match real_lit(s) { - Some(v) => Dom::R(Ival::point(v)), - None => Dom::R(Ival::TOP), - }, + // Exact: the literal's own value, a point. + Term::RealLit(r) => Dom::R(Ival::point(r.clone())), Term::StrLit(_) => Dom::Str, - Term::Var(i) => doms[*i], + Term::Var(i) => doms[*i].clone(), Term::EnumLit(sort, pos) => Dom::E(*sort, EnumSet::point(*pos)), Term::App(op, args) => { - if let Some(d) = args + // Every operand is evaluated exactly once: left-deep chains + // (quantifier expansions, sequence folds) would otherwise + // cost 2^depth evaluations. + let mut kids: Vec> = + args.iter().map(|a| Some(eval_term(a, doms))).collect(); + if let Some(k) = kids .iter() - .map(|a| eval_term(a, doms)) - .find(|d| d.is_empty()) + .position(|k| k.as_ref().is_some_and(Dom::is_empty)) { // An empty operand poisons the whole application; keep // the kind of the first empty operand — callers only ask // `is_empty`. - return d; + return kids[k].take().expect("operand evaluated above"); } - let a = |i: usize| eval_term(&args[i], doms); + let mut a = |i: usize| kids[i].take().expect("each operand is consumed once"); let tri = |d: Dom| d.as_tri().unwrap_or(Tri::Both); - let num = |d: Dom| d.as_ival().unwrap_or(Ival::TOP); + let num = |d: Dom| d.as_ival().unwrap_or_else(Ival::top); match op { Op::Not => Dom::B(tri(a(0)).not()), Op::And => Dom::B(tri(a(0)).and(tri(a(1)))), @@ -651,17 +828,17 @@ pub(crate) fn eval_term(t: &Term, doms: &[Dom]) -> Dom { Op::Implies => Dom::B(tri(a(0)).implies(tri(a(1)))), Op::Eq => Dom::B(match (a(0), a(1)) { (Dom::B(x), Dom::B(y)) => x.eq(y), - (Dom::E(s, x), Dom::E(t, y)) if s == t => x.eq(y), + (Dom::E(s, x), Dom::E(t, y)) if s == t => x.eq(&y), (Dom::Str, _) | (_, Dom::Str) => Tri::Both, (x, y) => match (x.as_ival(), y.as_ival()) { - (Some(u), Some(v)) => u.eq(v), + (Some(u), Some(v)) => u.eq(&v), _ => Tri::Both, }, }), - Op::Lt => Dom::B(num(a(0)).lt(num(a(1)))), - Op::Le => Dom::B(num(a(0)).le(num(a(1)))), - Op::Gt => Dom::B(num(a(1)).lt(num(a(0)))), - Op::Ge => Dom::B(num(a(1)).le(num(a(0)))), + Op::Lt => Dom::B(num(a(0)).lt(&num(a(1)))), + Op::Le => Dom::B(num(a(0)).le(&num(a(1)))), + Op::Gt => Dom::B(num(a(1)).lt(&num(a(0)))), + Op::Ge => Dom::B(num(a(1)).le(&num(a(0)))), Op::Add | Op::Sub | Op::Mul => match (a(0), a(1)) { // Integer structure survives integer arithmetic. (Dom::I(x), Dom::I(y)) => Dom::I(match op { @@ -672,14 +849,14 @@ pub(crate) fn eval_term(t: &Term, doms: &[Dom]) -> Dom { (x, y) => { let (u, v) = (num(x), num(y)); Dom::R(match op { - Op::Add => u.add(v), - Op::Sub => u.sub(v), - _ => u.mul(v), + Op::Add => u.add(&v), + Op::Sub => u.sub(&v), + _ => u.mul(&v), }) } }, // SMT division is always real-valued (operands coerced). - Op::Div => Dom::R(num(a(0)).div(num(a(1)))), + Op::Div => Dom::R(num(a(0)).div(&num(a(1)))), Op::TRem => match (a(0), a(1)) { (Dom::I(x), Dom::I(y)) => Dom::I(x.trem(y)), _ => Dom::I(IntIval::TOP), @@ -701,16 +878,34 @@ pub(crate) fn eval_term(t: &Term, doms: &[Dom]) -> Dom { // ------------------------------------------------ backward contraction -/// The largest real interval enclosing an integer domain: endpoints of a -/// real interval rounded *inward* to integers (`ceil`/`floor`, saturating -/// — an infinite endpoint stays saturated, never NaN). -fn ival_to_int(w: Ival) -> IntIval { +/// The largest integer interval inside a real interval: endpoints +/// rounded *inward* to integers (`ceil`/`floor`), saturating beyond the +/// machine range; an infinite endpoint stays saturated. +fn ival_to_int(w: &Ival) -> IntIval { if w.is_empty() { return IntIval::EMPTY; } - // f64 → i128 `as` saturates (and maps ±∞ to MIN/MAX), so ceil/floor of - // an infinite endpoint lands on the saturated integer. - IntIval::new(w.lo.ceil() as i128, w.hi.floor() as i128) + let lo = match &w.lo { + Ext::NegInf => i128::MIN, + Ext::PosInf => i128::MAX, + Ext::Fin(r) => saturating_i128(&r.ceil()), + }; + let hi = match &w.hi { + Ext::PosInf => i128::MAX, + Ext::NegInf => i128::MIN, + Ext::Fin(r) => saturating_i128(&r.floor()), + }; + IntIval::new(lo, hi) +} + +/// An integral rational as a machine integer, saturating to the end of +/// the range it overflows. +fn saturating_i128(r: &Rational) -> i128 { + match r.to_i128() { + Some(i) => i, + None if r.is_negative() => i128::MIN, + None => i128::MAX, + } } impl Dom { @@ -719,26 +914,26 @@ impl Dom { /// rounds inward; a kind mismatch (a sort error upstream) narrows /// nothing — the result is always a *subset* of `self`, so applying it /// can only tighten. - pub(crate) fn narrow(self, want: Dom) -> Dom { + pub(crate) fn narrow(self, want: &Dom) -> Dom { match self { Dom::R(a) => match want.as_ival() { - Some(w) => Dom::R(a.intersect(w)), - None => self, + Some(w) => Dom::R(a.intersect(&w)), + None => Dom::R(a), }, Dom::I(a) => match want { - Dom::I(w) => Dom::I(a.intersect(w)), + Dom::I(w) => Dom::I(a.intersect(*w)), Dom::R(w) => Dom::I(a.intersect(ival_to_int(w))), - _ => self, + _ => Dom::I(a), }, Dom::B(a) => match want { - Dom::B(w) => Dom::B(a.intersect(w)), - _ => self, + Dom::B(w) => Dom::B(a.intersect(*w)), + _ => Dom::B(a), }, Dom::E(s, a) => match want { - Dom::E(t, w) if t == s => Dom::E(s, a.intersect(w)), - _ => self, + Dom::E(t, w) if *t == s => Dom::E(s, a.intersect(w)), + _ => Dom::E(s, a), }, - Dom::Str => self, + Dom::Str => Dom::Str, } } } @@ -763,25 +958,43 @@ fn meet(a: Refine, b: Refine) -> Refine { } } -fn as_ival_or_top(d: Dom) -> Ival { - d.as_ival().unwrap_or(Ival::TOP) +fn as_ival_or_top(d: &Dom) -> Ival { + d.as_ival().unwrap_or_else(Ival::top) } -fn as_tri_or_both(d: Dom) -> Tri { +fn as_tri_or_both(d: &Dom) -> Tri { d.as_tri().unwrap_or(Tri::Both) } /// Is `new` (a subset of `old`) tighter than `old` by enough to be worth /// applying? Discrete domains progress in finite steps, so any change -/// counts; real endpoints must move by more than a relative epsilon, which -/// (with the driver's iteration cap) guarantees the fixpoint terminates -/// rather than crawling by ulps forever. -fn meaningful(old: Dom, new: Dom, eps: f64) -> bool { +/// counts; real endpoints must move by more than a relative epsilon +/// (measured on their double approximations), which (with the driver's +/// iteration cap) guarantees the fixpoint terminates rather than +/// crawling by ever-smaller fractions forever. +fn meaningful(old: &Dom, new: &Dom, eps: f64) -> bool { match (old, new) { (Dom::R(a), Dom::R(b)) => { - let scale = 1.0 + a.lo.abs().min(f64::MAX).max(a.hi.abs().min(f64::MAX)); + // An infinite endpoint that became finite is progress by any + // measure; the relative test below only compares finite + // endpoints (`∞ − ∞` carries no information). + if (!a.lo.is_finite() && b.lo.is_finite()) || (!a.hi.is_finite() && b.hi.is_finite()) { + return true; + } + // The scale comes from the finite endpoints alone: an infinite + // endpoint must not inflate the tolerance to the double range, + // which would freeze the finite side of a half-line forever. + let finite_mag = |e: &Ext| match e { + Ext::Fin(r) => r.to_f64().abs().min(f64::MAX), + _ => 0.0, + }; + let scale = 1.0 + finite_mag(&a.lo).max(finite_mag(&a.hi)); let tol = eps * scale; - (b.lo - a.lo) > tol || (a.hi - b.hi) > tol + let moved = |from: &Ext, to: &Ext| match (from, to) { + (Ext::Fin(x), Ext::Fin(y)) => (y.to_f64() - x.to_f64()).abs() > tol, + _ => false, + }; + moved(&a.lo, &b.lo) || moved(&a.hi, &b.hi) } _ => true, } @@ -799,14 +1012,14 @@ pub(crate) fn refine_term(t: &Term, want: Dom, doms: &mut [Dom], eps: f64) -> Re } match t { Term::Var(i) => { - let old = doms[*i]; - let new = old.narrow(want); + let old = doms[*i].clone(); + let new = old.clone().narrow(&want); if new == old { Refine::Unchanged } else if new.is_empty() { doms[*i] = new; Refine::Bottom - } else if meaningful(old, new, eps) { + } else if meaningful(&old, &new, eps) { doms[*i] = new; Refine::Changed } else { @@ -814,7 +1027,7 @@ pub(crate) fn refine_term(t: &Term, want: Dom, doms: &mut [Dom], eps: f64) -> Re } } Term::BoolLit(b) => { - let t = as_tri_or_both(want); + let t = as_tri_or_both(&want); let ok = if *b { t.may_true() } else { t.may_false() }; if ok { Refine::Unchanged @@ -824,10 +1037,10 @@ pub(crate) fn refine_term(t: &Term, want: Dom, doms: &mut [Dom], eps: f64) -> Re } Term::IntLit(i) => { // Against an integer demand the check is exact; otherwise fall - // back to the enclosing real interval. - let ok = match want { + // back to the enclosing real interval (also exact). + let ok = match &want { Dom::I(iv) => iv.contains(*i), - _ => as_ival_or_top(want).contains(*i as f64), + _ => as_ival_or_top(&want).contains_rational(&Rational::from_integer(*i)), }; if ok { Refine::Unchanged @@ -835,12 +1048,15 @@ pub(crate) fn refine_term(t: &Term, want: Dom, doms: &mut [Dom], eps: f64) -> Re Refine::Bottom } } - Term::RealLit(s) => match real_lit(s) { - Some(v) if !as_ival_or_top(want).contains(v) => Refine::Bottom, - _ => Refine::Unchanged, - }, - Term::EnumLit(s, pos) => match want { - Dom::E(t, set) if t == *s && !set.contains(*pos) => Refine::Bottom, + Term::RealLit(r) => { + if as_ival_or_top(&want).contains_rational(r) { + Refine::Unchanged + } else { + Refine::Bottom + } + } + Term::EnumLit(s, pos) => match &want { + Dom::E(t, set) if t == s && !set.contains(*pos) => Refine::Bottom, _ => Refine::Unchanged, }, Term::StrLit(_) => Refine::Unchanged, @@ -854,8 +1070,8 @@ pub(crate) fn refine_term(t: &Term, want: Dom, doms: &mut [Dom], eps: f64) -> Re fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> Refine { let a0 = &args[0]; match op { - Op::Not => refine_term(a0, Dom::B(as_tri_or_both(want).not()), doms, eps), - Op::And => match as_tri_or_both(want) { + Op::Not => refine_term(a0, Dom::B(as_tri_or_both(&want).not()), doms, eps), + Op::And => match as_tri_or_both(&want) { Tri::True => meet( refine_term(a0, Dom::B(Tri::True), doms, eps), refine_term(&args[1], Dom::B(Tri::True), doms, eps), @@ -863,8 +1079,8 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R Tri::False => { // The conjunction is false: whichever operand is pinned // true forces the other false. - let f0 = as_tri_or_both(eval_term(a0, doms)); - let f1 = as_tri_or_both(eval_term(&args[1], doms)); + let f0 = as_tri_or_both(&eval_term(a0, doms)); + let f1 = as_tri_or_both(&eval_term(&args[1], doms)); let mut acc = Refine::Unchanged; if !f1.may_false() { acc = meet(acc, refine_term(a0, Dom::B(Tri::False), doms, eps)); @@ -876,14 +1092,14 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R } _ => Refine::Unchanged, }, - Op::Or => match as_tri_or_both(want) { + Op::Or => match as_tri_or_both(&want) { Tri::False => meet( refine_term(a0, Dom::B(Tri::False), doms, eps), refine_term(&args[1], Dom::B(Tri::False), doms, eps), ), Tri::True => { - let f0 = as_tri_or_both(eval_term(a0, doms)); - let f1 = as_tri_or_both(eval_term(&args[1], doms)); + let f0 = as_tri_or_both(&eval_term(a0, doms)); + let f1 = as_tri_or_both(&eval_term(&args[1], doms)); let mut acc = Refine::Unchanged; if !f1.may_true() { acc = meet(acc, refine_term(a0, Dom::B(Tri::True), doms, eps)); @@ -895,10 +1111,10 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R } _ => Refine::Unchanged, }, - Op::Implies => match as_tri_or_both(want) { + Op::Implies => match as_tri_or_both(&want) { Tri::True => { - let f0 = as_tri_or_both(eval_term(a0, doms)); - let f1 = as_tri_or_both(eval_term(&args[1], doms)); + let f0 = as_tri_or_both(&eval_term(a0, doms)); + let f1 = as_tri_or_both(&eval_term(&args[1], doms)); let mut acc = Refine::Unchanged; if !f0.may_false() { acc = meet(acc, refine_term(&args[1], Dom::B(Tri::True), doms, eps)); @@ -917,13 +1133,13 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R }, Op::Xor => { // `xor` true ⟺ operands differ; false ⟺ they agree. - let want_diff = match as_tri_or_both(want) { + let want_diff = match as_tri_or_both(&want) { Tri::True => true, Tri::False => false, _ => return Refine::Unchanged, }; - let f0 = as_tri_or_both(eval_term(a0, doms)); - let f1 = as_tri_or_both(eval_term(&args[1], doms)); + let f0 = as_tri_or_both(&eval_term(a0, doms)); + let f1 = as_tri_or_both(&eval_term(&args[1], doms)); let force = |known: Tri| match known { Tri::True => Some(Tri::point(!want_diff)), Tri::False => Some(Tri::point(want_diff)), @@ -938,7 +1154,7 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R } acc } - Op::Eq => match as_tri_or_both(want) { + Op::Eq => match as_tri_or_both(&want) { Tri::True => { // Each side is confined to the other's domain. let c0 = eval_term(a0, doms); @@ -954,10 +1170,10 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R let c0 = eval_term(a0, doms); let c1 = eval_term(&args[1], doms); let mut acc = Refine::Unchanged; - if let Some(w) = exclude(c1) { + if let Some(w) = exclude(&c1, &c0) { acc = meet(acc, refine_term(a0, w, doms, eps)); } - if let Some(w) = exclude(c0) { + if let Some(w) = exclude(&c0, &c1) { acc = meet(acc, refine_term(&args[1], w, doms, eps)); } acc @@ -965,76 +1181,66 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R _ => Refine::Unchanged, }, Op::Lt | Op::Le => { - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); - match as_tri_or_both(want) { + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); + match as_tri_or_both(&want) { // x ≤ y: closed-interval bounds over-approximate `<`. Tri::True => meet( - refine_term(a0, Dom::R(Ival::new(f64::NEG_INFINITY, y.hi)), doms, eps), - refine_term(&args[1], Dom::R(Ival::new(x.lo, f64::INFINITY)), doms, eps), + refine_term(a0, Dom::R(Ival::new(Ext::NegInf, y.hi)), doms, eps), + refine_term(&args[1], Dom::R(Ival::new(x.lo, Ext::PosInf)), doms, eps), ), // ¬(x < y) ⟺ x ≥ y. Tri::False => meet( - refine_term(a0, Dom::R(Ival::new(y.lo, f64::INFINITY)), doms, eps), - refine_term( - &args[1], - Dom::R(Ival::new(f64::NEG_INFINITY, x.hi)), - doms, - eps, - ), + refine_term(a0, Dom::R(Ival::new(y.lo, Ext::PosInf)), doms, eps), + refine_term(&args[1], Dom::R(Ival::new(Ext::NegInf, x.hi)), doms, eps), ), _ => Refine::Unchanged, } } Op::Gt | Op::Ge => { - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); - match as_tri_or_both(want) { + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); + match as_tri_or_both(&want) { Tri::True => meet( - refine_term(a0, Dom::R(Ival::new(y.lo, f64::INFINITY)), doms, eps), - refine_term( - &args[1], - Dom::R(Ival::new(f64::NEG_INFINITY, x.hi)), - doms, - eps, - ), + refine_term(a0, Dom::R(Ival::new(y.lo, Ext::PosInf)), doms, eps), + refine_term(&args[1], Dom::R(Ival::new(Ext::NegInf, x.hi)), doms, eps), ), Tri::False => meet( - refine_term(a0, Dom::R(Ival::new(f64::NEG_INFINITY, y.hi)), doms, eps), - refine_term(&args[1], Dom::R(Ival::new(x.lo, f64::INFINITY)), doms, eps), + refine_term(a0, Dom::R(Ival::new(Ext::NegInf, y.hi)), doms, eps), + refine_term(&args[1], Dom::R(Ival::new(x.lo, Ext::PosInf)), doms, eps), ), _ => Refine::Unchanged, } } // z = x + y ⟹ x ∈ z − y, y ∈ z − x. Op::Add => { - let w = as_ival_or_top(want); - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); + let w = as_ival_or_top(&want); + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); meet( - refine_term(a0, Dom::R(w.sub(y)), doms, eps), - refine_term(&args[1], Dom::R(w.sub(x)), doms, eps), + refine_term(a0, Dom::R(w.sub(&y)), doms, eps), + refine_term(&args[1], Dom::R(w.sub(&x)), doms, eps), ) } // z = x − y ⟹ x ∈ z + y, y ∈ x − z. Op::Sub => { - let w = as_ival_or_top(want); - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); + let w = as_ival_or_top(&want); + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); meet( - refine_term(a0, Dom::R(w.add(y)), doms, eps), - refine_term(&args[1], Dom::R(x.sub(w)), doms, eps), + refine_term(a0, Dom::R(w.add(&y)), doms, eps), + refine_term(&args[1], Dom::R(x.sub(&w)), doms, eps), ) } // z = x·y ⟹ x ∈ z/y, y ∈ z/x (division through zero widens to // ⊤, so it never over-narrows). Op::Mul => { - let w = as_ival_or_top(want); - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); + let w = as_ival_or_top(&want); + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); meet( - refine_term(a0, Dom::R(w.div(y)), doms, eps), - refine_term(&args[1], Dom::R(w.div(x)), doms, eps), + refine_term(a0, Dom::R(w.div(&y)), doms, eps), + refine_term(&args[1], Dom::R(w.div(&x)), doms, eps), ) } // z = x/y ⟹ x ∈ z·y, y ∈ x/z — but only where the divisor @@ -1044,33 +1250,33 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R // own zero (keep 0 in the demand) — the forward pass's widening, // mirrored. Op::Div => { - let w = as_ival_or_top(want); - let x = as_ival_or_top(eval_term(a0, doms)); - let y = as_ival_or_top(eval_term(&args[1], doms)); - let acc = if y.contains(0.0) { + let w = as_ival_or_top(&want); + let x = as_ival_or_top(&eval_term(a0, doms)); + let y = as_ival_or_top(&eval_term(&args[1], doms)); + let acc = if y.contains_zero() { Refine::Unchanged } else { - refine_term(a0, Dom::R(w.mul(y)), doms, eps) + refine_term(a0, Dom::R(w.mul(&y)), doms, eps) }; - let yd = if y.contains(0.0) { - x.div(w).hull(Ival::point(0.0)) + let yd = if y.contains_zero() { + x.div(&w).hull(&Ival::point(Rational::zero())) } else { - x.div(w) + x.div(&w) }; meet(acc, refine_term(&args[1], Dom::R(yd), doms, eps)) } - Op::Neg => refine_term(a0, Dom::R(as_ival_or_top(want).neg()), doms, eps), + Op::Neg => refine_term(a0, Dom::R(as_ival_or_top(&want).neg()), doms, eps), // No useful inverse for truncated remainder. Op::TRem => Refine::Unchanged, - Op::Ite => match as_tri_or_both(eval_term(a0, doms)) { + Op::Ite => match as_tri_or_both(&eval_term(a0, doms)) { Tri::Empty => Refine::Bottom, Tri::True => refine_term(&args[1], want, doms, eps), Tri::False => refine_term(&args[2], want, doms, eps), Tri::Both => { // The condition is undecided: if a branch cannot meet // `want`, the condition must select the other. - let then_ok = !eval_term(&args[1], doms).narrow(want).is_empty(); - let else_ok = !eval_term(&args[2], doms).narrow(want).is_empty(); + let then_ok = !eval_term(&args[1], doms).narrow(&want).is_empty(); + let else_ok = !eval_term(&args[2], doms).narrow(&want).is_empty(); match (then_ok, else_ok) { (false, false) => Refine::Bottom, (false, true) => meet( @@ -1089,14 +1295,17 @@ fn refine_app(op: Op, args: &[Term], want: Dom, doms: &mut [Dom], eps: f64) -> R } /// The domain a `!=` (or `==`-is-false) partner must avoid, when the known -/// side is a definite point: the negation of a boolean, or an enum with -/// exactly that one literal removed. Numeric point-exclusion has no -/// interval representation, so it returns `None` (no contraction). -fn exclude(known: Dom) -> Option { - match known { - Dom::B(Tri::True) => Some(Dom::B(Tri::False)), - Dom::B(Tri::False) => Some(Dom::B(Tri::True)), - Dom::E(s, set) if set.is_point() => Some(Dom::E(s, EnumSet { bits: !set.bits })), +/// side is a definite point: the negation of a boolean, or the partner's +/// own forward domain (`partner`) with exactly that one literal removed. +/// Numeric point-exclusion has no interval representation, so it returns +/// `None` (no contraction). +fn exclude(known: &Dom, partner: &Dom) -> Option { + match (known, partner) { + (Dom::B(Tri::True), _) => Some(Dom::B(Tri::False)), + (Dom::B(Tri::False), _) => Some(Dom::B(Tri::True)), + (Dom::E(s, set), Dom::E(t, rest)) if s == t && set.is_point() => { + Some(Dom::E(*s, rest.minus(set))) + } _ => None, } } @@ -1141,19 +1350,21 @@ pub(crate) fn init_dom(sort: Sort, enum_sizes: &[usize]) -> Dom { match sort { Sort::Bool => Dom::B(Tri::Both), Sort::Int => Dom::I(IntIval::TOP), - Sort::Real => Dom::R(Ival::TOP), + Sort::Real => Dom::R(Ival::top()), Sort::Str => Dom::Str, Sort::Enum(i) => Dom::E(i, EnumSet::all(enum_sizes[i])), } } -fn fmt_f(x: f64) -> String { - if x == f64::INFINITY { - "+∞".into() - } else if x == f64::NEG_INFINITY { - "−∞".into() - } else { - format!("{x}") +/// Render a real endpoint: exact (a terminating decimal or a reduced +/// fraction) or, with `approx`, a non-terminating fraction as a marked +/// approximate decimal for glanceable surfaces. +fn fmt_ext(x: &Ext, approx: bool) -> String { + match x { + Ext::PosInf => "+∞".into(), + Ext::NegInf => "−∞".into(), + Ext::Fin(r) if approx => r.to_approx_string(), + Ext::Fin(r) => r.to_string(), } } @@ -1167,12 +1378,14 @@ fn fmt_i(x: i128) -> String { } } -/// Render a domain as a half-open/closed range or set, for `--ranges` -/// output. Enum literals use their model-facing names. -pub(crate) fn fmt_dom(d: Dom, enums: &[EnumSort]) -> String { +/// Render a domain as a closed range or set, for `--ranges` output +/// (`approx = false`, exact endpoints) and for editor hints (`approx = +/// true`, non-terminating endpoints as approximate decimals). Enum +/// literals use their model-facing names. +pub(crate) fn fmt_dom(d: &Dom, enums: &[EnumSort], approx: bool) -> String { match d { Dom::R(v) if v.is_empty() => "∅".into(), - Dom::R(v) => format!("[{}, {}]", fmt_f(v.lo), fmt_f(v.hi)), + Dom::R(v) => format!("[{}, {}]", fmt_ext(&v.lo, approx), fmt_ext(&v.hi, approx)), Dom::I(v) if v.is_empty() => "∅".into(), Dom::I(v) => format!("[{}, {}]", fmt_i(v.lo), fmt_i(v.hi)), Dom::B(Tri::True) => "{true}".into(), @@ -1181,7 +1394,7 @@ pub(crate) fn fmt_dom(d: Dom, enums: &[EnumSort]) -> String { Dom::B(Tri::Empty) => "∅".into(), Dom::E(_, set) if set.is_empty() => "∅".into(), Dom::E(s, set) => { - let names: Vec<&str> = enums[s] + let names: Vec<&str> = enums[*s] .displays .iter() .enumerate() @@ -1198,38 +1411,134 @@ pub(crate) fn fmt_dom(d: Dom, enums: &[EnumSort]) -> String { mod tests { use super::*; + fn iv(lo: f64, hi: f64) -> Ival { + Ival::from_f64(lo, hi) + } + + fn pt(x: f64) -> Ival { + Ival::from_f64(x, x) + } + + trait ContainsF64 { + fn contains_rational_f64(&self, x: f64) -> bool; + } + impl ContainsF64 for Ival { + fn contains_rational_f64(&self, x: f64) -> bool { + Ext::from_f64(x).is_some_and(|e| self.contains(&e)) + } + } + + fn dec(s: &str) -> Rational { + Rational::parse_decimal(s).unwrap() + } + // -- interval arithmetic ------------------------------------------------ #[test] fn real_ops_basics() { - let a = Ival::new(1.0, 2.0); - let b = Ival::new(-3.0, 4.0); - assert!(a.add(b).contains(-2.0) && a.add(b).contains(6.0)); - assert!(a.sub(b).contains(-3.0) && a.sub(b).contains(5.0)); - assert!(a.mul(b).contains(-6.0) && a.mul(b).contains(8.0)); - assert_eq!(Ival::EMPTY.add(a), Ival::EMPTY); - assert!(a.div(Ival::point(0.0)) == Ival::TOP); - assert!(b.div(a).contains(4.0) && b.div(a).contains(-3.0)); + let a = iv(1.0, 2.0); + let b = iv(-3.0, 4.0); + assert!(a.add(&b).contains_rational_f64(-2.0) && a.add(&b).contains_rational_f64(6.0)); + assert!(a.sub(&b).contains_rational_f64(-3.0) && a.sub(&b).contains_rational_f64(5.0)); + assert!(a.mul(&b).contains_rational_f64(-6.0) && a.mul(&b).contains_rational_f64(8.0)); + assert_eq!(Ival::empty().add(&a), Ival::empty()); + assert!(a.div(&pt(0.0)) == Ival::top()); + assert!(b.div(&a).contains_rational_f64(4.0) && b.div(&a).contains_rational_f64(-3.0)); // Divisor straddling zero widens to ⊤, never errs. - assert_eq!(a.div(b), Ival::TOP); + assert_eq!(a.div(&b), Ival::top()); + } + + #[test] + fn arithmetic_is_exact() { + // No rounding anywhere: decimal literals combine to decimal + // results, and inverses recover the operands exactly. + let tenth = Ival::point(dec("0.1")); + let fifth = Ival::point(dec("0.2")); + assert_eq!(tenth.add(&fifth), Ival::point(dec("0.3"))); + assert_eq!( + Ival::point(dec("1.1")).mul(&Ival::point(dec("100"))), + Ival::point(dec("110")) + ); + let third = Ival::point(dec("1")).div(&Ival::point(dec("3"))); + assert_eq!(third, Ival::point(Rational::new(1, 3).unwrap())); + assert_eq!(third.mul(&Ival::point(dec("3"))), Ival::point(dec("1"))); + let x = iv(0.8, 1.1); + assert_eq!(x.add(&fifth).sub(&fifth), x); } #[test] fn zero_times_unbounded_is_zero() { - assert_eq!(Ival::point(0.0).mul(Ival::TOP), Ival::point(0.0)); + assert_eq!(pt(0.0).mul(&Ival::top()), pt(0.0)); + } + + #[test] + fn infinite_endpoints_behave() { + let half_line = Ival::new(Ext::Fin(dec("10")), Ext::PosInf); + assert_eq!( + half_line.add(&half_line), + Ival::new(Ext::Fin(dec("20")), Ext::PosInf) + ); + // ∞ − ∞ never fabricates an empty interval. + let d = half_line.sub(&half_line); + assert!(!d.is_empty() && d.contains_zero(), "{d:?}"); + assert_eq!( + half_line.neg(), + Ival::new(Ext::NegInf, Ext::Fin(dec("-10"))) + ); + assert_eq!( + half_line.mul(&Ival::new(Ext::Fin(dec("2")), Ext::PosInf)), + Ival::new(Ext::Fin(dec("20")), Ext::PosInf) + ); + // [1, +∞] / [2, +∞] = [0, +∞]: a finite over an infinite is 0. + assert_eq!( + Ival::new(Ext::Fin(dec("1")), Ext::PosInf) + .div(&Ival::new(Ext::Fin(dec("2")), Ext::PosInf)), + Ival::new(Ext::zero(), Ext::PosInf) + ); + // NaN reaching the constructor widens instead of emptying. + assert_eq!(Ival::from_f64(f64::NAN, f64::NAN), Ival::top()); + assert_eq!( + Ival::from_f64(f64::NEG_INFINITY, f64::INFINITY), + Ival::top() + ); + } + + #[test] + fn oversized_endpoints_widen_outward() { + // An endpoint whose exact fraction outgrows the bit budget is + // replaced by a nearby double, on the widening side. + let big = Rational::from_integer(3).pow(2000).unwrap(); + let tiny = big.recip().unwrap(); // 3^-2000: far more than 1024 bits + let one_plus = Rational::one().add(&tiny); + let i = Ival::new(Ext::Fin(one_plus.clone()), Ext::Fin(one_plus.clone())); + assert!(!i.is_empty()); + assert!(i.contains_rational(&one_plus)); + let (Ext::Fin(lo), Ext::Fin(hi)) = (&i.lo, &i.hi) else { + panic!("{i:?}"); + }; + assert!(lo.bits() <= 64 && hi.bits() <= 64, "{i:?}"); + assert!(*lo < one_plus && one_plus < *hi); + // Within budget nothing moves: a decimal literal bound stays + // exactly itself. + assert_eq!(Ival::point(dec("0.8")).lo, Ext::Fin(dec("0.8"))); } #[test] fn comparisons_certainty() { - let a = Ival::new(1.0, 2.0); - let b = Ival::new(3.0, 4.0); - assert_eq!(a.lt(b), Tri::True); - assert_eq!(b.lt(a), Tri::False); - assert_eq!(a.lt(Ival::new(1.5, 5.0)), Tri::Both); - assert_eq!(a.le(Ival::new(2.0, 5.0)), Tri::True); - assert_eq!(Ival::point(2.0).eq(Ival::point(2.0)), Tri::True); - assert_eq!(a.eq(b), Tri::False); - assert_eq!(a.eq(Ival::new(2.0, 3.0)), Tri::Both); + let a = iv(1.0, 2.0); + let b = iv(3.0, 4.0); + assert_eq!(a.lt(&b), Tri::True); + assert_eq!(b.lt(&a), Tri::False); + assert_eq!(a.lt(&iv(1.5, 5.0)), Tri::Both); + assert_eq!(a.le(&iv(2.0, 5.0)), Tri::True); + assert_eq!(pt(2.0).eq(&pt(2.0)), Tri::True); + assert_eq!(a.eq(&b), Tri::False); + assert_eq!(a.eq(&iv(2.0, 3.0)), Tri::Both); + // Exact comparison across decimal and dyadic spellings. + assert_eq!( + Ival::point(dec("0.3")).eq(&Ival::point(dec("0.1")).add(&Ival::point(dec("0.2")))), + Tri::True + ); } #[test] @@ -1243,6 +1552,18 @@ mod tests { IntIval::new(0, 7).trem(IntIval::new(3, 3)), IntIval::new(0, 2) ); + // Saturated integer endpoints read as unbounded reals, and + // inward rounding brings them back. + assert_eq!(IntIval::TOP.to_ival(), Ival::top()); + assert_eq!(ival_to_int(&Ival::top()), IntIval::TOP); + assert_eq!( + ival_to_int(&Ival::new(Ext::Fin(dec("0.5")), Ext::Fin(dec("3.5")))), + IntIval::new(1, 3) + ); + assert_eq!( + ival_to_int(&Ival::new(Ext::Fin(dec("-1e50")), Ext::Fin(dec("1e50")))), + IntIval::TOP + ); } #[test] @@ -1257,23 +1578,6 @@ mod tests { assert_eq!(x.trem(IntIval::new(2, 5)), IntIval::new(-4, 4)); } - #[test] - fn overflow_clamps_instead_of_fabricating_empty() { - // An overflowed lower endpoint clamps to MAX rather than minting - // the degenerate point [+∞, +∞]… - let big = Ival::new(1e308, f64::INFINITY); - let s = big.add(big); - assert!(s.lo.is_finite() && s.hi == f64::INFINITY, "{s:?}"); - // …so ∞ − ∞ (NaN → EMPTY, a false unsat proof) can't arise. - let d = s.sub(s); - assert!(!d.is_empty() && d.contains(0.0), "{d:?}"); - // Same through multiplication overflow. - let p = Ival::point(1e200).mul(Ival::point(1e200)); - assert!(p.lo.is_finite() && p.hi == f64::INFINITY, "{p:?}"); - // And NaN reaching the constructor widens instead of emptying. - assert_eq!(Ival::new(f64::NAN, f64::NAN), Ival::TOP); - } - #[test] fn tri_logic() { use Tri::*; @@ -1292,17 +1596,198 @@ mod tests { let all = EnumSet::all(3); let a = EnumSet::point(0); let b = EnumSet::point(2); - assert_eq!(a.eq(b), Tri::False); - assert_eq!(a.eq(a), Tri::True); - assert_eq!(a.eq(all), Tri::Both); - assert!(a.hull(b).contains(0) && a.hull(b).contains(2) && !a.hull(b).contains(1)); + assert_eq!(a.eq(&b), Tri::False); + assert_eq!(a.eq(&a), Tri::True); + assert_eq!(a.eq(&all), Tri::Both); + let ab = a.hull(&b); + assert!(ab.contains(0) && ab.contains(2) && !ab.contains(1)); + assert_eq!(all.minus(&a), EnumSet::point(1).hull(&b)); + assert!(all.minus(&all).is_empty()); } #[test] - fn real_lit_round_trip() { + fn enum_sets_are_not_bounded_at_128_literals() { + // Positions past 128 are distinct members, never aliases of the + // low positions: literal 129 and literal 1 must not compare + // equal, and removing one leaves the other. + let all = EnumSet::all(130); + assert!(all.contains(0) && all.contains(127) && all.contains(129)); + assert!(!all.contains(130) && !all.contains(64 * 3)); + let hi = EnumSet::point(129); + let lo = EnumSet::point(1); + assert_ne!(hi, lo); + assert_eq!(hi.eq(&lo), Tri::False); + assert_eq!(hi.eq(&hi), Tri::True); + assert_eq!(all.intersect(&hi), hi); + let rest = all.minus(&hi); + assert!(rest.contains(1) && rest.contains(128) && !rest.contains(129)); + assert!(rest.intersect(&hi).is_empty()); + assert!(!rest.is_point() && all.minus(&rest).is_point()); + // Word-boundary widths. + assert!(EnumSet::all(64).contains(63) && !EnumSet::all(64).contains(64)); + assert!(EnumSet::all(65).contains(64)); + assert!(EnumSet::all(0).is_empty()); + } + + #[test] + fn real_literals_are_exact_points() { for f in [0.0, 1.0, -2.5, 3.15, 0.001, 1e10, -1e-10, 12345.6789] { - let s = crate::term::real_from_f64(f).unwrap(); - assert_eq!(real_lit(&s), Some(f), "{s}"); + let r = Rational::from_f64(f).unwrap(); + assert_eq!( + eval_term(&Term::RealLit(r.clone()), &[]), + Dom::R(Ival::point(r)) + ); + } + let tenth = dec("0.1"); + assert_eq!( + eval_term(&Term::RealLit(tenth.clone()), &[]), + Dom::R(Ival::point(tenth)) + ); + } + + // -- propagation exactness --------------------------------------------- + + #[test] + fn literal_bounds_propagate_exactly() { + // x ≥ 0.8 ∧ x ≤ 1.1 over a real variable: the narrowed domain is + // spelled exactly as the literals, not as their double + // neighbours. + let x = Term::Var(0); + let facts = vec![ + Term::App(Op::Ge, vec![x.clone(), Term::RealLit(dec("0.8"))]), + Term::App(Op::Le, vec![x.clone(), Term::RealLit(dec("1.1"))]), + ]; + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &facts, 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[0], &[], false), "[0.8, 1.1]"); + assert_eq!(fmt_dom(&doms[0], &[], true), "[0.8, 1.1]"); + // Bounds derived through arithmetic stay exact too: y = x + 0.2. + let y = Term::Var(1); + let facts = vec![ + Term::App(Op::Ge, vec![x.clone(), Term::RealLit(dec("0.8"))]), + Term::App(Op::Le, vec![x.clone(), Term::RealLit(dec("1.1"))]), + Term::App( + Op::Eq, + vec![ + y, + Term::App(Op::Add, vec![x.clone(), Term::RealLit(dec("0.2"))]), + ], + ), + ]; + let (doms, unsat) = drive(vec![Dom::R(Ival::top()), Dom::R(Ival::top())], &facts, 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[1], &[], false), "[1, 1.3]"); + // A non-terminating bound prints as a fraction exactly and as a + // marked decimal for hints. + let facts = vec![Term::App( + Op::Ge, + vec![ + x.clone(), + Term::App( + Op::Div, + vec![Term::RealLit(dec("1")), Term::RealLit(dec("3"))], + ), + ], + )]; + let (doms, _) = drive(vec![Dom::R(Ival::top())], &facts, 100); + assert_eq!(fmt_dom(&doms[0], &[], false), "[1/3, +∞]"); + assert_eq!(fmt_dom(&doms[0], &[], true), "[≈0.3333333333333333, +∞]"); + // Equality against an exact sum is decided exactly: 0.1 + 0.2 + // is 0.3, so demanding both is satisfiable. + let facts = vec![ + Term::App( + Op::Eq, + vec![ + x.clone(), + Term::App( + Op::Add, + vec![Term::RealLit(dec("0.1")), Term::RealLit(dec("0.2"))], + ), + ], + ), + Term::App(Op::Eq, vec![x, Term::RealLit(dec("0.3"))]), + ]; + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &facts, 100); + assert!(!unsat, "{doms:?}"); + assert_eq!(fmt_dom(&doms[0], &[], false), "[0.3, 0.3]"); + } + + #[test] + fn half_line_tightens_again() { + // The finite side of a half-line keeps moving: the progress + // tolerance is scaled from finite endpoints only, so + // [10, +∞] → [12, +∞] counts as progress (and so does the + // mirror image on the upper side). + let x = Term::Var(0); + let ge = |k: &str| Term::App(Op::Ge, vec![x.clone(), Term::RealLit(dec(k))]); + let le = |k: &str| Term::App(Op::Le, vec![x.clone(), Term::RealLit(dec(k))]); + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &[ge("10"), ge("12")], 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[0], &[], false), "[12, +∞]"); + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &[le("10"), le("8")], 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[0], &[], false), "[−∞, 8]"); + // A large second bound on a half-line already open at zero, then + // a weaker third one that the tightened domain settles. + let facts = [ge("0"), ge("1000"), ge("500")]; + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &facts, 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[0], &[], false), "[1000, +∞]"); + assert_eq!(eval_term(&facts[2], &doms), Dom::B(Tri::True)); + } + + #[test] + fn deep_chains_evaluate_each_operand_once() { + // A left-deep chain of depth 30 (the shape of a `sum` fold or a + // quantifier expansion) evaluates in linear time; doubling the + // work per level would take 2^30 operand evaluations. + let mut chain = Term::Var(0); + for i in 1..=30 { + chain = Term::App(Op::Add, vec![chain, Term::Var(i)]); + } + let mut doms: Vec = (0..=30) + .map(|i| Dom::R(iv(f64::from(i), f64::from(i) + 1.0))) + .collect(); + let start = std::time::Instant::now(); + let whole = eval_term(&chain, &doms); + // Σ [i, i+1] for i in 0..=30. + assert_eq!(fmt_dom(&whole, &[], false), "[465, 496]"); + doms.push(Dom::R(Ival::top())); + let facts = vec![Term::App(Op::Eq, vec![Term::Var(31), chain])]; + let (doms, unsat) = drive(doms, &facts, 100); + assert!(!unsat); + assert_eq!(fmt_dom(&doms[31], &[], false), "[465, 496]"); + assert!( + start.elapsed() < std::time::Duration::from_secs(1), + "deep chain took {:?}", + start.elapsed() + ); + } + + #[test] + fn fixpoint_terminates_on_crawling_contractions() { + // x = x / 2 contracts by halves forever; the progress epsilon and + // the pass cap stop it, and the endpoints stay within budget. + let x = Term::Var(0); + let facts = vec![ + Term::App(Op::Ge, vec![x.clone(), Term::RealLit(dec("0"))]), + Term::App(Op::Le, vec![x.clone(), Term::RealLit(dec("1"))]), + Term::App( + Op::Eq, + vec![ + x.clone(), + Term::App(Op::Div, vec![x, Term::RealLit(dec("2"))]), + ], + ), + ]; + let (doms, unsat) = drive(vec![Dom::R(Ival::top())], &facts, 100); + assert!(!unsat); + let Dom::R(d) = &doms[0] else { + panic!("{doms:?}") + }; + assert!(d.contains_zero()); + if let Ext::Fin(hi) = &d.hi { + assert!(hi.bits() <= MAX_ENDPOINT_BITS + 64, "{d:?}"); } } @@ -1336,7 +1821,7 @@ mod tests { return match r.pick(2) { 0 => Term::Var(r.pick(nvars)), _ => Term::RealLit( - crate::term::real_from_f64((r.f64_in(-8.0, 8.0) * 4.0).round() / 4.0).unwrap(), + Rational::from_f64((r.f64_in(-8.0, 8.0) * 4.0).round() / 4.0).unwrap(), ), }; } @@ -1365,8 +1850,8 @@ mod tests { let a = r.f64_in(-10.0, 10.0); let b = r.f64_in(-10.0, 10.0); let (lo, hi) = if a <= b { (a, b) } else { (b, a) }; - doms.push(Dom::R(Ival::new(lo, hi))); - pts.push(Dom::R(Ival::point(r.f64_in(lo, hi)))); + doms.push(Dom::R(iv(lo, hi))); + pts.push(Dom::R(pt(r.f64_in(lo, hi)))); } let whole = eval_term(&t, &doms); let point = eval_term(&t, &pts); @@ -1396,8 +1881,8 @@ mod tests { let a = r.f64_in(-6.0, 6.0); let b = r.f64_in(-6.0, 6.0); let (lo, hi) = if a <= b { (a, b) } else { (b, a) }; - doms.push(Dom::R(Ival::new(lo, hi))); - pts.push(Dom::R(Ival::point(r.f64_in(lo, hi)))); + doms.push(Dom::R(iv(lo, hi))); + pts.push(Dom::R(pt(r.f64_in(lo, hi)))); } let (Dom::B(w), Dom::B(p)) = (eval_term(&t, &doms), eval_term(&t, &pts)) else { panic!("comparison evaluated to non-boolean domains"); @@ -1410,4 +1895,84 @@ mod tests { ); } } + + /// A quarter-integer in `[−8, 8]`: exact both as a rational and as a + /// double, so a sampled coordinate is never blurred by conversion. + fn quarter(r: &mut Lcg) -> Rational { + Rational::from_f64((r.f64_in(-8.0, 8.0) * 4.0).round() / 4.0).expect("a finite sample") + } + + #[test] + fn the_fixpoint_keeps_every_satisfying_point() { + // The propagation invariant, sampled: the domains the fixpoint + // derives contain *every* assignment satisfying the facts, so a + // point known to satisfy them must survive. Narrowing one away + // would fabricate a refutation — the one way this backend can be + // unsound. (The other property suites cover the forward pass + // alone; this one drives the backward pass and the fixpoint.) + const NVARS: usize = 3; + let mut r = Lcg(0x05EE_D5A7); + let mut exercised = 0usize; + for _ in 0..2000 { + let point: Vec = (0..NVARS).map(|_| quarter(&mut r)).collect(); + let pts: Vec = point + .iter() + .map(|x| Dom::R(Ival::point(x.clone()))) + .collect(); + // Facts that hold at the sampled point by construction: a + // bound placed clear of the term's value there. Evaluating at + // a point may still widen (division), so the bound is taken + // from the widened end — anything it admits, the true value + // admits too. + let mut facts = Vec::new(); + for _ in 0..=r.pick(4) { + let t = random_term(&mut r, 3, NVARS); + let Dom::R(at) = eval_term(&t, &pts) else { + continue; + }; + let slack = quarter(&mut r).abs(); + let prefer_lower = r.pick(2) == 0; + let bound = match (&at.lo, &at.hi) { + (Ext::Fin(lo), Ext::Fin(hi)) => { + if prefer_lower { + Some((Op::Ge, lo.sub(&slack))) + } else { + Some((Op::Le, hi.add(&slack))) + } + } + (Ext::Fin(lo), _) => Some((Op::Ge, lo.sub(&slack))), + (_, Ext::Fin(hi)) => Some((Op::Le, hi.add(&slack))), + // The term is unbounded at the point (a division by + // zero): no bound can be asserted from it. + _ => None, + }; + if let Some((op, k)) = bound { + facts.push(Term::App(op, vec![t, Term::RealLit(k)])); + } + } + if facts.is_empty() { + continue; + } + exercised += 1; + let init: Vec = (0..NVARS).map(|_| Dom::R(Ival::top())).collect(); + let (doms, unsat) = drive(init, &facts, 100); + assert!( + !unsat, + "a system satisfied by {point:?} was refuted: {facts:?}" + ); + for (i, x) in point.iter().enumerate() { + let Dom::R(d) = &doms[i] else { + panic!("a real variable ended in {:?}", doms[i]); + }; + assert!( + d.contains_rational(x), + "{x} was narrowed out of {d:?} by {facts:?}" + ); + } + } + assert!( + exercised > 1000, + "too few systems reached the fixpoint: {exercised}" + ); + } } diff --git a/crates/sysmlv2-solve/src/lib.rs b/crates/sysmlv2-solve/src/lib.rs index 75667dd..4f59b6e 100644 --- a/crates/sysmlv2-solve/src/lib.rs +++ b/crates/sysmlv2-solve/src/lib.rs @@ -35,6 +35,7 @@ mod translate; mod z3; use std::fmt; +use std::fmt::Write as _; use std::path::PathBuf; pub use sysmlv2_model::check::ConstraintBinding; use sysmlv2_model::check::{ConstraintVerdict, constraint_bindings, constraint_verdict}; @@ -69,11 +70,19 @@ impl SolverConfig { } /// A witness value for one unbound feature. +/// +/// New kinds of value may be decoded in future releases, so a `match` +/// over this needs a catch-all arm. #[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] pub enum WitnessValue { + /// A boolean value. Bool(bool), + /// An integer value, exact within the machine range. Int(i128), - Real(f64), + /// An exact real value, as the solver printed it (a decimal or a + /// fraction), with no rounding through a double. + Real(sysmlv2_model::rational::Rational), /// An enumeration literal, by declared name. Enum(String), /// A value in an inferred measurement unit (e.g. `30 [d]`) — units are @@ -97,7 +106,11 @@ impl fmt::Display for WitnessValue { } /// What solving concluded about one undecided constraint. +/// +/// New conclusions may be added in future releases, so a `match` over +/// this needs a catch-all arm; treat an unrecognized one as undecided. #[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] pub enum SolveOutcome { /// Holds for every assignment of the unbound features. Valid, @@ -134,25 +147,67 @@ pub struct SolvedConstraint { } /// Why solving could not run at all. +/// +/// New reasons may be added in future releases, so a `match` over this +/// needs a catch-all arm. #[derive(Debug)] +#[non_exhaustive] pub enum SolveError { - /// The Z3 binary was not found or did not identify itself. - SolverUnavailable(String), + /// The Z3 binary could not be started, or started but did not + /// identify itself. + SolverUnavailable { + /// The binary that was tried: [`SolverConfig::z3_path`], or plain + /// `z3` to be looked up on `PATH`. + path: PathBuf, + /// What the operating system reported — `NotFound` when there is + /// no such binary, `PermissionDenied` when it is not executable, + /// and so on. `None` when the binary did run but printed no + /// version banner. Also reachable as + /// [`std::error::Error::source`]. + source: Option, + }, } impl fmt::Display for SolveError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { - SolveError::SolverUnavailable(m) => write!(f, "Z3 is not available: {m}"), + SolveError::SolverUnavailable { + path, + source: Some(e), + } => write!( + f, + "Z3 is not available: cannot run `{}`: {e}", + path.display() + ), + SolveError::SolverUnavailable { path, source: None } => write!( + f, + "Z3 is not available: `{} -version` printed nothing", + path.display() + ), } } } -impl std::error::Error for SolveError {} +impl std::error::Error for SolveError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + SolveError::SolverUnavailable { source, .. } => source + .as_ref() + .map(|e| e as &(dyn std::error::Error + 'static)), + } + } +} /// The configured Z3's version banner (the availability probe). +/// +/// # Errors +/// +/// [`SolveError::SolverUnavailable`] when the binary cannot be started — +/// its `source` distinguishes a missing binary from an unreadable one — +/// or when it starts but prints no banner. pub fn z3_version(cfg: &SolverConfig) -> Result { - z3::version(&cfg.z3()).map_err(SolveError::SolverUnavailable) + let path = cfg.z3(); + z3::version(&path).map_err(|source| SolveError::SolverUnavailable { path, source }) } /// Check every constraint of `model` (library units skipped) exactly like @@ -163,14 +218,15 @@ pub fn solve_constraints( ) -> Result, SolveError> { z3_version(cfg)?; let mut r = ResolvedModel::build(model); + let tables = translate::EnumTables::build(&r); let mut out = Vec::new(); for c in r.constraints() { - if model.units()[c.unit].is_library { + if model.is_library_unit(c.unit) { continue; } let verdict = constraint_verdict(&mut r, &c); let solve = match &verdict { - ConstraintVerdict::Undecided(_) => Some(solve_one(&mut r, &c, cfg, None)), + ConstraintVerdict::Undecided(_) => Some(solve_one(&mut r, &tables, &c, cfg, None)), _ => None, }; let bindings = match verdict { @@ -216,8 +272,14 @@ pub struct FeatureRange { pub feature: String, /// Inferred measurement unit (display spelling), if any. pub unit: Option, - /// Rendered range or set (`[10, +∞]`, `[3, 7]`, `{Red, Green}`). + /// Rendered range or set (`[10, +∞]`, `[3, 7]`, `{Red, Green}`), with + /// exact real endpoints: a terminating decimal or a reduced fraction. pub range: String, + /// [`Self::range`] for glanceable surfaces such as editor hints: a + /// real endpoint without a terminating decimal expansion renders as + /// a marked approximate decimal (`≈0.3333333333333333`) instead of a + /// fraction. + pub range_approx: String, /// Whether propagation tightened the domain past its declared type. pub narrowed: bool, } @@ -225,7 +287,11 @@ pub struct FeatureRange { /// What propagation concluded about one undecided constraint. All verdicts /// are definitive (the narrowed domains contain every satisfying /// assignment), never heuristic. +/// +/// New conclusions may be added in future releases, so a `match` over +/// this needs a catch-all arm; treat an unrecognized one as undecided. #[derive(Clone, Debug, PartialEq)] +#[non_exhaustive] pub enum PropagateOutcome { /// The body's forward interval is `{true}`: holds for every assignment /// consistent with the narrowed domains. @@ -285,12 +351,14 @@ pub struct Propagation { /// interval propagation over each unit's asserted constraints jointly — /// narrowing every free feature's domain, upgrading verdicts definitively, /// and proving empty domains inconsistent — without any external solver. +#[must_use] pub fn propagate_constraints(model: &Model, cfg: &PropagateConfig) -> Propagation { let mut r = ResolvedModel::build(model); + let tables = translate::EnumTables::build(&r); let all = user_constraints(&mut r, model); let verdicts: Vec = all.iter().map(|c| constraint_verdict(&mut r, c)).collect(); - let (outcomes, ranges, features) = propagate_core(&mut r, &all, &verdicts, cfg); + let (outcomes, ranges, features) = propagate_core(&mut r, &tables, &all, &verdicts, cfg); let constraints = all .iter() .enumerate() @@ -325,7 +393,7 @@ fn user_constraints( ) -> Vec { r.constraints() .into_iter() - .filter(|c| !model.units()[c.unit].is_library) + .filter(|c| !model.is_library_unit(c.unit)) .collect() } @@ -350,6 +418,7 @@ fn propagation_is_definitive(o: &Option) -> bool { /// [`verify_constraints`]. fn propagate_core( r: &mut ResolvedModel, + tables: &translate::EnumTables, all: &[sysmlv2_model::json::ConstraintInfo], verdicts: &[ConstraintVerdict], cfg: &PropagateConfig, @@ -376,7 +445,7 @@ fn propagate_core( for (_, idxs) in &by_unit { let cs: Vec<&sysmlv2_model::json::ConstraintInfo> = idxs.iter().map(|&i| &all[i]).collect(); - let jt = match translate::translate_all(r, &cs) { + let jt = match translate::translate_all(r, tables, &cs) { Ok(jt) => jt, Err(translate::Unsupported(m)) => { for &i in idxs { @@ -417,10 +486,14 @@ fn propagate_core( let (doms, _unsat) = ival::drive(baseline.clone(), &facts, cfg.max_iters); for (vi, v) in jt.vars.iter().enumerate() { + if v.aux { + continue; + } ranges.push(FeatureRange { feature: v.display.clone(), unit: v.unit.clone(), - range: ival::fmt_dom(doms[vi], &jt.enums), + range: ival::fmt_dom(&doms[vi], &jt.enums, false), + range_approx: ival::fmt_dom(&doms[vi], &jt.enums, true), narrowed: doms[vi] != baseline[vi], }); } @@ -440,7 +513,11 @@ fn propagate_core( } translate::JointRoot::Skipped(_) => {} } - features[i] = vs.iter().map(|&v| jt.vars[v].display.clone()).collect(); + features[i] = vs + .iter() + .filter(|&&v| !jt.vars[v].aux) + .map(|&v| jt.vars[v].display.clone()) + .collect(); } outcomes[i] = Some(match &jt.roots[k] { translate::JointRoot::Skipped(m) => PropagateOutcome::Unsupported(m.clone()), @@ -519,7 +596,10 @@ pub struct VerifiedConstraint { /// narrowed feature ranges. #[derive(Clone, Debug)] pub struct VerifyReport { + /// One entry per non-library constraint, in model order. pub constraints: Vec, + /// Narrowed feature domains, in first-encountered order (see + /// [`Propagation::ranges`]). pub ranges: Vec, } @@ -539,10 +619,11 @@ pub fn verify_constraints( z3_version(cfg)?; } let mut r = ResolvedModel::build(model); + let tables = translate::EnumTables::build(&r); let all = user_constraints(&mut r, model); let verdicts: Vec = all.iter().map(|c| constraint_verdict(&mut r, c)).collect(); - let (propagate, ranges, features) = propagate_core(&mut r, &all, &verdicts, prop_cfg); + let (propagate, ranges, features) = propagate_core(&mut r, &tables, &all, &verdicts, prop_cfg); let mut constraints = Vec::with_capacity(all.len()); for (i, c) in all.iter().enumerate() { @@ -553,7 +634,7 @@ pub fn verify_constraints( if matches!(verdicts[i], ConstraintVerdict::Undecided(_)) && !propagation_is_definitive(&propagate[i]) => { - Some(solve_one(&mut r, c, cfg, Some(prop_cfg))) + Some(solve_one(&mut r, &tables, c, cfg, Some(prop_cfg))) } _ => None, }; @@ -584,6 +665,9 @@ pub fn verify_constraints( /// (`(assert (>= x lo))`, enum membership, boolean fixing). Infinite / /// saturated endpoints and full domains contribute nothing. These are /// sound to add **only** to the "can it hold?" query — see [`solve_one`]. +/// +/// Writing into a `String` cannot fail, so the formatting results are +/// discarded rather than propagated. fn domain_bound_asserts( vars: &[translate::VarInfo], doms: &[ival::Dom], @@ -591,51 +675,45 @@ fn domain_bound_asserts( ) -> String { let mut out = String::new(); for (i, v) in vars.iter().enumerate() { - match doms[i] { + match &doms[i] { ival::Dom::R(iv) => { - if iv.lo.is_finite() { - if let Some(l) = term::real_from_f64(iv.lo) { - out.push_str(&format!("(assert (>= {} {l}))\n", v.sym)); - } + if let ival::Ext::Fin(l) = &iv.lo { + let l = term::render_real(l); + let _ = writeln!(out, "(assert (>= {} {l}))", v.sym); } - if iv.hi.is_finite() { - if let Some(h) = term::real_from_f64(iv.hi) { - out.push_str(&format!("(assert (<= {} {h}))\n", v.sym)); - } + if let ival::Ext::Fin(h) = &iv.hi { + let h = term::render_real(h); + let _ = writeln!(out, "(assert (<= {} {h}))", v.sym); } } ival::Dom::I(iv) => { if iv.lo != i128::MIN { - out.push_str(&format!( - "(assert (>= {} {}))\n", - v.sym, - term::render_int(iv.lo) - )); + let _ = writeln!(out, "(assert (>= {} {}))", v.sym, term::render_int(iv.lo)); } if iv.hi != i128::MAX { - out.push_str(&format!( - "(assert (<= {} {}))\n", - v.sym, - term::render_int(iv.hi) - )); + let _ = writeln!(out, "(assert (<= {} {}))", v.sym, term::render_int(iv.hi)); } } - ival::Dom::B(ival::Tri::True) => out.push_str(&format!("(assert {})\n", v.sym)), - ival::Dom::B(ival::Tri::False) => out.push_str(&format!("(assert (not {}))\n", v.sym)), + ival::Dom::B(ival::Tri::True) => { + let _ = writeln!(out, "(assert {})", v.sym); + } + ival::Dom::B(ival::Tri::False) => { + let _ = writeln!(out, "(assert (not {}))", v.sym); + } ival::Dom::E(s, set) => { // A strict, non-empty subset of the enum's literals. - let lits: Vec = enums[s] + let lits: Vec = enums[*s] .ctors .iter() .enumerate() .filter(|(j, _)| set.contains(*j)) .map(|(_, ctor)| format!("(= {} {ctor})", v.sym)) .collect(); - if !lits.is_empty() && lits.len() < enums[s].ctors.len() { + if !lits.is_empty() && lits.len() < enums[*s].ctors.len() { if lits.len() == 1 { - out.push_str(&format!("(assert {})\n", lits[0])); + let _ = writeln!(out, "(assert {})", lits[0]); } else { - out.push_str(&format!("(assert (or {}))\n", lits.join(" "))); + let _ = writeln!(out, "(assert (or {}))", lits.join(" ")); } } } @@ -659,11 +737,12 @@ fn domain_bound_asserts( /// clipping it away would fake a validity proof. fn solve_one( r: &mut ResolvedModel, + tables: &translate::EnumTables, c: &sysmlv2_model::json::ConstraintInfo, cfg: &SolverConfig, propagate_bounds: Option<&PropagateConfig>, ) -> SolveOutcome { - let tr = match translate::translate(r, c) { + let tr = match translate::translate(r, tables, c) { Ok(tr) => tr, Err(translate::Unsupported(m)) => { return SolveOutcome::Unknown(format!("not in the solvable fragment: {m}")); @@ -681,26 +760,27 @@ fn solve_one( Ok(g) => g, Err(e) => return internal(e), }; + // Writing into a `String` cannot fail, so every formatting result + // here is discarded rather than propagated. let mut decls = String::new(); - decls.push_str(&format!("(set-option :timeout {})\n", cfg.timeout_ms)); + let _ = writeln!(decls, "(set-option :timeout {})", cfg.timeout_ms); for e in &tr.enums { let ctors: Vec = e.ctors.iter().map(|c| format!("({c})")).collect(); - decls.push_str(&format!( - "(declare-datatypes (({} 0)) (({})))\n", + let _ = writeln!( + decls, + "(declare-datatypes (({} 0)) (({})))", e.sym, ctors.join(" ") - )); + ); } for v in &tr.vars { - decls.push_str(&format!( - "(declare-const {} {})\n", - v.sym, - ctx.sort_name(v.sort) - )); + let _ = writeln!(decls, "(declare-const {} {})", v.sym, ctx.sort_name(v.sort)); } for s in &tr.side { match ctx.render(s) { - Ok((t, _)) => decls.push_str(&format!("(assert {t})\n")), + Ok((t, _)) => { + let _ = writeln!(decls, "(assert {t})"); + } Err(e) => return internal(e), } } @@ -760,6 +840,7 @@ fn solve_one( .vars .iter() .zip(&witness) + .filter(|(v, _)| !v.aux) .map(|(v, val)| { let decoded = decode_value(val, &tr.enums); let decoded = match &v.unit { @@ -796,8 +877,8 @@ fn decode_value(s: &SExpr, enums: &[term::EnumSort]) -> WitnessValue { return Some(WitnessValue::Int(i)); } if a.contains('.') { - if let Ok(f) = a.parse::() { - return Some(WitnessValue::Real(f)); + if let Some(r) = sysmlv2_model::rational::Rational::parse_decimal(a) { + return Some(WitnessValue::Real(r)); } } for e in enums { @@ -810,21 +891,22 @@ fn decode_value(s: &SExpr, enums: &[term::EnumSort]) -> WitnessValue { SExpr::List(items) => match items.as_slice() { [SExpr::Atom(op), x] if op == "-" => match go(x, enums)? { WitnessValue::Int(i) => Some(WitnessValue::Int(-i)), - WitnessValue::Real(f) => Some(WitnessValue::Real(-f)), + WitnessValue::Real(r) => Some(WitnessValue::Real(r.neg())), _ => None, }, [SExpr::Atom(op), a, b] if op == "/" => { + use sysmlv2_model::rational::Rational; let num = match go(a, enums)? { - WitnessValue::Int(i) => i as f64, - WitnessValue::Real(f) => f, + WitnessValue::Int(i) => Rational::from_integer(i), + WitnessValue::Real(r) => r, _ => return None, }; let den = match go(b, enums)? { - WitnessValue::Int(i) => i as f64, - WitnessValue::Real(f) => f, + WitnessValue::Int(i) => Rational::from_integer(i), + WitnessValue::Real(r) => r, _ => return None, }; - Some(WitnessValue::Real(num / den)) + Some(WitnessValue::Real(num.div(&den)?)) } _ => None, }, @@ -846,7 +928,7 @@ mod witness_containment { use crate::ival::Dom; use crate::term::EnumSort; - fn dom_contains(val: &WitnessValue, d: Dom, enums: &[EnumSort]) -> bool { + fn dom_contains(val: &WitnessValue, d: &Dom, enums: &[EnumSort]) -> bool { // A quantity witness carries its magnitude in the same reference // scale the term (and thus the domain) uses. let val = match val { @@ -855,9 +937,11 @@ mod witness_containment { }; match (val, d) { (WitnessValue::Int(i), Dom::I(iv)) => iv.contains(*i), - (WitnessValue::Int(i), Dom::R(rv)) => rv.contains(*i as f64), - (WitnessValue::Real(f), Dom::R(rv)) => rv.contains(*f), - (WitnessValue::Real(f), Dom::I(iv)) => iv.to_ival().contains(*f), + (WitnessValue::Int(i), Dom::R(rv)) => { + rv.contains_rational(&sysmlv2_model::rational::Rational::from_integer(*i)) + } + (WitnessValue::Real(r), Dom::R(rv)) => rv.contains_rational(r), + (WitnessValue::Real(r), Dom::I(iv)) => iv.to_ival().contains_rational(r), (WitnessValue::Bool(b), Dom::B(t)) => { if *b { t.may_true() @@ -865,7 +949,7 @@ mod witness_containment { t.may_false() } } - (WitnessValue::Enum(name), Dom::E(s, set)) => enums[s] + (WitnessValue::Enum(name), Dom::E(s, set)) => enums[*s] .displays .iter() .enumerate() @@ -891,9 +975,10 @@ mod witness_containment { model.add_source(f.file_name().unwrap().to_string_lossy().into_owned(), &src); } let mut r = ResolvedModel::build(&model); + let tables = translate::EnumTables::build(&r); let mut checked = 0usize; for c in r.constraints() { - if model.units()[c.unit].is_library { + if model.is_library_unit(c.unit) { continue; } if !matches!( @@ -902,14 +987,15 @@ mod witness_containment { ) { continue; } - let SolveOutcome::Satisfiable(pairs) = solve_one(&mut r, &c, &cfg, None) else { + let SolveOutcome::Satisfiable(pairs) = solve_one(&mut r, &tables, &c, &cfg, None) + else { continue; }; // Re-translate the identical single constraint and propagate its // asserted system {root} ∪ declared-type side facts — exactly // what Z3's first query asserted. Determinism guarantees the // variable order matches the witness pairs. - let Ok(tr) = translate::translate(&mut r, &c) else { + let Ok(tr) = translate::translate(&mut r, &tables, &c) else { continue; }; let enum_sizes: Vec = tr.enums.iter().map(|e| e.ctors.len()).collect(); @@ -921,18 +1007,21 @@ mod witness_containment { let mut facts = tr.side.clone(); facts.push(tr.root.clone()); let (doms, unsat) = ival::drive(init, &facts, PropagateConfig::default().max_iters); - let where_ = &model.units()[c.unit].name; + let where_ = &model.unit(c.unit).name; assert!( !unsat, "propagation proved unsat but Z3 found a witness: {:?} in {where_}", c.name ); - assert_eq!(pairs.len(), tr.vars.len(), "witness/var count mismatch"); - for (k, (disp, val)) in pairs.iter().enumerate() { + // Auxiliaries are part of the variable space but never + // witnessed; the reported pairs align with the rest. + let reported: Vec = (0..tr.vars.len()).filter(|&k| !tr.vars[k].aux).collect(); + assert_eq!(pairs.len(), reported.len(), "witness/var count mismatch"); + for (&k, (disp, val)) in reported.iter().zip(&pairs) { assert!( - dom_contains(val, doms[k], &tr.enums), + dom_contains(val, &doms[k], &tr.enums), "witness {disp} = {val} escapes propagated range {} ({:?} in {where_})", - ival::fmt_dom(doms[k], &tr.enums), + ival::fmt_dom(&doms[k], &tr.enums, false), c.name ); } @@ -959,6 +1048,7 @@ mod bound_injection { sym: sym.into(), sort, unit: None, + aux: false, } } @@ -977,11 +1067,11 @@ mod bound_injection { var("free", Sort::Real), ]; let doms = vec![ - Dom::R(Ival::new(10.0, f64::INFINITY)), // one-sided real - Dom::I(IntIval::new(0, 5)), // closed integer - Dom::B(Tri::True), // fixed boolean - Dom::E(0, EnumSet { bits: 0b101 }), // {halt, init} - Dom::R(Ival::TOP), // nothing to say + Dom::R(Ival::from_f64(10.0, f64::INFINITY)), // one-sided real + Dom::I(IntIval::new(0, 5)), // closed integer + Dom::B(Tri::True), // fixed boolean + Dom::E(0, EnumSet::all(3).minus(&EnumSet::point(1))), // {halt, init} + Dom::R(Ival::top()), // nothing to say ]; let out = domain_bound_asserts(&vars, &doms, &enums); assert!(out.contains("(assert (>= x 10.0))"), "{out}"); @@ -1027,9 +1117,10 @@ mod bound_injection { model.add_source(f.file_name().unwrap().to_string_lossy().into_owned(), &src); } let mut r = ResolvedModel::build(&model); + let tables = translate::EnumTables::build(&r); let (mut agree, mut improved, mut regressed) = (0usize, 0usize, 0usize); for c in r.constraints() { - if model.units()[c.unit].is_library { + if model.is_library_unit(c.unit) { continue; } if !matches!( @@ -1038,9 +1129,9 @@ mod bound_injection { ) { continue; } - let plain = solve_one(&mut r, &c, &cfg, None); - let bounded = solve_one(&mut r, &c, &cfg, Some(&PropagateConfig::default())); - let where_ = &model.units()[c.unit].name; + let plain = solve_one(&mut r, &tables, &c, &cfg, None); + let bounded = solve_one(&mut r, &tables, &c, &cfg, Some(&PropagateConfig::default())); + let where_ = &model.unit(c.unit).name; match (discriminant(&plain), discriminant(&bounded)) { (Some(a), Some(b)) => { assert_eq!( diff --git a/crates/sysmlv2-solve/src/term.rs b/crates/sysmlv2-solve/src/term.rs index f1bc15d..f917cb1 100644 --- a/crates/sysmlv2-solve/src/term.rs +++ b/crates/sysmlv2-solve/src/term.rs @@ -5,6 +5,8 @@ //! finalization and inserts `to_real` coercions wherever `Int`- and //! `Real`-sorted operands mix (SMT-LIB has no implicit numeric widening). +use sysmlv2_model::rational::Rational; + /// SMT sort of a term. `Enum` carries an index into the translation's enum /// sort table. #[derive(Clone, Copy, PartialEq, Eq, Debug)] @@ -45,8 +47,8 @@ pub(crate) enum Op { pub(crate) enum Term { BoolLit(bool), IntLit(i128), - /// Pre-rendered SMT real literal (`3.14`, `(/ 1.0 2.0)`, `(- 0.5)`). - RealLit(String), + /// Exact real literal; rendered as `3.0` or `(/ 3.0 10.0)`. + RealLit(Rational), /// String literal (unescaped; rendering doubles interior quotes). StrLit(String), /// Free variable — index into the translation's variable table. @@ -110,7 +112,7 @@ impl RenderCtx<'_> { match t { Term::BoolLit(b) => Ok((b.to_string(), Sort::Bool)), Term::IntLit(i) => Ok((render_int(*i), Sort::Int)), - Term::RealLit(s) => Ok((s.clone(), Sort::Real)), + Term::RealLit(r) => Ok((render_real(r), Sort::Real)), Term::StrLit(s) => Ok((format!("\"{}\"", s.replace('"', "\"\"")), Sort::Str)), Term::Var(i) => Ok((self.var_syms[*i].clone(), self.var_sorts[*i])), Term::EnumLit(s, c) => Ok((self.enums[*s].ctors[*c].clone(), Sort::Enum(*s))), @@ -261,31 +263,18 @@ pub(crate) fn render_int(i: i128) -> String { } } -/// Exact SMT real literal for a finite `f64` (every finite double is a -/// dyadic rational). `None` when the exact fraction would overflow the -/// integer rendering (astronomically large or tiny magnitudes). -pub(crate) fn real_from_f64(f: f64) -> Option { - if !f.is_finite() { - return None; - } - let neg = f.is_sign_negative() && f != 0.0; - let mut x = f.abs(); - let mut den: i128 = 1; - while x.fract() != 0.0 { - if den > i128::MAX / 2 || x > 1e37 { - return None; - } - x *= 2.0; - den *= 2; - } - if x > 1e37 { - return None; - } - let num = x as i128; - let body = if den == 1 { - format!("{num}.0") +/// Render an exact rational as an SMT-LIB real literal: `3.0`, +/// `(/ 3.0 10.0)`, or either inside `(- …)` when negative. +pub(crate) fn render_real(r: &Rational) -> String { + let (n, d) = r.abs().to_string_parts(); + let body = if d == "1" { + format!("{n}.0") } else { - format!("(/ {num}.0 {den}.0)") + format!("(/ {n}.0 {d}.0)") }; - Some(if neg { format!("(- {body})") } else { body }) + if r.is_negative() { + format!("(- {body})") + } else { + body + } } diff --git a/crates/sysmlv2-solve/src/translate.rs b/crates/sysmlv2-solve/src/translate.rs index f3ec000..8e35beb 100644 --- a/crates/sysmlv2-solve/src/translate.rs +++ b/crates/sysmlv2-solve/src/translate.rs @@ -31,10 +31,11 @@ //! in one operation — or on one variable — bail. Each variable still //! lives in a single unit; witnesses report it. -use crate::term::{EnumSort, Op, Sort, Term, real_from_f64}; +use crate::term::{EnumSort, Op, Sort, Term}; use std::collections::{HashMap, HashSet, VecDeque}; use sysmlv2_model::eval::Value; use sysmlv2_model::json::{ConstraintInfo, ElementRef, ResolvedModel, ScopeRef}; +use sysmlv2_model::rational::Rational; use sysmlv2_syntax::ast::*; /// The construct (with context) that put an expression outside the @@ -55,6 +56,10 @@ pub(crate) struct VarInfo { pub sort: Sort, /// Inferred measurement unit (display spelling), for witness output. pub unit: Option, + /// An auxiliary introduced by the translation itself (it names one + /// step of a sequence fold and is defined by a side equality) — part + /// of the variable space, never reported to callers. + pub aux: bool, } /// A measurement-unit tag: canonical *dimensional* key, the scale to @@ -64,7 +69,7 @@ pub(crate) struct VarInfo { #[derive(Clone, Debug)] struct UTag { key: String, - scale: f64, + scale: Rational, display: String, } @@ -93,7 +98,8 @@ pub(crate) struct Translation { pub root: Term, pub vars: Vec, pub enums: Vec, - /// Extra assertions (declared-type range constraints, e.g. `Natural`). + /// Extra assertions: declared-type range constraints (e.g. `Natural`) + /// and the defining equalities of auxiliary variables. pub side: Vec, /// Features that carry a defining expression the translator could not /// encode and therefore treated as free — SAT results are then only @@ -164,7 +170,8 @@ pub(crate) enum JointRoot { /// system the propagation backend works on. A constraint outside the /// fragment is skipped (recorded) without poisoning the rest; variables /// and side assertions it half-registered stay — they are -/// true-by-declaration facts, so keeping them only widens nothing. +/// true-by-declaration facts or definitions of auxiliaries, so keeping +/// them narrows nothing. /// /// An over-approximated feature (a definition outside the fragment, treated /// as free) is not tracked here the way [`Translation::approx`] tracks it @@ -179,14 +186,50 @@ pub(crate) struct JointTranslation { pub side: Vec, } +/// The model's enumeration literals, indexed for translation. Deriving +/// them walks every scope's name table, so they are derived **once** per +/// resolved model and shared by every constraint's translation rather +/// than rebuilt per constraint. The element and scope tables a resolved +/// model is built from do not change afterwards, so one derivation +/// serves the whole run. +pub(crate) struct EnumTables { + /// Enum literal → its EnumerationDefinition. + lit_to_enum: HashMap, + /// EnumerationDefinition → its literals in declaration order. + enum_lits: HashMap>, + /// Literal → position within its definition. + lit_pos: HashMap, +} + +impl EnumTables { + pub(crate) fn build(r: &ResolvedModel) -> EnumTables { + let mut lit_to_enum = HashMap::new(); + let mut enum_lits = HashMap::new(); + let mut lit_pos = HashMap::new(); + for (def, lits) in r.enum_types() { + for (i, &lit) in lits.iter().enumerate() { + lit_to_enum.insert(lit, def); + lit_pos.insert(lit, i); + } + enum_lits.insert(def, lits); + } + EnumTables { + lit_to_enum, + enum_lits, + lit_pos, + } + } +} + /// Translate `cs` jointly. `Err` means finalization itself failed (a /// sort or unit conflict *between* constraints) — the caller degrades to /// no propagation, not to a partial one. pub(crate) fn translate_all( r: &mut ResolvedModel, + tables: &EnumTables, cs: &[&ConstraintInfo], ) -> Result { - let mut tr = Translator::new(r); + let mut tr = Translator::new(r, tables); let mut roots = Vec::with_capacity(cs.len()); for c in cs { let translated = tr @@ -270,9 +313,10 @@ fn seq_intrinsic_arity_ok(name: &str, n: usize) -> bool { pub(crate) fn translate( r: &mut ResolvedModel, + tables: &EnumTables, c: &ConstraintInfo, ) -> Result { - let mut tr = Translator::new(r); + let mut tr = Translator::new(r, tables); let root = tr.expr(c.scope, &c.expr)?.term; tr.demand(&root, Demand::Bool)?; let (vars, enums, side, approx) = tr.finish()?; @@ -298,6 +342,11 @@ struct Translator<'m> { var_keys: HashMap<(ElementRef, Option), usize>, displays: Vec, states: Vec, + /// Whether each variable is a translation-made auxiliary + /// (index-aligned with `displays`). + aux: Vec, + /// Auxiliary variable → index in `side` of its defining equality. + aux_defs: HashMap, side: Vec, /// Equalities between two still-unknown variables, unified at finish. pending_eq: Vec<(usize, usize)>, @@ -320,34 +369,22 @@ struct Translator<'m> { /// Unit linkage between two still-untagged variables, unified at /// finish (piggybacks the sort mechanism). pending_unit_eq: Vec<(usize, usize)>, - /// Enum literal → its EnumerationDefinition (whole model, precomputed). - lit_to_enum: HashMap, - /// EnumerationDefinition → its literals in declaration order. - enum_lits: HashMap>, - /// Literal → position within its definition. - enum_lit_pos: HashMap, + /// The model's enumeration literal index, derived once per run. + tables: &'m EnumTables, /// Enum definitions actually used, in first-use order. enum_defs: Vec, enum_index: HashMap, } impl<'m> Translator<'m> { - fn new(r: &'m mut ResolvedModel) -> Translator<'m> { - let mut lit_to_enum = HashMap::new(); - let mut enum_lits = HashMap::new(); - let mut enum_lit_pos = HashMap::new(); - for (def, lits) in r.enum_types() { - for (i, &lit) in lits.iter().enumerate() { - lit_to_enum.insert(lit, def); - enum_lit_pos.insert(lit, i); - } - enum_lits.insert(def, lits); - } + fn new(r: &'m mut ResolvedModel, tables: &'m EnumTables) -> Translator<'m> { Translator { r, var_keys: HashMap::new(), displays: Vec::new(), states: Vec::new(), + aux: Vec::new(), + aux_defs: HashMap::new(), side: Vec::new(), pending_eq: Vec::new(), inlining: HashSet::new(), @@ -357,9 +394,7 @@ impl<'m> Translator<'m> { approx: Vec::new(), var_units: Vec::new(), pending_unit_eq: Vec::new(), - lit_to_enum, - enum_lits, - enum_lit_pos, + tables, enum_defs: Vec::new(), enum_index: HashMap::new(), } @@ -374,32 +409,34 @@ impl<'m> Translator<'m> { match self.r.evaluate_in(scope, e) { Ok(Value::Boolean(b)) => Ok(Some(UT::plain(Term::BoolLit(b)))), Ok(Value::Integer(i)) => Ok(Some(UT::plain(Term::IntLit(i)))), - Ok(Value::Rational(f)) => match real_from_f64(f) { - Some(s) => Ok(Some(UT::plain(Term::RealLit(s)))), - None => bail("a non-finite or out-of-range numeric value"), + Ok(Value::Rational(r)) => Ok(Some(UT::plain(Term::RealLit(r)))), + Ok(Value::Real(f)) => match Rational::from_f64(f) { + Some(r) => Ok(Some(UT::plain(Term::RealLit(r)))), + None => bail("a non-finite numeric value"), }, Ok(Value::Quantity(n, u)) => { let unit = Some(UTag { key: u.dims_key(), - scale: u.scale(), + scale: u.scale().clone(), display: u.display().to_string(), }); let term = match *n { Value::Integer(i) => Term::IntLit(i), - Value::Rational(f) => match real_from_f64(f) { - Some(s) => Term::RealLit(s), - None => return bail("a non-finite or out-of-range numeric value"), + Value::Rational(r) => Term::RealLit(r), + Value::Real(f) => match Rational::from_f64(f) { + Some(r) => Term::RealLit(r), + None => return bail("a non-finite numeric value"), }, _ => return bail("a non-numeric quantity magnitude"), }; Ok(Some(UT { term, unit })) } Ok(Value::String(s)) => Ok(Some(UT::plain(Term::StrLit(s)))), - Ok(Value::Element(el)) if self.lit_to_enum.contains_key(&el) => { + Ok(Value::Element(el)) if self.tables.lit_to_enum.contains_key(&el) => { Ok(Some(UT::plain(self.enum_term(el)?))) } Ok(Value::Element(_)) - | Ok(Value::Unbound(_)) + | Ok(Value::Unbound(_) | Value::UnboundMember(_)) | Ok(Value::Indeterminate) | Ok(Value::Instance { .. }) | Ok(Value::Sequence(_)) @@ -471,15 +508,12 @@ impl<'m> Translator<'m> { .unit_of_in(scope, arg) .map_err(|e| Unsupported(format!("a quantity-unit bracket: {e}")))?; if unit.dims_key().is_empty() { - return if unit.scale() == 1.0 { + return if unit.scale().is_one() { Ok(UT::plain(t.term)) } else { - let Some(s) = real_from_f64(unit.scale()) else { - return bail("a non-finite unit scale"); - }; Ok(UT::plain(Term::App( Op::Mul, - vec![t.term, Term::RealLit(s)], + vec![t.term, Term::RealLit(unit.scale().clone())], ))) }; } @@ -487,7 +521,7 @@ impl<'m> Translator<'m> { term: t.term, unit: Some(UTag { key: unit.dims_key(), - scale: unit.scale(), + scale: unit.scale().clone(), display: unit.display().to_string(), }), }) @@ -592,7 +626,7 @@ impl<'m> Translator<'m> { (Some(u), 1) => Some(u.clone()), (Some(u), k) => Some(UTag { key: format!("({}^{k})", u.key), - scale: u.scale.powi(k as i32), + scale: u.scale.pow_or_approx(k as i32), display: format!("{}**{k}", u.display), }), }; @@ -921,31 +955,65 @@ impl<'m> Translator<'m> { } /// `max`/`min`: pairwise `ite(a ⋛ b, a, b)` with the comparison's - /// unit unification at each step. + /// unit unification at each step. Each step's value is named by an + /// auxiliary variable defined through a side equality, so the next + /// step references a variable rather than a copy of the whole prefix + /// (the operand appears in both the condition and a branch): the + /// fold stays linear in the item count for both backends. fn fold_extremum(&mut self, items: Vec, cmp: Op, display: &str) -> Result { let mut it = items.into_iter(); let Some(mut acc) = it.next() else { return bail(format!("`{display}` of an empty sequence")); }; self.demand(&acc.term, Demand::Numeric)?; - for mut x in it { + for (k, mut x) in it.enumerate() { self.demand(&x.term, Demand::Numeric)?; let unit = self.unify_units(&mut acc, &mut x)?; + let linked: Vec = [&acc.term, &x.term] + .into_iter() + .filter_map(|t| match t { + Term::Var(j) => Some(*j), + _ => None, + }) + .collect(); + let step = Term::App( + Op::Ite, + vec![ + Term::App(cmp, vec![acc.term.clone(), x.term.clone()]), + acc.term, + x.term, + ], + ); + let i = self.aux_var(format!("{display}#{}", k + 1), unit.clone(), &linked); + self.aux_defs.insert(i, self.side.len()); + self.side.push(Term::App(Op::Eq, vec![Term::Var(i), step])); acc = UT { - term: Term::App( - Op::Ite, - vec![ - Term::App(cmp, vec![acc.term.clone(), x.term.clone()]), - acc.term, - x.term, - ], - ), + term: Term::Var(i), unit, }; } Ok(acc) } + /// A fresh auxiliary numeric variable standing for a value the + /// translation names (`display` only seeds its symbol). It carries + /// the value's unit tag and is unit-linked to the `linked` + /// variables (the operands of its definition), so a tag arriving + /// later on either side reaches the other at finalization exactly as + /// it would through a direct comparison. The caller records the + /// defining equality. + fn aux_var(&mut self, display: String, unit: Option, linked: &[usize]) -> usize { + let i = self.displays.len(); + self.displays.push(display); + self.states.push(SortState::Numeric); + self.var_units.push(unit); + self.aux.push(true); + for &j in linked { + self.pending_unit_eq.push((i, j)); + } + i + } + // -- finite quantifier expansion ----------------------------------------- /// `target->Fn …` — quantifiers with a lambda body expand finitely; @@ -1121,6 +1189,7 @@ impl<'m> Translator<'m> { self.displays.push(display); self.states.push(state); self.var_units.push(None); + self.aux.push(false); if let Some(lo) = lower { self.side .push(Term::App(Op::Ge, vec![Term::Var(i), Term::IntLit(lo)])); @@ -1142,7 +1211,7 @@ impl<'m> Translator<'m> { ctx: Option, display: String, ) -> Result { - if self.lit_to_enum.contains_key(&elem) || self.r.is_enum_value(elem) { + if self.tables.lit_to_enum.contains_key(&elem) || self.r.is_enum_value(elem) { return self.feature_term(elem, ctx, display); } if let Some((own_scope, vexpr)) = self.r.value_expr(elem) { @@ -1150,7 +1219,10 @@ impl<'m> Translator<'m> { let closed = self.r.evaluate_in(scope, &vexpr).is_ok_and(|v| { !matches!( v, - Value::Element(_) | Value::Unbound(_) | Value::Indeterminate + Value::Element(_) + | Value::Unbound(_) + | Value::UnboundMember(_) + | Value::Indeterminate ) }); if closed && self.inlining.insert(elem) { @@ -1269,12 +1341,30 @@ impl<'m> Translator<'m> { .r .evaluate_in(scope, target) .map_err(|e| Unsupported(format!("chain target: {e}")))?; + if matches!(tval, Value::Indeterminate | Value::UnboundMember(_)) { + // A nested unknown member has no concrete featuring context. + // Do not identify distinct receiver paths by their shared + // declaration, or inline defaults from that declaration. + return bail("a chain through an unknown receiver member"); + } + let unbound = matches!(&tval, Value::Unbound(t) if self.r.is_reference_feature(*t)); let (Value::Element(t) | Value::Unbound(t)) = tval else { return bail("a chain whose target is not a model element"); }; let Some((hit, sub)) = self.r.member_of(t, qn) else { return bail(format!("unresolved reference `{}`", display_expr(whole))); }; + if unbound { + // Closed results were already handled by `fold`, which uses + // the evaluator's receiver-aware default rules. An unknown + // fixed formula may depend on sibling defaults too; inlining + // it without that context would invent a definitive value. + let display = display_expr(whole); + if self.r.has_own_fixed_value(hit) && !self.approx.contains(&display) { + self.approx.push(display.clone()); + } + return self.var(hit, sub, display); + } self.feature_term(hit, sub, display_expr(whole)) } @@ -1289,7 +1379,7 @@ impl<'m> Translator<'m> { ctx: Option, display: String, ) -> Result { - if self.lit_to_enum.contains_key(&elem) { + if self.tables.lit_to_enum.contains_key(&elem) { return self.enum_term(elem).map(UT::plain); } if self.r.is_enum_value(elem) { @@ -1330,6 +1420,7 @@ impl<'m> Translator<'m> { self.displays.push(display); self.states.push(state); self.var_units.push(None); + self.aux.push(false); if let Some(lo) = lower { self.side .push(Term::App(Op::Ge, vec![Term::Var(i), Term::IntLit(lo)])); @@ -1365,12 +1456,24 @@ impl<'m> Translator<'m> { match &self.var_units[i] { None => { self.var_units[i] = Some(u.clone()); - Ok(()) + // An auxiliary's tag reaches the value it names, + // exactly as the tag would have reached that value + // spelled in place. + let Some(&k) = self.aux_defs.get(&i) else { + return Ok(()); + }; + let mut def = std::mem::replace(&mut self.side[k], Term::BoolLit(true)); + let out = match &mut def { + Term::App(Op::Eq, args) => self.demand_unit(&mut args[1], u), + _ => Ok(()), + }; + self.side[k] = def; + out } Some(v) if v == u => Ok(()), Some(v) if v.key == u.key => { - let Some(ratio) = real_from_f64(v.scale / u.scale) else { - return bail("a non-finite unit-conversion ratio"); + let Some(ratio) = v.scale.div(&u.scale) else { + return bail("a zero unit scale"); }; *t = Term::App(Op::Mul, vec![Term::Var(i), Term::RealLit(ratio)]); Ok(()) @@ -1410,8 +1513,8 @@ impl<'m> Translator<'m> { // right term into the left's unit (mirroring the // evaluator's measurement-reference conversion). (Some(u), Some(v)) if u.key == v.key => { - let Some(ratio) = real_from_f64(v.scale / u.scale) else { - return bail("a non-finite unit-conversion ratio"); + let Some(ratio) = v.scale.div(&u.scale) else { + return bail("a zero unit scale"); }; b.term = Term::App( Op::Mul, @@ -1470,7 +1573,8 @@ impl<'m> Translator<'m> { if steps > 64 { break; } - if self.r.element_type(t) == "EnumerationDefinition" && self.enum_lits.contains_key(&t) + if self.r.element_type(t) == "EnumerationDefinition" + && self.tables.enum_lits.contains_key(&t) { let idx = self.intern_enum(t)?; return Ok((SortState::Fixed(Sort::Enum(idx)), None)); @@ -1497,16 +1601,16 @@ impl<'m> Translator<'m> { } fn enum_term(&mut self, lit: ElementRef) -> Result { - let def = self.lit_to_enum[&lit]; + let def = self.tables.lit_to_enum[&lit]; let idx = self.intern_enum(def)?; - Ok(Term::EnumLit(idx, self.enum_lit_pos[&lit])) + Ok(Term::EnumLit(idx, self.tables.lit_pos[&lit])) } fn intern_enum(&mut self, def: ElementRef) -> Result { if let Some(&i) = self.enum_index.get(&def) { return Ok(i); } - if self.enum_lits[&def].is_empty() { + if self.tables.enum_lits[&def].is_empty() { return bail("an enumeration without literals"); } let i = self.enum_defs.len(); @@ -1687,12 +1791,13 @@ impl<'m> Translator<'m> { sym: format!("v{i}_{}", sanitize(display)), sort, unit: self.var_units[i].as_ref().map(|u| u.display.clone()), + aux: self.aux[i], }); } let mut enums = Vec::with_capacity(self.enum_defs.len()); for (k, &def) in self.enum_defs.iter().enumerate() { let def_name = self.r.element_name(def).unwrap_or("enum").to_string(); - let lits = &self.enum_lits[&def]; + let lits = &self.tables.enum_lits[&def]; let mut ctors = Vec::with_capacity(lits.len()); let mut displays = Vec::with_capacity(lits.len()); for (j, &lit) in lits.iter().enumerate() { @@ -1734,7 +1839,7 @@ fn compose_mul(a: &Option, b: &Option) -> Option { let (x, y) = if u.key <= v.key { (u, v) } else { (v, u) }; Some(UTag { key: format!("({}*{})", x.key, y.key), - scale: u.scale * v.scale, + scale: u.scale.mul(&v.scale), display: format!("{}*{}", u.display, v.display), }) } @@ -1750,12 +1855,12 @@ fn compose_div(a: &Option, b: &Option) -> Option { (Some(u), Some(v)) if u == v => None, (x, Some(v)) => { let (nk, nd, ns) = match x { - Some(u) => (u.key.clone(), u.display.clone(), u.scale), - None => ("1".to_string(), "1".to_string(), 1.0), + Some(u) => (u.key.clone(), u.display.clone(), u.scale.clone()), + None => ("1".to_string(), "1".to_string(), Rational::one()), }; Some(UTag { key: format!("({nk}/{})", v.key), - scale: ns / v.scale, + scale: ns.div(&v.scale).unwrap_or_else(Rational::one), display: format!("{nd}/{}", v.display), }) } diff --git a/crates/sysmlv2-solve/src/z3.rs b/crates/sysmlv2-solve/src/z3.rs index 4f7e8d4..68f1be8 100644 --- a/crates/sysmlv2-solve/src/z3.rs +++ b/crates/sysmlv2-solve/src/z3.rs @@ -36,15 +36,38 @@ pub(crate) fn run_query( .stderr(Stdio::piped()) .spawn() .map_err(|e| format!("cannot run `{}`: {e}", z3.display()))?; - child - .stdin - .take() - .expect("stdin piped") - .write_all(script.as_bytes()) - .map_err(|e| format!("cannot write to z3: {e}"))?; - let out = child - .wait_with_output() - .map_err(|e| format!("z3 did not run to completion: {e}"))?; + let mut stdin = child.stdin.take().expect("stdin piped"); + let write_err = stdin.write_all(script.as_bytes()).err(); + // Closing the pipe is what tells the solver the script is complete. + // (On a target without processes the handle is a stub with nothing + // to drop, which the lint would otherwise report.) + #[cfg_attr(target_family = "wasm", allow(clippy::drop_non_drop))] + drop(stdin); + if write_err.is_some() { + // The script did not get through — most often because the solver + // rejected its command line and exited before reading it. Stop it + // and collect it below: an abandoned child would linger as a + // zombie in a long-lived host, and its own message explains the + // failure far better than a broken pipe does. + let _ = child.kill(); + } + let out = match child.wait_with_output() { + Ok(out) => out, + Err(e) => { + return Err(match write_err { + Some(w) => { + format!("cannot write to z3: {w}; and it did not run to completion: {e}") + } + None => format!("z3 did not run to completion: {e}"), + }); + } + }; + if let Some(w) = write_err { + return Err(format!( + "cannot write to z3: {w}{}", + early_exit_report(&out) + )); + } let text = String::from_utf8_lossy(&out.stdout); let mut rest: &str = &text; // Skip anything before the verdict line (warnings etc.). @@ -105,17 +128,38 @@ pub(crate) fn run_query( } } -/// The z3 binary's version banner, or an error naming what failed — the -/// availability probe. -pub(crate) fn version(z3: &Path) -> Result { - let out = Command::new(z3) - .arg("-version") - .output() - .map_err(|e| format!("cannot run `{}`: {e}", z3.display()))?; +/// What a solver that quit before the script reached it has to say for +/// itself: its own output (stderr, else stdout) and how it ended. Appended +/// to the write failure so the caller sees the cause and not just the +/// symptom. +fn early_exit_report(out: &std::process::Output) -> String { + let stderr = String::from_utf8_lossy(&out.stderr); + let said = if stderr.trim().is_empty() { + String::from_utf8_lossy(&out.stdout).trim().to_string() + } else { + stderr.trim().to_string() + }; + let how = match out.status.code() { + Some(c) => format!("; z3 exited first with status {c}"), + None => "; z3 exited first".to_string(), + }; + if said.is_empty() { + how + } else { + format!("{how}: {said}") + } +} + +/// The z3 binary's version banner — the availability probe. The error +/// carries the operating system's own account of why the binary could not +/// be run (a missing binary and an unreadable one are different failures), +/// or `None` when it ran but printed no banner. +pub(crate) fn version(z3: &Path) -> Result> { + let out = Command::new(z3).arg("-version").output().map_err(Some)?; let banner = String::from_utf8_lossy(&out.stdout); let banner = banner.trim(); if banner.is_empty() { - Err(format!("`{} -version` printed nothing", z3.display())) + Err(None) } else { Ok(banner.to_string()) } @@ -166,3 +210,39 @@ pub(crate) fn parse_sexpr(input: &str) -> Option<(SExpr, &str)> { } Some((SExpr::Atom(input[..end].to_string()), &input[end..])) } + +#[cfg(all(test, unix))] +mod tests { + use super::*; + use std::os::unix::fs::PermissionsExt; + + /// A stand-in solver that never reads its input: it writes one line of + /// its own and exits straight away, the way a real one does when it + /// rejects its command line. + fn stub_that_exits_first() -> (std::path::PathBuf, std::path::PathBuf) { + let dir = std::env::temp_dir().join(format!("sysmlv2-solve-stub-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("exits-first"); + std::fs::write(&path, "#!/bin/sh\necho 'unrecognized option' >&2\nexit 3\n").unwrap(); + std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o755)).unwrap(); + (dir, path) + } + + #[test] + fn a_solver_that_quits_first_is_collected_and_quoted() { + let (dir, stub) = stub_that_exits_first(); + // Wider than any pipe buffer, so the write cannot slip into the + // buffer before the child is gone. + let script = format!("; {}\n(check-sat)\n", "x".repeat(1 << 20)); + let outcome = run_query(&stub, 1000, &script, 0); + std::fs::remove_dir_all(&dir).unwrap(); + let Err(err) = outcome else { + panic!("a solver that never read the script cannot have a verdict"); + }; + assert!(err.contains("cannot write to z3"), "{err}"); + // Its own account reaches the caller, which is only possible if + // the driver waited for it instead of abandoning it. + assert!(err.contains("status 3"), "{err}"); + assert!(err.contains("unrecognized option"), "{err}"); + } +} diff --git a/crates/sysmlv2-solve/tests/apollo.rs b/crates/sysmlv2-solve/tests/apollo.rs index bad0150..053e228 100644 --- a/crates/sysmlv2-solve/tests/apollo.rs +++ b/crates/sysmlv2-solve/tests/apollo.rs @@ -42,6 +42,9 @@ fn apollo_solve_ratchet() { ); } Some(SolveOutcome::Unknown(_)) => unknown += 1, + // A conclusion this count does not know would silently skew + // the ratchet. + Some(other) => panic!("unhandled solve conclusion: {other:?}"), } } assert_eq!( diff --git a/crates/sysmlv2-solve/tests/corpus.rs b/crates/sysmlv2-solve/tests/corpus.rs index 219f420..a42bbc8 100644 --- a/crates/sysmlv2-solve/tests/corpus.rs +++ b/crates/sysmlv2-solve/tests/corpus.rs @@ -3,8 +3,9 @@ //! solve to exactly the recorded outcome counts — `valid` and //! `unsatisfiable` must stay 0 on a conforming corpus (a nonzero //! `unsatisfiable` would mean we prove a published model self- -//! contradictory); `satisfiable` should only grow as the translator learns -//! more of the fragment. Skips when no `z3` is on PATH. +//! contradictory). Changes in satisfiable/unknown counts require an +//! explained translation improvement or soundness correction. Skips when +//! no `z3` is on PATH. use sysmlv2_model::model::Model; use sysmlv2_solve::{SolveOutcome, SolverConfig, solve_constraints, z3_version}; @@ -49,6 +50,9 @@ fn corpus_solve_ratchet() { ); } Some(SolveOutcome::Unknown(_)) => unknown += 1, + // A conclusion this count does not know would silently skew + // the ratchet. + Some(other) => panic!("unhandled solve conclusion: {other:?}"), } } // The 1 valid is genuine and verified by hand: `Turbojet Stage @@ -59,7 +63,7 @@ fn corpus_solve_ratchet() { // benign strengthening on a conforming corpus; UNSAT (⇒ violated) // is the alarming direction and must stay 0. // 56/23 → 59/30 when asserted constraints with *inherited* bodies - // entered the undecided pool (2026-07-17): the solver produces + // entered the undecided pool: the solver produces // witnesses for three of the ten, the rest stay unknown. // 59/30 → 64/25 with the sequence intrinsics (sum over bound // sequence arguments — the Mass-Roll-up family); the ten remaining @@ -72,16 +76,21 @@ fn corpus_solve_ratchet() { // approx-Unknown bucket (its `outerDiameter` leaf is a // bracket-over-quantity value, outside the fragment). // 65/24 → 65/27 when unbound-feature cardinality stopped - // fabricating (2026-07-23): three `(1..size(xs)-1)->forAll` bodies + // fabricating: three `(1..size(xs)-1)->forAll` bodies // over unbound `[0..*]` collections used to evaluate vacuously true // (fabricated size 1 emptied the range) and never reached the // solver; they now enter the undecided pool, where the quantified // size-dependent bodies are outside the decidable fragment. + // 65/27 → 63/29 when nested unknown receiver paths stopped sharing + // declaration-level variables: `device.battery.power` in User Keyword + // Example and `generator.generateTorque.torque` in 12b-Allocation-1 + // now stay unknown. Supporting them again requires preserving each + // receiver path in the solver's variable identity. assert_eq!( (valid, sat, unsat, unknown), - (1, 65, 0, 27), + (1, 63, 0, 29), "solve ratchet moved — unsatisfiable must stay 0 on the \ - conforming corpus; satisfiable should only grow via translator \ - improvements" + conforming corpus; satisfiable/unknown changes require an \ + explained translation improvement or soundness correction" ); } diff --git a/crates/sysmlv2-solve/tests/prepared.rs b/crates/sysmlv2-solve/tests/prepared.rs new file mode 100644 index 0000000..55773db --- /dev/null +++ b/crates/sysmlv2-solve/tests/prepared.rs @@ -0,0 +1,41 @@ +//! Solver entry points must read unit metadata without reconstructing the +//! syntax of a prepared library. +use std::sync::Arc; +use sysmlv2_model::{model::Model, prepared::PreparedLibrary}; +use sysmlv2_solve::{PropagateConfig, propagate_constraints}; + +#[test] +fn propagation_over_a_prepared_library_keeps_library_syntax_unloaded() { + let mut base = Model::new(); + base.add_library_source( + "lib.sysml", + "package Lib { attribute def N; part def T { attribute n : N; assert constraint c { n > 0 } } }", + ); + // A decoded snapshot starts with no library syntax in memory. + let bytes = base.prepare_library().unwrap().to_bytes(1).unwrap(); + let prepared = Arc::new(PreparedLibrary::from_bytes(&bytes, 1).unwrap()); + let mut model = Model::new(); + prepared.install(&mut model).unwrap(); + model.add_source( + "user.sysml", + "package U { part t : Lib::T { attribute :>> n = 2; } constraint k { t.n < 5 } }", + ); + assert_eq!(model.loaded_library_unit_count(), 0); + let propagation = propagate_constraints(&model, &PropagateConfig::default()); + assert!( + propagation + .constraints + .iter() + .all(|c| !model.is_library_unit(c.unit)), + "library constraints are never reported" + ); + assert!( + !propagation.constraints.is_empty(), + "the user constraint is analysed" + ); + assert_eq!( + model.loaded_library_unit_count(), + 0, + "solver metadata reads must not materialize library syntax" + ); +} diff --git a/crates/sysmlv2-solve/tests/propagate.rs b/crates/sysmlv2-solve/tests/propagate.rs index 4288ec1..6fa498a 100644 --- a/crates/sysmlv2-solve/tests/propagate.rs +++ b/crates/sysmlv2-solve/tests/propagate.rs @@ -45,6 +45,96 @@ fn sole_outcome(p: &Propagation) -> PropagateOutcome { .expect("undecided ⇒ propagated") } +/// Propagation must not decide a constraint from a value read *through +/// an unbound parameter*: a requirement definition's `subject` stands +/// for an argument bound later (`satisfy R by x`), and the `default` +/// its type declares is exactly what such an argument may override. +/// Inlining it would let the interval backend *prove* a verdict the +/// model never committed to, so the step stays a free variable and the +/// constraint stays undecided. +#[test] +fn a_subjects_defaults_do_not_decide_propagation() { + let p = prop( + "package P { + part def Valve { attribute cycleSeconds default = 8; } + requirement def CyclesFastEnough { + subject unit : Valve; + require constraint c { unit.cycleSeconds <= 2 } + } + }", + ); + assert!( + !matches!(sole_outcome(&p), PropagateOutcome::Violated), + "{:?}", + p.constraints + ); +} + +#[test] +fn unknown_receiver_formulas_and_aliases_do_not_decide_propagation() { + for (declaration, expression) in [ + ("ref part unit : Device;", "unit.enabled"), + ("subject unit : Device;", "unit.computed"), + ( + "subject unit : Device; ref part aliasUnit : Device = unit;", + "aliasUnit.enabled", + ), + ( + "subject unit : Device;", + "(if true ? unit else unit).enabled", + ), + ("subject unit : Device;", "unit.child.enabled"), + ("in unit : Device;", "unit.enabled"), + ] { + let p = prop(&format!( + "package P {{ + attribute def Boolean; + part def Child {{ attribute enabled : Boolean default = false; }} + part def Device {{ + attribute enabled : Boolean default = false; + attribute computed : Boolean = enabled; + part child : Child; + }} + requirement def R {{ + {declaration} + require constraint c {{ {expression} }} + }} + }}" + )); + assert!( + matches!( + sole_outcome(&p), + PropagateOutcome::Undecided | PropagateOutcome::Unsupported(_) + ), + "{declaration} / {expression}: {:?}", + p.constraints + ); + } +} + +#[test] +fn nested_unknown_receivers_do_not_share_solver_variables() { + let p = prop( + "package P { + attribute def Real; + part def Child { attribute value : Real default = 0; } + part def Parent { part child : Child; } + requirement def R { + subject leftUnit : Parent; + actor rightUnit : Parent; + assert constraint c { + leftUnit.child.value >= 1 and rightUnit.child.value <= 0 + } + } + }", + ); + assert!( + matches!(sole_outcome(&p), PropagateOutcome::Unsupported(_)), + "{:?}", + p.constraints + ); +} + // -- narrowing --------------------------------------------------------------- #[test] @@ -63,6 +153,24 @@ fn lower_bound_narrows_to_half_line() { assert_eq!(sole_outcome(&p), PropagateOutcome::Satisfied); } +#[test] +fn lower_bound_tightens_twice() { + // A half-line's finite side keeps moving under a second, stronger + // bound; a third, weaker bound is then settled by the tightened + // domain rather than left undecided. + let p = prop( + "package P { + attribute def Real; + attribute x : Real; + assert constraint open { x > 0 } + assert constraint strong { x >= 1000 } + assert constraint weak { x >= 500 } + }", + ); + assert_eq!(range_of(&p, "x").range, "[1000, +∞]"); + assert_eq!(outcome_of(&p, "weak"), PropagateOutcome::Satisfied); +} + #[test] fn two_constraints_narrow_jointly() { // Separate asserted constraints over one shared feature contract the @@ -274,6 +382,109 @@ fn ranges_narrow_through_a_sum_fold() { assert!(range_of(&p, "x").narrowed); } +#[test] +fn max_fold_pins_the_result() { + // `max` lowers to a chain of conditionals whose steps are named by + // hidden auxiliaries: the result narrows like any other feature, and + // the auxiliaries never surface as ranges or referenced features. + // The narrowing itself held before the auxiliaries existed — what + // this pins is that naming the steps did not change the answer, and + // that nothing internal leaks out. The cost is pinned separately by + // the forty-item test below. + let p = prop( + "package P { + attribute def Integer; + attribute hi : Integer; + attribute a : Integer; + attribute b : Integer; + assert constraint m { hi == max((a, b)) } + assert constraint af { a == 2 } + assert constraint bf { b == 7 } + }", + ); + assert_eq!(range_of(&p, "hi").range, "[7, 7]"); + let declared = ["hi", "a", "b"]; + assert!( + p.ranges + .iter() + .all(|r| declared.contains(&r.feature.as_str())), + "{:?}", + p.ranges + ); + for c in &p.constraints { + assert!( + c.features.iter().all(|f| declared.contains(&f.as_str())), + "{:?}", + c.features + ); + } +} + +#[test] +fn max_over_forty_items_stays_linear() { + // Each fold step references the previous step's auxiliary, so a + // 41-item extremum is a 41-step chain — not a term doubling per item. + let items: Vec = (1..=40).map(|i| i.to_string()).collect(); + let start = std::time::Instant::now(); + let p = prop(&format!( + "package P {{ + attribute def Integer; + attribute x : Integer; + attribute y : Integer; + assert constraint m {{ x == max(({}, y)) }} + assert constraint yf {{ y == 45 }} + }}", + items.join(", ") + )); + assert_eq!(range_of(&p, "x").range, "[45, 45]"); + assert!( + start.elapsed() < std::time::Duration::from_secs(5), + "fold took {:?}", + start.elapsed() + ); +} + +#[test] +fn separate_units_each_see_their_own_enumerations() { + // The enumeration literal index is derived once for the whole model + // and shared by every unit's translation: each unit must still reach + // its own enumeration, and literals of the same position in different + // enumerations must stay apart. This is a property of the sharing, + // not of the caching — a stale index would need a model that changed + // after the index was built, which the resolved model does not allow. + let mut model = Model::new(); + for (name, src) in [ + ( + "a.sysml", + "package A { + enum def Phase { init; run; halt; } + attribute p : Phase; + assert constraint ap { p == Phase::halt } + }", + ), + ( + "b.sysml", + "package B { + enum def Colour { red; green; blue; } + attribute c : Colour; + assert constraint bc { c != Colour::red } + }", + ), + ] { + let unit = model.add_source(name, src); + assert!( + unit.diagnostics.is_empty(), + "fixture must parse clean: {:?}", + unit.diagnostics + ); + } + let p = propagate_constraints(&model, &PropagateConfig::default()); + assert_eq!(range_of(&p, "p").range, "{halt}"); + assert_eq!(range_of(&p, "c").range, "{green, blue}"); + assert_eq!(outcome_of(&p, "ap"), PropagateOutcome::Satisfied); + assert_eq!(outcome_of(&p, "bc"), PropagateOutcome::Satisfied); +} + // -- finite quantifier expansion -------------------------------------------- #[test] @@ -313,6 +524,25 @@ fn inequality_removes_one_enum_literal() { assert!(!r.range.contains("mid"), "mid not excluded: {}", r.range); } +#[test] +fn enum_literals_past_position_128_stay_distinct() { + // A wide enumeration: pinning the 130th literal must narrow to that + // literal alone, and excluding the 2nd must not empty the domain + // (the two positions are distinct members, not aliases). + let lits: String = (1..=130).map(|i| format!("l{i}; ")).collect(); + let p = prop(&format!( + "package P {{ + enum def Wide {{ {lits} }} + attribute c : Wide; + assert constraint pin {{ c == Wide::l130 }} + assert constraint apart {{ c != Wide::l2 }} + }}" + )); + assert_eq!(range_of(&p, "c").range, "{l130}"); + assert_eq!(outcome_of(&p, "pin"), PropagateOutcome::Satisfied); + assert_eq!(outcome_of(&p, "apart"), PropagateOutcome::Satisfied); +} + // -- partial conjunctions ---------------------------------------------------- #[test] @@ -392,3 +622,38 @@ fn corpus_no_false_violations() { } } } + +#[test] +fn decimal_bounds_stay_exact() { + // Bounds spelled as decimal literals contract the domain to exactly + // those decimals — not to their nearest doubles. + let p = prop( + "package Mass { + attribute def Real; + attribute airframeKg : Real; + attribute batteryKg : Real; + assert constraint airframeRange { airframeKg >= 0.8 and airframeKg <= 1.1 } + assert constraint batteryRange { batteryKg >= 0.2 and batteryKg <= 0.3 } + }", + ); + let a = range_of(&p, "airframeKg"); + assert_eq!(a.range, "[0.8, 1.1]"); + assert_eq!(a.range_approx, "[0.8, 1.1]"); + let b = range_of(&p, "batteryKg"); + assert_eq!(b.range, "[0.2, 0.3]"); + assert_eq!(b.range_approx, "[0.2, 0.3]"); +} + +#[test] +fn non_terminating_bounds_print_as_fractions_and_hint_as_decimals() { + let p = prop( + "package Ratio { + attribute def Real; + attribute share : Real; + assert constraint c { share >= 1 / 3 and share <= 2 / 3 } + }", + ); + let r = range_of(&p, "share"); + assert_eq!(r.range, "[1/3, 2/3]"); + assert_eq!(r.range_approx, "[≈0.3333333333333333, ≈0.6666666666666666]"); +} diff --git a/crates/sysmlv2-solve/tests/solve.rs b/crates/sysmlv2-solve/tests/solve.rs index de7f886..80db6bc 100644 --- a/crates/sysmlv2-solve/tests/solve.rs +++ b/crates/sysmlv2-solve/tests/solve.rs @@ -102,9 +102,12 @@ fn real_witness_by_default_sort() { panic!("expected a witness, got {out:?}"); }; assert_eq!(w.len(), 1); - match w[0].1 { - WitnessValue::Real(f) => assert!(f > 3.0 && f < 4.0, "witness {f} out of range"), - ref v => panic!("expected a real witness, got {v:?}"), + match &w[0].1 { + WitnessValue::Real(r) => { + let f = r.to_f64(); + assert!(f > 3.0 && f < 4.0, "witness {r} out of range"); + } + v => panic!("expected a real witness, got {v:?}"), } } @@ -408,7 +411,12 @@ fn variable_converts_across_same_dimension_units() { let x = w.iter().find(|(n, _)| n == "x").expect("x in witness"); assert_eq!( x.1, - WitnessValue::WithUnit(Box::new(WitnessValue::Real(20.0)), "beat".to_string()), + WitnessValue::WithUnit( + Box::new(WitnessValue::Real( + sysmlv2_model::rational::Rational::from_integer(20), + )), + "beat".to_string(), + ), "{w:?}" ); } @@ -450,11 +458,11 @@ fn scalar_scaling_keeps_the_unit() { match &w[0].1 { sysmlv2_solve::WitnessValue::WithUnit(v, u) => { assert_eq!(u, "mm"); - match **v { - sysmlv2_solve::WitnessValue::Real(f) => { - assert!((4.0..=5.0).contains(&f), "{f}") + match &**v { + sysmlv2_solve::WitnessValue::Real(r) => { + assert!((4.0..=5.0).contains(&r.to_f64()), "{r}") } - ref other => panic!("unexpected witness {other:?}"), + other => panic!("unexpected witness {other:?}"), } } other => panic!("expected a unit-tagged witness, got {other:?}"), @@ -478,19 +486,58 @@ fn unsupported_construct_is_unknown() { assert!(m.contains("not in the solvable fragment"), "{m}"); } -#[test] -fn missing_z3_binary_reports_unavailable() { +/// Try to solve an empty model with `z3` taken from `path`, and return +/// the availability failure that must follow. +fn unavailable(path: &std::path::Path) -> sysmlv2_solve::SolveError { let cfg = SolverConfig { - z3_path: Some("/nonexistent/z3-binary".into()), + z3_path: Some(path.to_path_buf()), ..Default::default() }; let mut model = Model::new(); model.add_source("test.sysml", "package P { }"); - let err = solve_constraints(&model, &cfg); - assert!(matches!( - err, - Err(sysmlv2_solve::SolveError::SolverUnavailable(_)) - )); + match solve_constraints(&model, &cfg) { + Err(e) => e, + Ok(_) => panic!("solving cannot succeed through `{}`", path.display()), + } +} + +#[test] +fn missing_z3_binary_reports_unavailable() { + use std::error::Error as _; + let err = unavailable(std::path::Path::new("/nonexistent/z3-binary")); + match &err { + sysmlv2_solve::SolveError::SolverUnavailable { path, source } => { + assert_eq!(path, std::path::Path::new("/nonexistent/z3-binary")); + assert_eq!( + source.as_ref().map(std::io::Error::kind), + Some(std::io::ErrorKind::NotFound) + ); + } + other => panic!("unexpected failure: {other}"), + } + assert!(err.source().is_some(), "the cause is reachable as a source"); + assert!(err.to_string().contains("/nonexistent/z3-binary"), "{err}"); +} + +#[test] +#[cfg(unix)] +fn an_unreadable_z3_binary_is_told_apart_from_a_missing_one() { + use std::os::unix::fs::PermissionsExt; + let dir = std::env::temp_dir().join(format!("sysmlv2-solve-perm-{}", std::process::id())); + std::fs::create_dir_all(&dir).unwrap(); + let path = dir.join("z3"); + std::fs::write(&path, "#!/bin/sh\nexit 0\n").unwrap(); + std::fs::set_permissions(&path, std::fs::Permissions::from_mode(0o644)).unwrap(); + let err = unavailable(&path); + std::fs::remove_dir_all(&dir).unwrap(); + match &err { + sysmlv2_solve::SolveError::SolverUnavailable { source, .. } => assert_eq!( + source.as_ref().map(std::io::Error::kind), + Some(std::io::ErrorKind::PermissionDenied), + "a binary that exists but cannot be executed must not read as missing: {err}" + ), + other => panic!("unexpected failure: {other}"), + } } #[test] @@ -754,6 +801,12 @@ fn max_min_fold_to_ite_chains() { w.contains(&("lo".to_string(), WitnessValue::Int(2))), "{w:?}" ); + // The fold's step auxiliaries never surface in the witness. + let declared = ["hi", "lo", "a", "b"]; + assert!( + w.iter().all(|(n, _)| declared.contains(&n.as_str())), + "{w:?}" + ); } /// `product`, `abs`, `head`, `last` — the rest of the fold table. diff --git a/crates/sysmlv2-syntax/Cargo.toml b/crates/sysmlv2-syntax/Cargo.toml index 17598f4..f164d13 100644 --- a/crates/sysmlv2-syntax/Cargo.toml +++ b/crates/sysmlv2-syntax/Cargo.toml @@ -11,4 +11,9 @@ license.workspace = true repository.workspace = true include = ["src/**", "Cargo.toml"] +[features] +# Internal prepared-library persistence; the default syntax crate stays dependency-free. +serde = ["dep:serde"] + [dependencies] +serde = { workspace = true, optional = true } diff --git a/crates/sysmlv2-syntax/src/ast.rs b/crates/sysmlv2-syntax/src/ast.rs index acbfc6d..bfff1a8 100644 --- a/crates/sysmlv2-syntax/src/ast.rs +++ b/crates/sysmlv2-syntax/src/ast.rs @@ -13,6 +13,7 @@ use crate::span::Span; /// SysML share one lexical structure and expression grammar but differ in /// structural keywords and reserved words. #[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Dialect { #[default] Sysml, @@ -21,6 +22,7 @@ pub enum Dialect { /// A parsed source unit (one `.sysml` / `.kerml` file): the root namespace. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct SourceUnit { pub dialect: Dialect, pub members: Vec, @@ -28,6 +30,7 @@ pub struct SourceUnit { /// One member of a namespace or body, with its optional visibility prefix. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Member { pub visibility: Option, /// A bare `then` immediately before this (occurrence) member — an @@ -41,6 +44,7 @@ pub struct Member { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Visibility { Public, Private, @@ -48,6 +52,7 @@ pub enum Visibility { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum MemberKind { Package(Package), Import(Import), @@ -104,6 +109,7 @@ pub enum MemberKind { /// KerML standalone relationship declarations. #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum RelationshipDeclKind { /// `subtype A specializes B` (Specialization) Specialization, @@ -126,6 +132,7 @@ pub enum RelationshipDeclKind { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct RelationshipDecl { pub kind: RelationshipDeclKind, pub id: Identification, @@ -134,6 +141,7 @@ pub struct RelationshipDecl { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct MultiplicityDecl { pub id: Identification, /// `subsets N` form. @@ -144,12 +152,14 @@ pub struct MultiplicityDecl { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum RequirementConstraintKind { Assumption, Requirement, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum StateSubactionKind { Entry, Do, @@ -158,6 +168,7 @@ pub enum StateSubactionKind { /// `dependency ? from? clients to suppliers` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Dependency { pub metadata: Vec, pub id: Identification, @@ -167,12 +178,14 @@ pub struct Dependency { /// `` and/or name from an element declaration. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Identification { pub short_name: Option, pub name: Option, } impl Identification { + #[must_use] pub fn is_empty(&self) -> bool { self.short_name.is_none() && self.name.is_none() } @@ -180,6 +193,7 @@ impl Identification { /// A single name: an `ID` or an `'unrestricted name'` (already unescaped). #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Name { pub value: String, pub span: Span, @@ -189,7 +203,16 @@ pub struct Name { /// basic name (`[a-zA-Z_]\w*`), otherwise single-quoted with /// `\b \t \n \f \r " ' \` escaped. Used by the printer and by the normative /// library-ID computation. +#[must_use] pub fn escape_name(name: &str) -> String { + let mut out = String::with_capacity(name.len() + 2); + write_escaped_name(name, &mut out); + out +} + +/// [`escape_name`] appended to an existing buffer, for callers that +/// render many names through one allocation. +pub fn write_escaped_name(name: &str, out: &mut String) { let basic = !name.is_empty() && name .chars() @@ -198,9 +221,9 @@ pub fn escape_name(name: &str) -> String { .unwrap_or(false) && name.chars().all(|c| c.is_ascii_alphanumeric() || c == '_'); if basic { - return name.to_string(); + out.push_str(name); + return; } - let mut out = String::with_capacity(name.len() + 2); out.push('\''); for c in name.chars() { match c { @@ -216,11 +239,11 @@ pub fn escape_name(name: &str) -> String { } } out.push('\''); - out } /// `($::)? (Name ::)* Name` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct QualifiedName { /// Prefixed with `$::` (resolve from the global root namespace). pub is_global: bool, @@ -230,6 +253,7 @@ pub struct QualifiedName { impl QualifiedName { /// Dot/colons-free display form, e.g. `Vehicle::engine`. + #[must_use] pub fn to_display_string(&self) -> String { let mut s = String::new(); if self.is_global { @@ -246,37 +270,80 @@ impl QualifiedName { /// Textual-notation form with restricted names quoted (`A::'..'`) — /// the `{"@ref"}` encoding, parsed back by the JSON reader. + #[must_use] pub fn to_ref_string(&self) -> String { let mut s = String::new(); + self.write_ref_string(&mut s); + s + } + + /// [`Self::to_ref_string`] appended to an existing buffer, for + /// callers that render many names through one allocation. + pub fn write_ref_string(&self, out: &mut String) { if self.is_global { - s.push_str("$::"); + out.push_str("$::"); } for (i, seg) in self.segments.iter().enumerate() { if i > 0 { - s.push_str("::"); + out.push_str("::"); } - s.push_str(&escape_name(&seg.value)); + write_escaped_name(&seg.value, out); } - s } } /// A reference target: a plain qualified name or a feature chain `a.b.c` /// (each chain link itself a qualified name). #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TargetRef { Name(QualifiedName), Chain(Vec), } impl TargetRef { + /// The reference of a connector end the text does not spell. + /// + /// The target-succession shorthand (`then next;`) and the bare-end + /// connector forms leave one end's reference out entirely: the end + /// exists, but what it refers to comes from the surrounding member + /// rather than from any name in the text. That is this value, and + /// [`TargetRef::is_unspelled`] recognises it. + #[must_use] + pub fn unspelled() -> Self { + TargetRef::Chain(Vec::new()) + } + + /// Whether this is the unspelled reference of [`TargetRef::unspelled`]. + #[must_use] + pub fn is_unspelled(&self) -> bool { + matches!(self, TargetRef::Chain(links) if links.is_empty()) + } + + /// The single qualified name this reference spells, if it spells one + /// rather than a feature chain. + /// + /// A reference reached through a pointer cannot be matched down to its + /// name in a nested pattern, so callers that only want the name ask + /// for it here instead of guarding a match arm and re-testing inside. + #[must_use] + pub fn as_name(&self) -> Option<&QualifiedName> { + match self { + TargetRef::Name(qn) => Some(qn), + TargetRef::Chain(_) => None, + } + } + + /// The source text this reference covers; empty for an unspelled one, + /// which has no text of its own. + #[must_use] pub fn span(&self) -> Span { match self { TargetRef::Name(qn) => qn.span, - TargetRef::Chain(links) => links - .first() - .map(|f| f.span.join(links.last().unwrap().span)) - .unwrap_or_default(), + TargetRef::Chain(links) => match (links.first(), links.last()) { + (Some(first), Some(last)) => first.span.join(last.span), + _ => Span::default(), + }, } } } @@ -288,6 +355,7 @@ impl TargetRef { /// `('standard'? 'library')? '#Meta'* 'package' Identification? Body` /// (also KerML `namespace` declarations, flagged `is_namespace`). #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Package { pub is_library: bool, pub is_standard: bool, @@ -302,6 +370,7 @@ pub struct Package { /// `import all? (::*)? (::**)? [filters] ;` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Import { pub is_import_all: bool, pub target: QualifiedName, @@ -315,6 +384,7 @@ pub struct Import { /// `alias name for ;` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Alias { pub id: Identification, pub target: QualifiedName, @@ -326,6 +396,7 @@ pub struct Alias { /// `comment ? (about e1, e2)? (locale "...")? /* body */` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Comment { pub id: Identification, pub about: Vec, @@ -336,6 +407,7 @@ pub struct Comment { /// `doc ? (locale "...")? /* body */` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Doc { pub id: Identification, pub locale: Option, @@ -344,6 +416,7 @@ pub struct Doc { /// `rep ? language "lang" /* body */` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TextualRep { pub id: Identification, pub language: String, @@ -356,6 +429,7 @@ pub struct TextualRep { /// The kind keyword(s) of a SysML definition (` def`). #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum DefKind { Attribute, Enum, @@ -403,6 +477,7 @@ pub enum DefKind { /// The kind keyword of a SysML usage. #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum UsageKind { Attribute, Enum, @@ -481,6 +556,7 @@ pub enum UsageKind { /// `abstract` / `variation` / `individual` / `#Meta` prefixes on a definition. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct DefPrefix { pub is_abstract: bool, pub is_variation: bool, @@ -491,6 +567,7 @@ pub struct DefPrefix { /// ` def Identification? (:> supers)? Body` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Definition { pub prefix: DefPrefix, pub kind: DefKind, @@ -502,7 +579,7 @@ pub struct Definition { /// KerML `all` sufficiency marker (`classifier all C …`). pub is_sufficient: bool, /// KerML type multiplicity (`class C [2] …`). - pub multiplicity: Option, + pub multiplicity: Option>, /// KerML `~` / `conjugates` target. pub conjugates: Vec, /// KerML `disjoint from A, B`. @@ -517,6 +594,7 @@ pub struct Definition { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FeatureDirection { In, Out, @@ -525,6 +603,7 @@ pub enum FeatureDirection { /// Occurrence portion kind (`snapshot` / `timeslice` prefix). #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum PortionKind { Snapshot, Timeslice, @@ -532,6 +611,7 @@ pub enum PortionKind { /// Prefix modifiers on a usage. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct UsagePrefix { pub direction: Option, pub is_derived: bool, @@ -562,6 +642,7 @@ pub struct UsagePrefix { /// carrying its own basic prefix, distinct from the end feature's own /// prefix (`end in x : T feature y;`, `end derived c : Cart[1] item x;`). #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct CrossFeature { pub direction: Option, pub is_derived: bool, @@ -584,8 +665,9 @@ pub struct CrossFeature { /// One end of a connector (`connect`, `bind`, `first…then`, interface parts): /// `([mult])? (name ::>)? target` #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct ConnectorEnd { - pub multiplicity: Option, + pub multiplicity: Option>, pub name: Option, pub target: TargetRef, } @@ -593,29 +675,33 @@ pub struct ConnectorEnd { /// A flow/message end: a feature chain whose last step is the flow feature /// (e.g. `tank.fuelOut`). #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FlowEnd { pub target: TargetRef, } /// Payload of a flow/message (`of` clause) or an accept action. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct PayloadPart { pub id: Identification, pub specializations: Vec, - pub multiplicity: Option, + pub multiplicity: Option>, pub is_ordered: bool, pub is_nonunique: bool, - pub value: Option, + pub value: Option>, } /// Trigger of an accept action: `at`/`after`/`when` expression. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Trigger { pub kind: TriggerKind, pub expr: Expr, } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum TriggerKind { At, After, @@ -623,7 +709,13 @@ pub enum TriggerKind { } /// Kind-specific parts of a usage beyond the uniform declaration shape. +/// +/// Each variant's payload sits behind a pointer. A usage carries exactly +/// one detail, so an inline payload would size every usage in the tree by +/// the largest form; the field names and the shape of every pattern stay +/// as they are. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum UsageDetail { #[default] None, @@ -634,12 +726,12 @@ pub enum UsageDetail { Binding { ends: Vec }, /// `first a then b` (also `then b` target shorthand with no source). Succession { - source: Option, - target: ConnectorEnd, + source: Option>, + target: Box, }, /// Flow/message: `of` payload, `from a to b` (or bare `a to b`). Flow { - payload: Option, + payload: Option>, source: Option, target: Option, }, @@ -655,47 +747,47 @@ pub enum UsageDetail { Assert { negated: bool }, /// `accept (via )?` (+ trigger inside payload). Accept { - payload: PayloadPart, - trigger: Option, - via: Option, + payload: Box, + trigger: Option>, + via: Option>, }, /// `send ? (via )? (to )?` Send { - payload: Option, - via: Option, - to: Option, + payload: Option>, + via: Option>, + to: Option>, }, /// `assign := ` - Assign { target: Expr, value: Expr }, + Assign { target: Box, value: Box }, /// `terminate ?` - Terminate { target: Option }, + Terminate { target: Option> }, /// `if { … } (else …)?` — bodies are anonymous action usages. IfNode { - cond: Expr, + cond: Box, then_body: Box, /// Either an action body or a nested if-node usage. else_body: Option>, }, /// `while { … } (until ;)?` — `cond` is `None` for `loop`. WhileLoop { - cond: Option, + cond: Option>, body: Box, - until: Option, + until: Option>, }, /// `for in { … }` ForLoop { - var: FeatureDeclaration, - seq: Expr, + var: Box, + seq: Box, body: Box, }, /// `transition (first)? ? trigger? guard? effect? then ` Transition { source: Option, trigger: Option>, - guard: Option, + guard: Option>, /// Effect action (`do …`): a performed-action usage. effect: Option>, - target: Option, + target: Option>, /// `else target ;` default transition. is_default: bool, }, @@ -703,6 +795,7 @@ pub enum UsageDetail { /// One specialization clause in a feature declaration. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum FeatureSpecialization { /// `: T1, T2` or `defined by T1, T2`. `conjugated` per entry (`~Port`). TypedBy(Vec), @@ -717,6 +810,7 @@ pub enum FeatureSpecialization { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct TypeRef { /// `~T` — conjugated (port) type. pub is_conjugated: bool, @@ -725,6 +819,7 @@ pub struct TypeRef { /// `[expr]` or `[expr .. expr]`, with optional `ordered` / `nonunique`. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Multiplicity { /// Lower bound when the `l..u` form is used. pub lower: Option, @@ -735,10 +830,11 @@ pub struct Multiplicity { /// The declaration part of a usage: identification plus any specializations, /// multiplicity, and ordering markers, in source order. #[derive(Clone, Debug, PartialEq, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FeatureDeclaration { pub id: Identification, pub specializations: Vec, - pub multiplicity: Option, + pub multiplicity: Option>, pub is_ordered: bool, pub is_nonunique: bool, /// KerML `all` sufficiency marker. @@ -760,6 +856,7 @@ pub struct FeatureDeclaration { impl FeatureDeclaration { /// True when nothing at all was declared. + #[must_use] pub fn is_empty(&self) -> bool { self.id.is_empty() && self.specializations.is_empty() @@ -779,6 +876,7 @@ impl FeatureDeclaration { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ValueKind { /// `= expr` Bound, @@ -791,6 +889,7 @@ pub enum ValueKind { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct FeatureValue { pub kind: ValueKind, pub expr: Expr, @@ -802,12 +901,13 @@ pub struct FeatureValue { /// their target as a leading [`FeatureSpecialization::References`] in the /// declaration, mirroring the grammar's `OwnedReferenceSubsetting`. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Usage { pub prefix: UsagePrefix, pub kind: UsageKind, pub declaration: FeatureDeclaration, pub detail: UsageDetail, - pub value: Option, + pub value: Option>, /// `state … parallel { … }` pub is_parallel: bool, pub body: Option>, @@ -820,6 +920,7 @@ pub struct Usage { /// Binary / n-ary operators, named as in the abstract syntax `operator` /// strings. #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum BinaryOp { NullCoalescing, // ?? Implies, // implies @@ -847,6 +948,7 @@ pub enum BinaryOp { } #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum UnaryOp { Plus, Minus, @@ -856,6 +958,7 @@ pub enum UnaryOp { /// `istype` / `hastype` / `@` / `as` / `meta` / `@@` operators. #[derive(Clone, Copy, Debug, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ClassificationOp { IsType, HasType, @@ -866,12 +969,18 @@ pub enum ClassificationOp { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Expr { pub kind: ExprKind, pub span: Span, } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +/// +/// Every `ty` reference sits behind a pointer: a named type is a +/// qualified name of its own, and leaving one inline would size every +/// expression node in the tree by it. pub enum ExprKind { Literal(Literal), /// `null` or `()` @@ -898,11 +1007,11 @@ pub enum ExprKind { op: ClassificationOp, /// `None` = implicit self operand. operand: Option>, - ty: TargetRef, + ty: Box, }, /// `all T` — extent of a type. Extent { - ty: TargetRef, + ty: Box, }, /// `target.member` — feature-chain step. ChainStep { @@ -922,7 +1031,7 @@ pub enum ExprKind { /// `target->Fn(args)` / `target->Fn {body}` / `target->Fn ref`. Arrow { target: Box, - ty: TargetRef, + ty: Box, args: ArrowArgs, }, /// `target.{ body }` — collect. @@ -937,12 +1046,12 @@ pub enum ExprKind { }, /// `Type(args)` — invocation. Invocation { - ty: TargetRef, + ty: Box, args: Vec, }, /// `new Type(args)` — constructor. Constructor { - ty: TargetRef, + ty: Box, args: Vec, }, /// `{ in p1 : T1; … ; result-expr }` — expression body (lambda). SysML @@ -964,6 +1073,7 @@ pub enum ExprKind { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum ArrowArgs { /// `->Fn { body }` Body(Box), @@ -975,6 +1085,7 @@ pub enum ArrowArgs { /// A positional or named (`param = value`) argument. #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Arg { /// Redefined parameter name for named arguments. pub name: Option, @@ -982,6 +1093,7 @@ pub struct Arg { } #[derive(Clone, Debug, PartialEq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Literal { Bool(bool), /// Raw text preserved; decoded value. @@ -993,3 +1105,55 @@ pub enum Literal { /// `*` — positive infinity (unbounded multiplicity). Infinity, } + +#[cfg(test)] +mod spelling_tests { + use super::{Name, QualifiedName, escape_name, write_escaped_name}; + use crate::Span; + + fn qn(is_global: bool, segments: &[&str]) -> QualifiedName { + QualifiedName { + is_global, + segments: segments + .iter() + .map(|s| Name { + value: (*s).to_string(), + span: Span::default(), + }) + .collect(), + span: Span::default(), + } + } + + /// The buffered spellings render exactly what the allocating ones do, + /// appending rather than replacing. + #[test] + fn buffered_spelling_matches_the_allocating_one() { + for name in [ + "Vehicle", + "_x9", + "", + "with space", + "9lead", + "it's", + "back\\slash", + "tab\there", + "line\nbreak", + "quote\"mark", + ] { + let mut buf = String::from("<"); + write_escaped_name(name, &mut buf); + assert_eq!(buf, format!("<{}", escape_name(name)), "{name:?}"); + } + for name in [ + qn(false, &["Vehicle"]), + qn(false, &["Vehicle", "engine"]), + qn(true, &["Vehicle", "engine", "with space"]), + qn(true, &[]), + ] { + let mut buf = String::from("<"); + name.write_ref_string(&mut buf); + assert_eq!(buf, format!("<{}", name.to_ref_string())); + } + } +} diff --git a/crates/sysmlv2-syntax/src/check.rs b/crates/sysmlv2-syntax/src/check.rs index a718405..7db72f0 100644 --- a/crates/sysmlv2-syntax/src/check.rs +++ b/crates/sysmlv2-syntax/src/check.rs @@ -42,6 +42,7 @@ pub const IMPLEMENTED_NORMATIVE_VALIDATION_RULES: &[&str] = &[ ]; /// Validate one parsed source unit; returns all body-context diagnostics. +#[must_use] pub fn validate(unit: &SourceUnit) -> Vec { let mut v = Validator { dialect: unit.dialect, diff --git a/crates/sysmlv2-syntax/src/diag.rs b/crates/sysmlv2-syntax/src/diag.rs index e550259..86c9a69 100644 --- a/crates/sysmlv2-syntax/src/diag.rs +++ b/crates/sysmlv2-syntax/src/diag.rs @@ -4,6 +4,7 @@ use crate::span::Span; use std::fmt; #[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub enum Severity { Error, Warning, @@ -13,11 +14,33 @@ pub enum Severity { /// /// The lexer and parser are error-tolerant: they record diagnostics and keep /// going, so one pass reports as many problems as possible. -#[derive(Clone, Debug)] +/// +/// Non-exhaustive: a finding may come to carry more about itself, as it +/// came to carry [`Diagnostic::code`]. Build one with [`Diagnostic::error`] +/// or [`Diagnostic::warning`]. +/// +/// Two diagnostics are equal when they report the same thing — the same +/// severity, place and message. The rule code is derived state that a +/// serialization round trip does not carry (see the field), so counting +/// it in equality would make a value unequal to its own round trip. +#[derive(Clone, Debug, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +#[non_exhaustive] pub struct Diagnostic { pub severity: Severity, pub span: Span, pub message: String, + /// Identifier of the named rule this finding reports, when it reports + /// one — so a consumer reads a field instead of parsing the message. + /// Derived state: it is not carried across a serialization boundary. + #[cfg_attr(feature = "serde", serde(skip))] + pub code: Option<&'static str>, +} + +impl PartialEq for Diagnostic { + fn eq(&self, other: &Self) -> bool { + self.severity == other.severity && self.span == other.span && self.message == other.message + } } impl Diagnostic { @@ -26,6 +49,7 @@ impl Diagnostic { severity: Severity::Error, span, message: message.into(), + code: None, } } @@ -34,8 +58,16 @@ impl Diagnostic { severity: Severity::Warning, span, message: message.into(), + code: None, } } + + /// The same finding, reporting the rule `code` names. + #[must_use] + pub fn with_code(mut self, code: &'static str) -> Self { + self.code = Some(code); + self + } } impl fmt::Display for Diagnostic { @@ -47,3 +79,79 @@ impl fmt::Display for Diagnostic { write!(f, "{sev}: {} at {:?}", self.message, self.span) } } + +/// The diagnostics that made an operation fail, as a single error value. +/// +/// Dereferences to the slice, so the individual diagnostics stay reachable +/// (`first`, `len`, iteration, indexing); `Display` lists them one per +/// line; and it is a [`std::error::Error`], so a caller can propagate it +/// with `?` instead of having to unpack a vector by hand. +#[derive(Clone, Debug, Default, PartialEq, Eq)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] +pub struct Diagnostics(Vec); + +impl Diagnostics { + /// The diagnostics, giving up the wrapper. + #[must_use] + pub fn into_vec(self) -> Vec { + self.0 + } +} + +impl From> for Diagnostics { + fn from(diagnostics: Vec) -> Self { + Diagnostics(diagnostics) + } +} + +impl From for Vec { + fn from(diagnostics: Diagnostics) -> Self { + diagnostics.0 + } +} + +impl FromIterator for Diagnostics { + fn from_iter>(iter: I) -> Self { + Diagnostics(iter.into_iter().collect()) + } +} + +impl std::ops::Deref for Diagnostics { + type Target = [Diagnostic]; + + fn deref(&self) -> &[Diagnostic] { + &self.0 + } +} + +impl IntoIterator for Diagnostics { + type Item = Diagnostic; + type IntoIter = std::vec::IntoIter; + + fn into_iter(self) -> Self::IntoIter { + self.0.into_iter() + } +} + +impl<'a> IntoIterator for &'a Diagnostics { + type Item = &'a Diagnostic; + type IntoIter = std::slice::Iter<'a, Diagnostic>; + + fn into_iter(self) -> Self::IntoIter { + self.0.iter() + } +} + +impl fmt::Display for Diagnostics { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + for (i, d) in self.0.iter().enumerate() { + if i > 0 { + writeln!(f)?; + } + write!(f, "{d}")?; + } + Ok(()) + } +} + +impl std::error::Error for Diagnostics {} diff --git a/crates/sysmlv2-syntax/src/lexer.rs b/crates/sysmlv2-syntax/src/lexer.rs index 9457f92..84c7c4e 100644 --- a/crates/sysmlv2-syntax/src/lexer.rs +++ b/crates/sysmlv2-syntax/src/lexer.rs @@ -24,15 +24,27 @@ use crate::diag::Diagnostic; use crate::span::Span; use crate::token::{Token, TokenKind}; +/// The most token slots reserved before tokenizing, whatever the input +/// size (see the estimate below). +const MAX_TOKEN_HINT: usize = 64 * 1024; + /// Tokenize `src`, returning every token including trivia, terminated by an /// [`TokenKind::Eof`] token. Malformed input yields `Error` tokens plus /// diagnostics; the token stream always covers the entire input. +#[must_use] pub fn tokenize(src: &str) -> (Vec, Vec) { let mut lexer = Lexer { src: src.as_bytes(), text: src, pos: 0, - tokens: Vec::new(), + // Measured across the corpora, source text runs about two bytes + // to the token once trivia is counted. The estimate is capped + // because the ratio is a property of written notation, not of + // text: a file that is mostly one long comment is a couple of + // tokens, and a slot per two bytes of it would reserve orders of + // magnitude more than the lexer will fill. Past the cap the + // vector grows the usual way. + tokens: Vec::with_capacity((src.len() / 2 + 1).min(MAX_TOKEN_HINT)), diags: Vec::new(), }; lexer.run(); @@ -55,13 +67,16 @@ impl<'s> Lexer<'s> { debug_assert!(self.pos > start, "lexer must always make progress"); self.tokens.push(Token::new(kind, self.span_from(start))); } - let end = self.src.len() as u32; + let end = crate::span::clamp_offset(self.src.len()); self.tokens .push(Token::new(TokenKind::Eof, Span::new(end, end))); } fn span_from(&self, start: usize) -> Span { - Span::new(start as u32, self.pos as u32) + Span::new( + crate::span::clamp_offset(start), + crate::span::clamp_offset(self.pos), + ) } fn peek(&self, ahead: usize) -> Option { @@ -343,8 +358,14 @@ impl<'s> Lexer<'s> { /// Decode the value of an `UNRESTRICTED_NAME` or `STRING_VALUE` token: strip /// the quotes and resolve escape sequences. Invalid escapes (already reported /// by the lexer) are kept verbatim without the backslash. +/// +/// Total over any input: a leading quote and a trailing quote are removed +/// when present, so text that is not a complete token — empty, unterminated, +/// or never quoted at all — decodes to what it holds rather than failing. +#[must_use] pub fn unescape(raw: &str) -> String { - let inner = &raw[1..raw.len().saturating_sub(1).max(1)]; + let inner = raw.strip_prefix(['\'', '"']).unwrap_or(raw); + let inner = inner.strip_suffix(['\'', '"']).unwrap_or(inner); let mut out = String::with_capacity(inner.len()); let mut chars = inner.chars(); while let Some(c) = chars.next() { diff --git a/crates/sysmlv2-syntax/src/lib.rs b/crates/sysmlv2-syntax/src/lib.rs index f682624..8e5acc5 100644 --- a/crates/sysmlv2-syntax/src/lib.rs +++ b/crates/sysmlv2-syntax/src/lib.rs @@ -15,5 +15,5 @@ pub mod span; pub mod token; pub mod visit; -pub use diag::Diagnostic; +pub use diag::{Diagnostic, Diagnostics}; pub use span::Span; diff --git a/crates/sysmlv2-syntax/src/name.rs b/crates/sysmlv2-syntax/src/name.rs index 813e37a..d10cc5c 100644 --- a/crates/sysmlv2-syntax/src/name.rs +++ b/crates/sysmlv2-syntax/src/name.rs @@ -8,6 +8,29 @@ //! non-basic name is quoted with the lexer's escapes, and anything else //! prints bare. The printer uses the same function, so a generated //! spelling can never disagree with what the formatter would emit. +//! +//! Two forms of a name exist side by side and must not be confused: +//! +//! - the **canonical** form, [`escape_name`] — the specification's +//! `escapedName` derivation (KerML 8.3.2.1: a name with the *form* of +//! a basic name is returned as-is), which the model's qualified names, +//! the interchange `qualifiedName` property and the normative id +//! computations use. A reserved word used as a name stays bare there +//! (`ControlFunctions::if`), exactly as the pilot implementation +//! derives and hashes it; +//! - the **reference** form, [`spell_name`] / [`spell_path`] — what the +//! textual notation re-parses. A reserved word has the form of a +//! basic name but cannot be used as one (KerML 8.2.2.6), so it is +//! quoted here. Anything that turns a canonical name back into source +//! text goes through this form; [`respell_canonical`] converts. +//! +//! Which reserved-word table governs is a property of the text being +//! produced, not of the element: text printed into a known unit uses +//! that unit's dialect, and a spelling produced without a destination +//! (an API answer a host splices anywhere, a rename touching both +//! kinds of unit) quotes the words of *either* dialect — a quoted name +//! is legal in both, so the union is the destination-agnostic safe +//! choice. use crate::ast::{Dialect, escape_name}; use crate::parser::is_reserved; @@ -42,14 +65,97 @@ impl std::error::Error for NameError {} /// Spell `name` as the printer would in `dialect`, without a legality /// check (an empty name spells as `''`). +#[must_use] pub fn spell_name(dialect: Dialect, name: &str) -> String { - if is_reserved(dialect, name) { + spell_name_in(Some(dialect), name) +} + +/// Spell `name` so it re-parses as a name in `dialect` — or, with +/// `None`, in either dialect: quoted when it is a reserved word of the +/// governing table(s) or not a basic name, bare otherwise. No legality +/// check (an empty name spells as `''`). +#[must_use] +pub fn spell_name_in(dialect: Option, name: &str) -> String { + let reserved = match dialect { + Some(d) => is_reserved(d, name), + None => is_reserved(Dialect::Sysml, name) || is_reserved(Dialect::Kerml, name), + }; + if reserved { format!("'{name}'") } else { escape_name(name) } } +/// Spell raw (unescaped) name segments as a `::`-joined qualified +/// reference for `dialect` (`None`: either dialect — see +/// [`spell_name_in`]). +pub fn spell_path(dialect: Option, segments: I) -> String +where + I: IntoIterator, + S: AsRef, +{ + segments + .into_iter() + .map(|s| spell_name_in(dialect, s.as_ref())) + .collect::>() + .join("::") +} + +/// Split a canonical qualified name — [`escape_name`] segments joined +/// by `::`, as the model's qualified names and the interchange +/// `qualifiedName` are spelled — into its raw segments: the inverse of +/// `escape_name` applied per segment. Quoted segments unescape (so a +/// `::` inside quotes does not split) and bare segments are taken +/// verbatim, which reads a reserved word spelled either way. +#[must_use] +pub fn split_canonical(canonical: &str) -> Vec { + let mut out = Vec::new(); + let mut cur = String::new(); + let mut chars = canonical.chars().peekable(); + while let Some(c) = chars.next() { + match c { + '\'' => { + while let Some(c) = chars.next() { + match c { + '\\' => match chars.next() { + Some('b') => cur.push('\u{0008}'), + Some('t') => cur.push('\t'), + Some('n') => cur.push('\n'), + Some('f') => cur.push('\u{000C}'), + Some('r') => cur.push('\r'), + Some(e) => cur.push(e), + None => {} + }, + '\'' => break, + c => cur.push(c), + } + } + } + ':' if chars.peek() == Some(&':') => { + chars.next(); + out.push(std::mem::take(&mut cur)); + } + c => cur.push(c), + } + } + out.push(cur); + out +} + +/// Respell a canonical qualified name (see [`split_canonical`]) as +/// reference text for `dialect` (`None`: either dialect). A leading +/// global-root marker `$::` is kept. This is how a host turns a +/// reported `qualifiedName` into an `import`/`expose` target that +/// parses. +#[must_use] +pub fn respell_canonical(dialect: Option, canonical: &str) -> String { + match canonical.strip_prefix("$::") { + Some(rest) => format!("$::{}", spell_path(dialect, split_canonical(rest))), + None => spell_path(dialect, split_canonical(canonical)), + } +} + /// The canonical spelling of `name` in `dialect`, or why it is not a /// legal name. pub fn canonical_name(dialect: Dialect, name: &str) -> Result { @@ -111,6 +217,63 @@ mod tests { assert_eq!(sysml("line\nbreak").spelling, "'line\\nbreak'"); } + #[test] + fn either_dialect_spelling_quotes_the_union() { + // `part` is SysML-only, `end` KerML-only in name, `as` in both. + assert_eq!(spell_name_in(None, "part"), "'part'"); + assert_eq!(spell_name_in(None, "end"), "'end'"); + assert_eq!(spell_name_in(None, "as"), "'as'"); + assert_eq!(spell_name_in(None, "Node"), "Node"); + assert_eq!(spell_name_in(None, "no-referrer"), "'no-referrer'"); + assert_eq!(spell_name_in(Some(Dialect::Kerml), "part"), "part"); + assert_eq!(spell_name_in(Some(Dialect::Sysml), "part"), "'part'"); + } + + #[test] + fn paths_spell_per_segment() { + assert_eq!( + spell_path(None, ["part", "view", "Node"]), + "'part'::'view'::Node" + ); + assert_eq!( + spell_path(Some(Dialect::Kerml), ["part", "view", "Node"]), + "part::view::Node" + ); + assert_eq!(spell_path(None, ["My Views", "x"]), "'My Views'::x"); + assert_eq!(spell_path(None, [""]), "''"); + } + + #[test] + fn canonical_names_split_and_respell() { + // The inverse of `escape_name` per segment, on every escape. + for segs in [ + vec!["A", "b"], + vec!["My Views", "part"], + vec!["it's", "a\\b", "x::y"], + vec!["line\nbreak", "tab\tx", "\"q\""], + vec![""], + ] { + let canonical = segs + .iter() + .map(|s| escape_name(s)) + .collect::>() + .join("::"); + assert_eq!(split_canonical(&canonical), segs, "{canonical}"); + } + assert_eq!(respell_canonical(None, "part::view"), "'part'::'view'"); + assert_eq!(respell_canonical(None, "part::'view'"), "'part'::'view'"); + assert_eq!( + respell_canonical(Some(Dialect::Kerml), "part::view"), + "part::view" + ); + assert_eq!(respell_canonical(None, "'My Views'::x"), "'My Views'::x"); + assert_eq!(respell_canonical(None, "$::part::x"), "$::'part'::x"); + // Respelling is idempotent: reference text is its own canonical + // form's respelling. + let spelled = respell_canonical(None, "part::'it\\'s'::x::y"); + assert_eq!(respell_canonical(None, &spelled), spelled); + } + #[test] fn empty_is_illegal() { assert_eq!(canonical_name(Dialect::Sysml, ""), Err(NameError::Empty)); diff --git a/crates/sysmlv2-syntax/src/parser.rs b/crates/sysmlv2-syntax/src/parser.rs index 40a06f2..505dc9e 100644 --- a/crates/sysmlv2-syntax/src/parser.rs +++ b/crates/sysmlv2-syntax/src/parser.rs @@ -30,17 +30,20 @@ pub struct Parse { } impl Parse { + #[must_use] pub fn has_errors(&self) -> bool { !self.diagnostics.is_empty() } } /// Parse a `.sysml` source text (root namespace, SysML dialect). +#[must_use] pub fn parse_source(src: &str) -> Parse { parse_dialect(src, Dialect::Sysml) } /// Parse a `.kerml` source text (root namespace, KerML dialect). +#[must_use] pub fn parse_kerml_source(src: &str) -> Parse { parse_dialect(src, Dialect::Kerml) } @@ -60,12 +63,10 @@ pub struct ExprParse { /// an error. Expressions are shared between the dialects; the SysML /// reserved-word set applies, so reserved names need quoting (`'part'` /// stays a plain name in KerML but must be quoted here). +#[must_use] pub fn parse_expression(src: &str) -> ExprParse { - let (all_tokens, mut diags) = tokenize(src); - let tokens: Vec = all_tokens - .into_iter() - .filter(|t| !t.kind.is_trivia()) - .collect(); + let (mut tokens, mut diags) = tokenize(src); + tokens.retain(|t| !t.kind.is_trivia()); let mut p = Parser { src, tokens, @@ -75,6 +76,9 @@ pub fn parse_expression(src: &str) -> ExprParse { meta_body: false, enum_body: false, semi_repair: SemiRepair::Off, + depth: 0, + expr_frames: 0, + expr_chain: 0, }; let expr = p.parse_expr(); if expr.is_some() && !p.at_eof() { @@ -94,11 +98,34 @@ pub fn parse_expression(src: &str) -> ExprParse { } fn parse_dialect(src: &str, dialect: Dialect) -> Parse { - let (all_tokens, mut diags) = tokenize(src); - let tokens: Vec = all_tokens - .into_iter() - .filter(|t| !t.kind.is_trivia()) - .collect(); + parse_keeping_notes(src, dialect, None) +} + +/// Parse and hand back the note tokens in source order, from the one +/// tokenization the parse already does. The formatter needs the notes the +/// parser drops as trivia, and re-lexing the file to recover them doubles +/// the lexical work. +pub(crate) fn parse_with_notes(src: &str, dialect: Dialect) -> (Parse, Vec<(Span, String)>) { + let mut notes = Vec::new(); + let parse = parse_keeping_notes(src, dialect, Some(&mut notes)); + (parse, notes) +} + +fn parse_keeping_notes( + src: &str, + dialect: Dialect, + notes: Option<&mut Vec<(Span, String)>>, +) -> Parse { + let (mut tokens, mut diags) = tokenize(src); + if let Some(notes) = notes { + notes.extend( + tokens + .iter() + .filter(|t| matches!(t.kind, TokenKind::LineNote | TokenKind::BlockNote)) + .map(|t| (t.span, t.text(src).trim_end().to_string())), + ); + } + tokens.retain(|t| !t.kind.is_trivia()); let mut p = Parser { src, tokens, @@ -108,6 +135,9 @@ fn parse_dialect(src: &str, dialect: Dialect) -> Parse { meta_body: false, enum_body: false, semi_repair: SemiRepair::Off, + depth: 0, + expr_frames: 0, + expr_chain: 0, }; let unit = p.parse_root(); diags.append(&mut p.diags); @@ -117,6 +147,138 @@ fn parse_dialect(src: &str, dialect: Dialect) -> Parse { } } +/// How deeply bodies and expressions may nest before the parser reports +/// that the input is too deeply nested and stops descending. +/// +/// Nesting is bounded because descending is recursive and running out of +/// stack ends the process outright instead of producing a diagnostic. The +/// number is above every depth the toolkit supports downstream — a name is +/// resolved through at most sixty-four owners, and the published example +/// and library models nest ten levels of braces — so it turns unbounded +/// input into a diagnostic without standing in the way of a real model. +/// +/// The bound assumes a stack it fits inside: [`MAX_NESTING_STACK_BYTES`]. +pub const MAX_NESTING: u32 = 128; + +/// The stack a thread needs to parse input nested to [`MAX_NESTING`]. +/// +/// A bound on the descent only turns unbounded input into a diagnostic +/// where the stack reaches the bound. On a smaller one the process ends +/// at some shallower depth the parser accepts — a stack overflow, which +/// is an abort, not a diagnostic and not even an unwind — so a thread +/// that parses has to hold the whole of what the parser admits. +/// +/// Measured over the deepest input the bound admits: bodies nested to +/// the bound cost the most, and which body is dearest shows only +/// unoptimized — a flow's costs about ten and a half megabytes there, +/// against about nine and three quarters for the part bodies the probes +/// nest, while optimized both come in just under four. Nesting that +/// carries a full operator chain at its deepest level costs a little +/// less again. This is sized above the largest unoptimized figure, so +/// it holds in either build. +/// +/// A thread that does not ask for a stack gets two megabytes, which +/// holds about seventy of the levels an optimized build admits and +/// about two dozen unoptimized; [`on_parsing_stack`] is how a thread +/// asks for this instead. Reserved address space only — pages are +/// committed as the recursion touches them. +pub const MAX_NESTING_STACK_BYTES: usize = 16 << 20; + +/// Run `work` on a thread holding [`MAX_NESTING_STACK_BYTES`], named +/// `name`. +/// +/// The nesting bound only turns unbounded input into a diagnostic on a +/// stack that reaches the bound, and a thread that asks for no stack +/// does not have one. Every entry point of this workspace that parses +/// runs its work through here — the command line and the language +/// server's loop — and the server's workspace worker reserves the same +/// size on the thread it spawns. +/// +/// An embedder's thread is not one of those: a library call parses on +/// whichever thread makes it. One that may be handed deeply nested +/// input can call this, or reserve the same size on a thread of its +/// own. +/// +/// Where no thread can be had — a target without them, a host that +/// refuses one — `work` runs on the calling thread, which then reaches +/// only as deep as that stack allows: input the bound admits can run the +/// descent out of stack, and that ends the process outright, with no +/// diagnostic and no unwind. A host that refused the thread is told so +/// through `refused`, which is handed what the system said and reports it +/// the way the caller's channel allows, before `work` runs. A target +/// without threads is not a refusal and does not reach it. +pub fn on_parsing_stack(name: &str, refused: impl FnOnce(&std::io::Error), work: F) -> T +where + F: FnOnce() -> T + Send, + T: Send, +{ + // The work is handed to the thread, so it cannot simply be called + // again where the thread never starts: the thread takes it from + // here, and it is still here when nothing took it. + let mut work = Some(work); + #[cfg(not(target_family = "wasm"))] + { + let spawned = std::thread::scope(|scope| { + let slot = &mut work; + std::thread::Builder::new() + .name(name.to_string()) + .stack_size(MAX_NESTING_STACK_BYTES) + .spawn_scoped(scope, move || { + (slot.take().expect("the work is taken once"))() + }) + .map(std::thread::ScopedJoinHandle::join) + }); + match spawned { + Ok(Ok(value)) => return value, + Ok(Err(panic)) => std::panic::resume_unwind(panic), + // No thread to be had: nothing took the work, so it runs + // here — on a stack that was not reserved, which is what the + // caller is told before the work starts. + Err(err) => refused(&err), + } + } + #[cfg(target_family = "wasm")] + let _ = (name, refused); + work.take().expect("no thread took the work")() +} + +/// The most operators one leaning chain of an expression may spell. +/// +/// Operators at one precedence level, feature-chain steps, indexes and +/// `->` applications are all built iteratively, so no descent is charged +/// for them — but the tree each builds leans one node deep per operator, +/// and *walking* that tree recurses: dropping it, printing it, checking +/// it, emitting it. An unbounded chain therefore exhausts the stack +/// outside the parser, where there is no diagnostic to report. +/// +/// The budget measures the longest chain of operators leaning on one +/// another, not the number of nodes in the expression: a branch hanging +/// off the chain — an operand on the right, one item of a sequence, one +/// argument of an invocation, one member of a body — spells a chain of +/// its own, and what an operator leans on is the longer of the two. So a +/// thousand short operands cost what one of them costs, while a thousand +/// operators stacked on one another are refused however they are spelled. +/// The bound is far above the chain any written expression spells and far +/// below the depth those walks can hold on the smallest stack the toolkit +/// ships against. +pub const MAX_EXPR_OPERATORS: u32 = 1024; + +thread_local! { + static ACCEPT_LOOKAHEAD_TOKENS: std::cell::Cell = const { std::cell::Cell::new(0) }; +} + +/// Tokens the accept-member lookahead has read on this thread since this +/// was last called, and reset the count to zero. +/// +/// Classifying a member that begins with `accept` needs a look ahead for +/// the transition shorthand's `then`. The scan is meant to stop within +/// the member it classifies, whether or not that member is well formed; +/// this reports what it actually read, so the cost can be pinned without +/// timing the machine it runs on. +pub fn take_accept_lookahead_tokens() -> u64 { + ACCEPT_LOOKAHEAD_TOKENS.with(|n| n.replace(0)) +} + /// Words reserved by the SysML dialect (SysML.xtext ∪ KerMLExpressions.xtext). /// Must stay sorted: looked up by binary search. const RESERVED: &[&str] = &[ @@ -390,9 +552,20 @@ struct Parser<'s> { /// an entirely empty usage followed by its terminating semicolon. enum_body: bool, semi_repair: SemiRepair, + /// How many bodies and expressions are open above the current one. + /// Both recurse, so both count against the same budget. + depth: u32, + /// How many expression frames are open above the current one. Zero at + /// the start of a member's outermost expression, which is where the + /// chain budget below is refilled. + expr_frames: u32, + /// How deep the expression completed at this position leans — the + /// longest chain of operators in it (see [`MAX_EXPR_OPERATORS`]). + expr_chain: u32, } /// Is `word` reserved in `dialect` (and thus unusable as a bare name)? +#[must_use] pub fn is_reserved(dialect: Dialect, word: &str) -> bool { let table = match dialect { Dialect::Sysml => RESERVED, @@ -723,8 +896,48 @@ impl<'s> Parser<'s> { } fn parse_body_members(&mut self) -> Vec { + if self.depth >= MAX_NESTING { + self.error_here(format!( + "nesting is too deep (more than {MAX_NESTING} levels of bodies and expressions)" + )); + self.skip_to_body_close(); + return Vec::new(); + } + self.depth += 1; + let members = self.parse_body_members_inner(); + self.depth -= 1; + members + } + + /// Consume the rest of the current body, leaving its closing brace for + /// the caller. Used when the parser refuses to descend any further, so + /// that one diagnostic is reported instead of a cascade. + fn skip_to_body_close(&mut self) { + let mut depth = 0i32; + while !self.at_eof() { + match self.cur().kind { + TokenKind::LBrace => depth += 1, + TokenKind::RBrace => { + if depth == 0 { + return; + } + depth -= 1; + } + _ => {} + } + self.bump(); + } + } + + fn parse_body_members_inner(&mut self) -> Vec { let mut members = Vec::new(); + // Members of a body are siblings: each spells a chain of its own + // rather than continuing the one its predecessor spelled, and the + // body leans as deep as its deepest member (see [`Self::branch`]). + let mut deepest = self.expr_chain; while !self.at(TokenKind::RBrace) && !self.at_eof() { + deepest = deepest.max(self.expr_chain); + self.expr_chain = 0; let before = self.pos; let diags_before = self.diags.len(); match self.parse_member() { @@ -806,6 +1019,7 @@ impl<'s> Parser<'s> { } } } + self.expr_chain = deepest.max(self.expr_chain); members } @@ -830,7 +1044,7 @@ impl<'s> Parser<'s> { let checkpoint = self.pos; self.bump(); if self.at(TokenKind::LBracket) { - leading_then_multiplicity = self.parse_multiplicity().map(Box::new); + leading_then_multiplicity = self.parse_multiplicity(); } let starts_full_member = self.at(TokenKind::Hash) || self.at_kw("public") @@ -873,7 +1087,10 @@ impl<'s> Parser<'s> { prefix: UsagePrefix::default(), kind: UsageKind::Succession, declaration: FeatureDeclaration::default(), - detail: UsageDetail::Succession { source, target }, + detail: UsageDetail::Succession { + source: source.map(Box::new), + target: Box::new(target), + }, value: None, is_parallel: false, body, @@ -1074,7 +1291,10 @@ impl<'s> Parser<'s> { prefix: UsagePrefix::default(), kind: UsageKind::Succession, declaration: FeatureDeclaration::default(), - detail: UsageDetail::Succession { source, target }, + detail: UsageDetail::Succession { + source: source.map(Box::new), + target: Box::new(target), + }, value: None, is_parallel: false, body, @@ -1094,7 +1314,7 @@ impl<'s> Parser<'s> { trigger: None, guard: None, effect: None, - target: Some(target), + target: Some(Box::new(target)), is_default: true, }, value: None, @@ -1331,8 +1551,8 @@ impl<'s> Parser<'s> { kind: UsageKind::Succession, declaration: FeatureDeclaration::default(), detail: UsageDetail::Succession { - source: Some(source), - target, + source: Some(Box::new(source)), + target: Box::new(target), }, value: None, is_parallel: false, @@ -1351,9 +1571,9 @@ impl<'s> Parser<'s> { detail: UsageDetail::Transition { source: Some(source.target), trigger: None, - guard: Some(guard), + guard: Some(Box::new(guard)), effect: None, - target: Some(target), + target: Some(Box::new(target)), is_default: false, }, value: None, @@ -1415,9 +1635,9 @@ impl<'s> Parser<'s> { detail: UsageDetail::Transition { source: None, trigger: None, - guard: Some(cond), + guard: Some(Box::new(cond)), effect, - target: Some(target), + target: Some(Box::new(target)), is_default: false, }, value: None, @@ -1434,28 +1654,151 @@ impl<'s> Parser<'s> { /// `;`/`{` after the payload) rather than a transition shorthand /// (`accept … then …`)? Scan ahead for `then`/`if`/`do` before the /// terminator. + /// + /// A brace only nests where an expression may spell one: the + /// body-expression argument of an operator applied through `->` + /// (`xs->exists { in x; x > 0 }`), or an operand position inside a + /// trigger or value expression. A brace anywhere a complete expression + /// has just ended — after a name, a literal or a closing bracket — + /// opens the node's own body and ends the scan. + /// + /// Only a brace can hold a `;`, so an unclosed `(` or `[` never + /// carries the scan past the member's own terminator, and a run of + /// members that each leave a bracket open costs time linear in the + /// body rather than quadratic. Unclosed braces are bounded instead by + /// the nesting the parser will descend at all: past that the input is + /// refused whichever way this classifies it. Within those bounds the + /// scan is not truncated by a token count — an arbitrarily long + /// trigger is still classified from its own tokens. fn accept_is_node(&self) -> bool { - let mut i = 1; - let mut depth = 0i32; + let mut scanned = 1; + let is_node = self.accept_node_scan(&mut scanned); + ACCEPT_LOOKAHEAD_TOKENS.with(|n| n.set(n.get().saturating_add(scanned as u64))); + is_node + } + + /// The scan itself, leaving the token it stopped at in `i` so its cost + /// can be observed (see [`take_accept_lookahead_tokens`]). + fn accept_node_scan(&self, i: &mut usize) -> bool { + #[derive(PartialEq, Eq, Clone, Copy)] + enum ArrowRef { + /// Not in the target reference of `->`. + No, + /// A name is expected next: just after `->`, `::`, `.` or the + /// global-scope root `$`. + Expect, + /// The last token was one of the reference's names. + InName, + } + + // Expression braces the scan has entered, and parentheses and + // brackets within them. They are counted apart because a `;` ends + // the member wherever a brace is not holding it. + let mut braces = 0i32; + let mut groups = 0i32; + // Whether a `{` at this point would open an expression rather than + // the node's own body. + let mut expr_brace = false; + // Where in the target reference of `->` the scan stands. The + // reference names the operator whose argument may be a body + // expression, and its own words are not member keywords. + let mut arrow = ArrowRef::No; loop { - let t = self.nth(i); + let t = self.nth(*i); match t.kind { TokenKind::Eof => return true, - TokenKind::Semi | TokenKind::LBrace if depth == 0 => return true, - TokenKind::LParen | TokenKind::LBracket => depth += 1, - TokenKind::RParen | TokenKind::RBracket => depth -= 1, - TokenKind::Ident if depth == 0 => { + TokenKind::Semi if braces == 0 => return true, + TokenKind::LBrace if braces == 0 && groups == 0 && !expr_brace => return true, + TokenKind::RBrace if braces == 0 => return true, + TokenKind::LBrace => { + braces += 1; + if braces > MAX_NESTING as i32 { + return true; + } + } + TokenKind::RBrace => braces -= 1, + TokenKind::LParen | TokenKind::LBracket => groups += 1, + TokenKind::RParen | TokenKind::RBracket if groups > 0 => groups -= 1, + TokenKind::Ident if braces == 0 && groups == 0 && arrow != ArrowRef::Expect => { let text = t.text(self.src); - if text == "then" || text == "if" || text == "do" { + // `if` is the shorthand's guard only where a complete + // expression has just ended. Where an operand is + // expected instead it opens a conditional expression + // — the trigger, the `via` expression and a payload's + // value are all parsed as full expressions, and each + // admits one — so the same state that says whether a + // brace would open an expression says whether this + // `if` does. + if text == "then" || text == "do" || (text == "if" && !expr_brace) { return false; } } _ => {} } - i += 1; - if i > 200 { - return true; + // What a `{` would mean *after* this token. + match t.kind { + TokenKind::Arrow => { + arrow = ArrowRef::Expect; + expr_brace = false; + } + // A target reference continues through a qualification, a + // feature-chain step, and the global-scope root it may + // start from: `->f.g { … }`, `->$::Q::exists { … }`. + TokenKind::ColonColon | TokenKind::Dot if arrow == ArrowRef::InName => { + arrow = ArrowRef::Expect; + expr_brace = false; + } + TokenKind::Dollar if arrow == ArrowRef::Expect => { + arrow = ArrowRef::InName; + expr_brace = true; + } + TokenKind::Ident | TokenKind::UnrestrictedName => { + expr_brace = if arrow == ArrowRef::Expect { + arrow = ArrowRef::InName; + true + } else { + arrow = ArrowRef::No; + // Words an operand follows: the trigger and `via` + // clauses introduce one, `else` continues a + // conditional expression with one, and the + // word-spelled operators take one the way their + // symbolic spellings do. The classification words + // (`as`, `istype`, `hastype`, `meta`) and `all` + // take a type name instead, where a brace cannot + // stand, so they are not here. + matches!( + t.text(self.src), + "at" | "after" + | "when" + | "via" + | "else" + | "and" + | "or" + | "xor" + | "implies" + | "not" + ) + }; + } + TokenKind::String + | TokenKind::Decimal + | TokenKind::Exp + | TokenKind::RParen + | TokenKind::RBracket + | TokenKind::RBrace + | TokenKind::LBrace => { + arrow = ArrowRef::No; + expr_brace = false; + } + // Operators, separators and openers all leave an operand + // expected, and an expression may spell that operand as a + // body. + _ => { + arrow = ArrowRef::No; + expr_brace = true; + } } + *i += 1; } } @@ -1520,9 +1863,9 @@ impl<'s> Parser<'s> { detail: UsageDetail::Transition { source, trigger, - guard, + guard: guard.map(Box::new), effect, - target: Some(target), + target: Some(Box::new(target)), is_default: false, }, value: None, @@ -1580,9 +1923,9 @@ impl<'s> Parser<'s> { detail: UsageDetail::Transition { source, trigger, - guard, + guard: guard.map(Box::new), effect, - target: Some(target), + target: Some(Box::new(target)), is_default: false, }, value: None, @@ -1619,7 +1962,11 @@ impl<'s> Parser<'s> { prefix: UsagePrefix::default(), kind: UsageKind::Send, declaration: FeatureDeclaration::default(), - detail: UsageDetail::Send { payload, via, to }, + detail: UsageDetail::Send { + payload: payload.map(Box::new), + via: via.map(Box::new), + to: to.map(Box::new), + }, value: None, is_parallel: false, body, @@ -1657,7 +2004,10 @@ impl<'s> Parser<'s> { prefix: UsagePrefix::default(), kind: UsageKind::Assign, declaration: FeatureDeclaration::default(), - detail: UsageDetail::Assign { target, value }, + detail: UsageDetail::Assign { + target: Box::new(target), + value: Box::new(value), + }, value: None, is_parallel: false, body, @@ -1677,7 +2027,11 @@ impl<'s> Parser<'s> { prefix: UsagePrefix::default(), kind: UsageKind::Send, declaration, - detail: UsageDetail::Send { payload, via, to }, + detail: UsageDetail::Send { + payload: payload.map(Box::new), + via: via.map(Box::new), + to: to.map(Box::new), + }, value: None, is_parallel: false, body, @@ -1714,8 +2068,8 @@ impl<'s> Parser<'s> { kind: UsageKind::Assign, declaration, detail: UsageDetail::Assign { - target, - value: assigned, + target: Box::new(target), + value: Box::new(assigned), }, value: None, is_parallel: false, @@ -1760,7 +2114,7 @@ impl<'s> Parser<'s> { Some(ConnectorEnd { multiplicity, name: None, - target: TargetRef::Chain(Vec::new()), + target: TargetRef::unspelled(), }) } else { None @@ -1995,7 +2349,7 @@ impl<'s> Parser<'s> { self.expect_kw("multiplicity"); let id = self.parse_identification(); let (subsets, range) = if self.at(TokenKind::LBracket) { - (None, self.parse_multiplicity()) + (None, self.parse_multiplicity().map(|m| *m)) } else { if !self.eat(TokenKind::ColonGt) { self.expect_kw("subsets"); @@ -2414,8 +2768,8 @@ impl<'s> Parser<'s> { self.expect_kw("then"); let target = self.parse_connector_end()?; UsageDetail::Succession { - source: Some(source), - target, + source: Some(Box::new(source)), + target: Box::new(target), } } else { UsageDetail::None @@ -3147,7 +3501,9 @@ impl<'s> Parser<'s> { usage_prefix, UsageKind::Terminate, FeatureDeclaration::default(), - UsageDetail::Terminate { target }, + UsageDetail::Terminate { + target: target.map(Box::new), + }, ) .map(MemberKind::Usage); } @@ -3356,7 +3712,8 @@ impl<'s> Parser<'s> { }) } - /// Like [`parse_body`] but distinguishes `None` (`;`) from parse failure. + /// Like [`Parser::parse_brace_body`] but distinguishes `None` (a `;` + /// body) from a parse failure. fn parse_body_or_semi(&mut self) -> Option>> { self.parse_body_or_semi_ctx(false, false) } @@ -3471,7 +3828,9 @@ impl<'s> Parser<'s> { prefix, UsageKind::Terminate, declaration, - UsageDetail::Terminate { target }, + UsageDetail::Terminate { + target: target.map(Box::new), + }, ); } } @@ -3566,9 +3925,9 @@ impl<'s> Parser<'s> { detail: UsageDetail::Transition { source: Some(source.target), trigger: None, - guard: Some(guard), + guard: Some(Box::new(guard)), effect: None, - target: Some(target), + target: Some(Box::new(target)), is_default: false, }, value: None, @@ -3584,8 +3943,8 @@ impl<'s> Parser<'s> { kind: UsageKind::Succession, declaration, detail: UsageDetail::Succession { - source: Some(source), - target, + source: Some(Box::new(source)), + target: Box::new(target), }, value: None, is_parallel: false, @@ -3646,7 +4005,7 @@ impl<'s> Parser<'s> { }; let detail = if payload.is_some() || source.is_some() { UsageDetail::Flow { - payload, + payload: payload.map(Box::new), source, target, } @@ -3965,9 +4324,9 @@ impl<'s> Parser<'s> { None }; Some(UsageDetail::Accept { - payload, - trigger, - via, + payload: Box::new(payload), + trigger: trigger.map(Box::new), + via: via.map(Box::new), }) } @@ -4006,7 +4365,11 @@ impl<'s> Parser<'s> { prefix, kind: UsageKind::Send, declaration, - detail: UsageDetail::Send { payload, via, to }, + detail: UsageDetail::Send { + payload: payload.map(Box::new), + via: via.map(Box::new), + to: to.map(Box::new), + }, value: None, is_parallel: false, body, @@ -4026,7 +4389,10 @@ impl<'s> Parser<'s> { prefix, kind: UsageKind::Assign, declaration, - detail: UsageDetail::Assign { target, value }, + detail: UsageDetail::Assign { + target: Box::new(target), + value: Box::new(value), + }, value: None, is_parallel: false, body, @@ -4052,6 +4418,31 @@ impl<'s> Parser<'s> { }) } + /// Just after `else`: does a nested if-node follow rather than an + /// anonymous action body? An if-node reaches its `if` keyword before any + /// body brace, however it is prefixed (`else if`, `else action a if`, + /// `else #Meta if`); an action-body parameter reaches the brace first. + /// Type arguments are balanced so an `if` inside a declaration's + /// parenthesised or bracketed parts does not count. + fn else_starts_if_node(&self) -> bool { + let mut i = 0; + let mut depth = 0i32; + loop { + let t = self.nth(i); + match t.kind { + TokenKind::Eof => return false, + TokenKind::LBrace | TokenKind::RBrace | TokenKind::Semi if depth == 0 => { + return false; + } + TokenKind::LParen | TokenKind::LBracket => depth += 1, + TokenKind::RParen | TokenKind::RBracket if depth > 0 => depth -= 1, + TokenKind::Ident if depth == 0 && t.is_kw(self.src, "if") => return true, + _ => {} + } + i += 1; + } + } + /// After `if ` where an action body follows. fn parse_if_node_rest( &mut self, @@ -4062,20 +4453,36 @@ impl<'s> Parser<'s> { let then_body = Box::new(self.parse_action_body_parameter()?); let else_body = if self.eat_kw("else") { // Both alternatives may start with `action`: an action-body - // parameter, or a nested IfNode carrying its full - // ActionNodePrefix. Try the complete node first, then roll back - // cleanly to the anonymous-action-body alternative. - let checkpoint = self.pos; - let diags = self.diags.len(); - let nested_if = match self.parse_definition_or_usage() { - Some(MemberKind::Usage(u)) if u.kind == UsageKind::IfNode => Some(u), - _ => None, - }; - if let Some(nested_if) = nested_if { - Some(Box::new(nested_if)) + // parameter, or a nested if-node carrying its full action node + // prefix. The `if` keyword that a nested node must reach before + // its body brace decides between them, so the alternative is + // chosen before parsing — parsing the branch speculatively and + // rolling back would re-parse every nested `else action { … }` + // level once per level. + if self.else_starts_if_node() { + let checkpoint = self.pos; + let diags = self.diags.len(); + // An else-if nests an action without an enclosing body. + // Charge this edge too, before entering its parser frames. + if self.depth >= MAX_NESTING { + self.refuse_deeper(format!( + "nesting is too deep (more than {MAX_NESTING} levels of bodies and expressions)" + )); + return None; + } + self.depth += 1; + let nested = self.parse_definition_or_usage(); + self.depth -= 1; + match nested { + None => return None, + Some(MemberKind::Usage(u)) if u.kind == UsageKind::IfNode => Some(Box::new(u)), + _ => { + self.pos = checkpoint; + self.diags.truncate(diags); + Some(Box::new(self.parse_action_body_parameter()?)) + } + } } else { - self.pos = checkpoint; - self.diags.truncate(diags); Some(Box::new(self.parse_action_body_parameter()?)) } } else { @@ -4089,7 +4496,7 @@ impl<'s> Parser<'s> { kind: UsageKind::IfNode, declaration, detail: UsageDetail::IfNode { - cond, + cond: Box::new(cond), then_body, else_body, }, @@ -4118,7 +4525,11 @@ impl<'s> Parser<'s> { prefix, kind: UsageKind::WhileLoop, declaration, - detail: UsageDetail::WhileLoop { cond, body, until }, + detail: UsageDetail::WhileLoop { + cond: cond.map(Box::new), + body, + until: until.map(Box::new), + }, value: None, is_parallel: false, body: None, @@ -4139,7 +4550,11 @@ impl<'s> Parser<'s> { prefix, kind: UsageKind::ForLoop, declaration, - detail: UsageDetail::ForLoop { var, seq, body }, + detail: UsageDetail::ForLoop { + var: Box::new(var), + seq: Box::new(seq), + body, + }, value: None, is_parallel: false, body: None, @@ -4277,7 +4692,9 @@ impl<'s> Parser<'s> { } } - fn parse_multiplicity(&mut self) -> Option { + /// Boxed: a multiplicity holds two expressions inline, and every + /// declaration that can carry one would otherwise pay for them. + fn parse_multiplicity(&mut self) -> Option> { let start = self.cur().span; self.expect(TokenKind::LBracket, "`[`")?; let Some(first) = self.parse_mult_bound() else { @@ -4295,11 +4712,11 @@ impl<'s> Parser<'s> { }; let end = self.cur().span; self.expect(TokenKind::RBracket, "`]` closing multiplicity"); - Some(Multiplicity { + Some(Box::new(Multiplicity { lower, upper, span: start.join(end), - }) + })) } /// After a malformed multiplicity bound, skip to (and past) the `]` @@ -4381,7 +4798,9 @@ impl<'s> Parser<'s> { None } - fn parse_value_part(&mut self) -> Option { + /// Boxed: a feature value holds an expression inline, and every + /// usage carries the slot whether or not it has a value. + fn parse_value_part(&mut self) -> Option> { let kind = if self.eat(TokenKind::Eq) { ValueKind::Bound } else if self.eat(TokenKind::ColonEq) { @@ -4397,24 +4816,80 @@ impl<'s> Parser<'s> { return None; }; let expr = self.parse_expr()?; - Some(FeatureValue { kind, expr }) + Some(Box::new(FeatureValue { kind, expr })) } // ---- expressions (KerML Expressions grammar, precedence climbing) ---- pub(crate) fn parse_expr(&mut self) -> Option { - self.parse_conditional() + self.descend(Self::parse_conditional) + } + + /// Take one expression-nesting step, running `parse` one level down. + /// + /// Every recursive expression path goes through here, so the bound is + /// charged wherever the parser descends — including the + /// right-associative exponentiation recursion, which does not return + /// through [`Self::parse_expr`]. + fn descend(&mut self, parse: fn(&mut Self) -> Option) -> Option { + if self.depth >= MAX_NESTING { + self.refuse_deeper(format!( + "nesting is too deep (more than {MAX_NESTING} levels of bodies and expressions)" + )); + return None; + } + if self.expr_frames == 0 { + self.expr_chain = 0; + } + self.depth += 1; + self.expr_frames += 1; + let expr = parse(self); + self.expr_frames -= 1; + self.depth -= 1; + expr + } + + /// Report that the parser will not take this expression any further, + /// and abandon the rest of it. + /// + /// One diagnostic per truncated subtree, as on the body path: the text + /// that will not be parsed is consumed here, so it does not reach the + /// member loop as a run of stray tokens each reported again. + fn refuse_deeper(&mut self, message: String) { + self.error_here(message); + self.skip_to_member_end(); + } + + /// Consume the rest of the current member, leaving its `;` — or the + /// closing brace of the enclosing body — for the caller. Brackets and + /// parentheses opened before this point were consumed by the frames + /// being abandoned, so a closer with no opener here belongs to the + /// abandoned text. + fn skip_to_member_end(&mut self) { + let mut depth = 0i32; + while !self.at_eof() { + match self.cur().kind { + TokenKind::Semi if depth == 0 => return, + TokenKind::RBrace if depth == 0 => return, + TokenKind::LBrace | TokenKind::LBracket | TokenKind::LParen => depth += 1, + TokenKind::RBrace | TokenKind::RBracket | TokenKind::RParen => { + depth = (depth - 1).max(0); + } + _ => {} + } + self.bump(); + } } fn parse_conditional(&mut self) -> Option { if self.at_kw("if") { let start = self.cur().span; self.bump(); - let cond = self.parse_null_coalescing()?; + let cond = self.branch(Self::parse_null_coalescing)?; self.expect(TokenKind::Question, "`?` in conditional expression"); - let then_branch = self.parse_expr()?; + let then_branch = self.branch(Self::parse_expr)?; self.expect_kw("else"); - let else_branch = self.parse_expr()?; + let else_branch = self.branch(Self::parse_expr)?; let span = start.join(else_branch.span); return Some(Expr { kind: ExprKind::Conditional { @@ -4428,23 +4903,57 @@ impl<'s> Parser<'s> { self.parse_null_coalescing() } - fn mk_binary(&self, op: BinaryOp, lhs: Expr, rhs: Expr) -> Expr { + /// Charge `links` more operators to the chain that leads here, and + /// refuse to build it any longer once it passes + /// [`MAX_EXPR_OPERATORS`]. + fn charge_chain(&mut self, links: u32) -> Option<()> { + self.expr_chain = self.expr_chain.saturating_add(links); + if self.expr_chain > MAX_EXPR_OPERATORS { + self.refuse_deeper(format!( + "expression has a chain of more than {MAX_EXPR_OPERATORS} operators" + )); + return None; + } + Some(()) + } + + /// Run `parse` as a branch hanging off the current chain rather than + /// as a continuation of it: an operand on the right, one item of a + /// sequence, one argument, one member of a body. + /// + /// The branch spells a chain of its own, so it starts from an empty + /// budget — siblings do not charge each other. What it reaches is + /// then folded back with a maximum, because the node that owns both + /// leans on whichever side is longer: a branch deeper than the chain + /// it hangs from keeps the whole expression's operators charged to + /// everything built above it. + fn branch(&mut self, parse: impl FnOnce(&mut Self) -> T) -> T { + let chain = std::mem::take(&mut self.expr_chain); + let parsed = parse(self); + self.expr_chain = chain.max(self.expr_chain); + parsed + } + + /// Build one binary node, charging it against the chain budget (see + /// [`MAX_EXPR_OPERATORS`]). + fn mk_binary(&mut self, op: BinaryOp, lhs: Expr, rhs: Expr) -> Option { + self.charge_chain(1)?; let span = lhs.span.join(rhs.span); - Expr { + Some(Expr { kind: ExprKind::Binary { op, lhs: Box::new(lhs), rhs: Box::new(rhs), }, span, - } + }) } fn parse_null_coalescing(&mut self) -> Option { let mut lhs = self.parse_implies()?; while self.eat(TokenKind::QuestionQuestion) { - let rhs = self.parse_implies()?; - lhs = self.mk_binary(BinaryOp::NullCoalescing, lhs, rhs); + let rhs = self.branch(Self::parse_implies)?; + lhs = self.mk_binary(BinaryOp::NullCoalescing, lhs, rhs)?; } Some(lhs) } @@ -4452,8 +4961,8 @@ impl<'s> Parser<'s> { fn parse_implies(&mut self) -> Option { let mut lhs = self.parse_or()?; while self.eat_kw("implies") { - let rhs = self.parse_or()?; - lhs = self.mk_binary(BinaryOp::Implies, lhs, rhs); + let rhs = self.branch(Self::parse_or)?; + lhs = self.mk_binary(BinaryOp::Implies, lhs, rhs)?; } Some(lhs) } @@ -4468,8 +4977,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_xor()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_xor)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4477,8 +4986,8 @@ impl<'s> Parser<'s> { fn parse_xor(&mut self) -> Option { let mut lhs = self.parse_and()?; while self.eat_kw("xor") { - let rhs = self.parse_and()?; - lhs = self.mk_binary(BinaryOp::Xor, lhs, rhs); + let rhs = self.branch(Self::parse_and)?; + lhs = self.mk_binary(BinaryOp::Xor, lhs, rhs)?; } Some(lhs) } @@ -4493,8 +5002,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_equality()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_equality)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4513,8 +5022,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_classification()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_classification)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4552,7 +5061,7 @@ impl<'s> Parser<'s> { kind: ExprKind::Classification { op, operand: None, - ty, + ty: Box::new(ty), }, span, } @@ -4571,12 +5080,13 @@ impl<'s> Parser<'s> { { let op = self.classification_op()?; let ty = self.parse_target_ref()?; + self.charge_chain(1)?; let span = lhs.span.join(ty.span()); lhs = Expr { kind: ExprKind::Classification { op, operand: Some(Box::new(lhs)), - ty, + ty: Box::new(ty), }, span, }; @@ -4598,8 +5108,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_range()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_range)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4607,8 +5117,8 @@ impl<'s> Parser<'s> { fn parse_range(&mut self) -> Option { let lhs = self.parse_additive()?; if self.eat(TokenKind::DotDot) { - let rhs = self.parse_additive()?; - return Some(self.mk_binary(BinaryOp::Range, lhs, rhs)); + let rhs = self.branch(Self::parse_additive)?; + return self.mk_binary(BinaryOp::Range, lhs, rhs); } Some(lhs) } @@ -4623,8 +5133,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_multiplicative()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_multiplicative)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4642,8 +5152,8 @@ impl<'s> Parser<'s> { } else { break; }; - let rhs = self.parse_exponentiation()?; - lhs = self.mk_binary(op, lhs, rhs); + let rhs = self.branch(Self::parse_exponentiation)?; + lhs = self.mk_binary(op, lhs, rhs)?; } Some(lhs) } @@ -4666,9 +5176,10 @@ impl<'s> Parser<'s> { } else { return Some(lhs); }; - // Right-associative. - let rhs = self.parse_exponentiation()?; - Some(self.mk_binary(op, lhs, rhs)) + // Right-associative: the recursion is this operator's right + // operand, one level further down, and is charged as such. + let rhs = self.branch(|p| p.descend(Self::parse_exponentiation))?; + self.mk_binary(op, lhs, rhs) } fn parse_unary(&mut self) -> Option { @@ -4706,7 +5217,7 @@ impl<'s> Parser<'s> { let ty = self.parse_target_ref()?; let span = start.join(ty.span()); return Some(Expr { - kind: ExprKind::Extent { ty }, + kind: ExprKind::Extent { ty: Box::new(ty) }, span, }); } @@ -4719,10 +5230,11 @@ impl<'s> Parser<'s> { if self.at(TokenKind::Dot) { // `.{ body }` = collect; `.metadata` = metadata access; // otherwise a feature-chain step. + self.charge_chain(1)?; match self.nth(1).kind { TokenKind::LBrace | TokenKind::Semi => { self.bump(); - let body = self.parse_body_expr()?; + let body = self.branch(Self::parse_body_expr)?; let span = expr.span.join(body.span); expr = Expr { kind: ExprKind::Collect { @@ -4733,19 +5245,28 @@ impl<'s> Parser<'s> { }; } _ if self.nth_kw(1, "metadata") => { - if let ExprKind::Ref(qn) = expr.kind.clone() { - self.bump(); - let end = self.bump().span; - expr = Expr { - kind: ExprKind::MetadataAccess { target: qn }, - span: expr.span.join(end), - }; - } else { - self.error_here( - "`.metadata` requires an element reference on the left".to_string(), - ); - self.bump(); - self.bump(); + // Move the left operand out rather than copying it: + // a chain of suffixes would clone everything parsed + // so far at each `.metadata`. + let span = expr.span; + match expr.kind { + ExprKind::Ref(qn) => { + self.bump(); + let end = self.bump().span; + expr = Expr { + kind: ExprKind::MetadataAccess { target: qn }, + span: span.join(end), + }; + } + kind => { + self.error_here( + "`.metadata` requires an element reference on the left" + .to_string(), + ); + self.bump(); + self.bump(); + expr = Expr { kind, span }; + } } } _ => { @@ -4762,8 +5283,9 @@ impl<'s> Parser<'s> { } } } else if self.at(TokenKind::DotQuestion) { + self.charge_chain(1)?; self.bump(); - let body = self.parse_body_expr()?; + let body = self.branch(Self::parse_body_expr)?; let span = expr.span.join(body.span); expr = Expr { kind: ExprKind::Select { @@ -4773,9 +5295,10 @@ impl<'s> Parser<'s> { span, }; } else if self.at(TokenKind::Hash) && self.nth(1).kind == TokenKind::LParen { + self.charge_chain(1)?; self.bump(); self.bump(); - let index = self.parse_sequence_expr()?; + let index = self.branch(Self::parse_sequence_expr)?; let end = self.cur().span; self.expect(TokenKind::RParen, "`)` closing index"); expr = Expr { @@ -4786,8 +5309,9 @@ impl<'s> Parser<'s> { }, }; } else if self.at(TokenKind::LBracket) { + self.charge_chain(1)?; self.bump(); - let arg = self.parse_sequence_expr()?; + let arg = self.branch(Self::parse_sequence_expr)?; let end = self.cur().span; self.expect(TokenKind::RBracket, "`]`"); expr = Expr { @@ -4798,14 +5322,15 @@ impl<'s> Parser<'s> { }, }; } else if self.at(TokenKind::Arrow) { + self.charge_chain(1)?; self.bump(); let ty = self.parse_target_ref()?; let args = if self.at(TokenKind::LBrace) || (self.dialect == Dialect::Sysml && self.at(TokenKind::Semi)) { - ArrowArgs::Body(Box::new(self.parse_body_expr()?)) + ArrowArgs::Body(Box::new(self.branch(Self::parse_body_expr)?)) } else if self.at(TokenKind::LParen) { - ArrowArgs::List(self.parse_argument_list()?) + ArrowArgs::List(self.branch(Self::parse_argument_list)?) } else { ArrowArgs::FunctionRef(self.parse_qualified_name()?) }; @@ -4813,7 +5338,7 @@ impl<'s> Parser<'s> { expr = Expr { kind: ExprKind::Arrow { target: Box::new(expr), - ty, + ty: Box::new(ty), args, }, span, @@ -4866,10 +5391,13 @@ impl<'s> Parser<'s> { if self.at_kw("new") { self.bump(); let ty = self.parse_target_ref()?; - let args = self.parse_argument_list()?; + let args = self.branch(Self::parse_argument_list)?; let span = start.join(self.prev_end_span()); return Some(Expr { - kind: ExprKind::Constructor { ty, args }, + kind: ExprKind::Constructor { + ty: Box::new(ty), + args, + }, span, }); } @@ -4906,25 +5434,27 @@ impl<'s> Parser<'s> { if self.at_name() || self.at(TokenKind::Dollar) { let target = self.parse_target_ref()?; if self.at(TokenKind::LParen) { - let args = self.parse_argument_list()?; + let args = self.branch(Self::parse_argument_list)?; let span = start.join(self.prev_end_span()); return Some(Expr { - kind: ExprKind::Invocation { ty: target, args }, + kind: ExprKind::Invocation { + ty: Box::new(target), + args, + }, span, }); } - return Some(match target { - TargetRef::Name(qn) => Expr { + return match target { + TargetRef::Name(qn) => Some(Expr { span: qn.span, kind: ExprKind::Ref(qn), - }, - chain @ TargetRef::Chain(_) => { + }), + TargetRef::Chain(links) => { // A chain in expression position: fold into chain steps - // from a leading reference. - let span = chain.span(); - let TargetRef::Chain(links) = chain else { - unreachable!() - }; + // from a leading reference. The fold leans one node per + // link, so the links are charged like any other chain. + let span = links.first().unwrap().span.join(links.last().unwrap().span); + self.charge_chain(links.len() as u32 - 1)?; let mut iter = links.into_iter(); let first = iter.next().unwrap(); let mut expr = Expr { @@ -4941,9 +5471,9 @@ impl<'s> Parser<'s> { span: s, }; } - Expr { span, ..expr } + Some(Expr { span, ..expr }) } - }); + }; } self.error_here(format!( @@ -5029,7 +5559,7 @@ impl<'s> Parser<'s> { if self.at(TokenKind::RParen) || self.at(TokenKind::RBracket) { break; } - items.push(self.parse_expr()?); + items.push(self.branch(Self::parse_expr)?); } let span = items.first().unwrap().span.join(items.last().unwrap().span); Some(Expr { @@ -5046,7 +5576,7 @@ impl<'s> Parser<'s> { return Some(args); } loop { - let value = self.parse_expr()?; + let value = self.branch(Self::parse_expr)?; if self.eat(TokenKind::Eq) { // Named argument: the "value" we parsed is the parameter name. let name = match value.kind { @@ -5059,7 +5589,7 @@ impl<'s> Parser<'s> { None } }; - let actual = self.parse_expr()?; + let actual = self.branch(Self::parse_expr)?; args.push(Arg { name, value: actual, diff --git a/crates/sysmlv2-syntax/src/print.rs b/crates/sysmlv2-syntax/src/print.rs index 698f511..a98cb88 100644 --- a/crates/sysmlv2-syntax/src/print.rs +++ b/crates/sysmlv2-syntax/src/print.rs @@ -16,11 +16,9 @@ //! * idempotency — `format(format(x)) == format(x)`. use crate::ast::*; -use crate::diag::Diagnostic; -use crate::lexer::tokenize; -use crate::parser::{parse_expression, parse_kerml_source, parse_source}; +use crate::diag::Diagnostics; +use crate::parser::parse_expression; use crate::span::{LineIndex, Span}; -use crate::token::TokenKind; /// Indentation style for printed text. The canonical style (and the /// default everywhere) is four spaces; hosts whose files are @@ -72,11 +70,13 @@ pub const FORMAT_CHAIN_MIN: u8 = 3; /// Print an AST as canonical textual notation (no source layout available: /// notes are gone — they are trivia — and members are single-spaced). +#[must_use] pub fn print_source(unit: &SourceUnit) -> String { print_source_with(unit, Indent::default()) } /// [`print_source`] with an explicit indentation style. +#[must_use] pub fn print_source_with(unit: &SourceUnit, indent: Indent) -> String { print_source_opts( unit, @@ -88,6 +88,7 @@ pub fn print_source_with(unit: &SourceUnit, indent: Indent) -> String { } /// [`print_source`] with explicit [`PrintOptions`]. +#[must_use] pub fn print_source_opts(unit: &SourceUnit, opts: PrintOptions) -> String { let mut p = Printer::new_opts(unit.dialect, None, opts); p.print_unit(unit); @@ -111,13 +112,13 @@ pub fn format_expression( dialect: Dialect, indent: Indent, width: usize, -) -> Result> { +) -> Result { let parse = parse_expression(src); if !parse.diagnostics.is_empty() { - return Err(parse.diagnostics); + return Err(parse.diagnostics.into()); } let Some(e) = parse.expr else { - return Err(Vec::new()); + return Err(Diagnostics::default()); }; let mut p = Printer::new_opts( dialect, @@ -138,6 +139,7 @@ pub fn format_expression( /// Print one expression as canonical textual notation — diagram labels, /// diagnostics. Bodied expressions may span lines; callers that need a /// single line collapse the whitespace themselves. +#[must_use] pub fn print_expr_source(e: &Expr, dialect: Dialect) -> String { let mut p = Printer::new(dialect, None); p.print_expr(e, 0); @@ -151,7 +153,7 @@ pub fn print_expr_source(e: &Expr, dialect: Dialect) -> String { /// Format source text: parse (with the dialect's grammar), then re-print /// preserving notes and single blank lines. Fails if the source has parse /// diagnostics — a formatter must not guess at broken input. -pub fn format_source(src: &str, dialect: Dialect) -> Result> { +pub fn format_source(src: &str, dialect: Dialect) -> Result { format_source_with(src, dialect, Indent::default()) } @@ -160,7 +162,7 @@ pub fn format_source_with( src: &str, dialect: Dialect, indent: Indent, -) -> Result> { +) -> Result { // The formatter (unlike the canonical serializer) breaks long // logical chains one condition per line by default. format_source_opts( @@ -181,15 +183,12 @@ pub fn format_source_opts( src: &str, dialect: Dialect, opts: PrintOptions, -) -> Result> { - let parse = match dialect { - Dialect::Sysml => parse_source(src), - Dialect::Kerml => parse_kerml_source(src), - }; +) -> Result { + let (parse, notes) = crate::parser::parse_with_notes(src, dialect); if !parse.diagnostics.is_empty() { - return Err(parse.diagnostics); + return Err(parse.diagnostics.into()); } - let layout = Layout::new(src); + let layout = Layout::with_notes(src, notes); let mut p = Printer::new_opts(dialect, Some(layout), opts); p.print_unit(&parse.unit); Ok(p.finish()) @@ -203,13 +202,9 @@ struct Layout { } impl Layout { - fn new(src: &str) -> Self { - let (tokens, _) = tokenize(src); - let notes = tokens - .iter() - .filter(|t| matches!(t.kind, TokenKind::LineNote | TokenKind::BlockNote)) - .map(|t| (t.span, t.text(src).trim_end().to_string())) - .collect(); + /// The notes come from the parse: they are the trivia the parser has + /// already seen, so the formatter never lexes the file a second time. + fn with_notes(src: &str, notes: Vec<(Span, String)>) -> Self { Layout { lines: LineIndex::new(src), notes, @@ -569,8 +564,12 @@ impl Printer { /// (`doc`/`comment`); `rep` bodies emit raw into interchange, so /// reflowing them would not invert — they stay verbatim always. fn print_comment_body(&mut self, body: &str, reflow: bool) { - self.trim_trailing_space(); - if !self.out.ends_with('\n') && !self.out.ends_with(char::is_whitespace) { + // Only indentation so far on this line (an anonymous `/* … */` + // member): keep it. Trimming here used to eat the pushed indent + // and flush such comments to column 0. + let line_start = self.out.rfind('\n').map_or(0, |i| i + 1); + if !self.out[line_start..].trim().is_empty() { + self.trim_trailing_space(); // `comment ` etc. already emitted: keep the body on the line. self.w(" "); } @@ -621,8 +620,13 @@ impl Printer { self.out.push('\n'); } + /// Drop the spaces a member left at the end of the line — but never + /// the indentation it opened the line with, so a member that spells + /// little or nothing still sits where it belongs. fn trim_trailing_space(&mut self) { - while self.out.ends_with(' ') { + let line = self.out.rfind('\n').map_or(0, |i| i + 1); + let floor = self.out.len() - self.out[line..].trim_start_matches(' ').len(); + while self.out.len() > floor && self.out.ends_with(' ') { self.out.pop(); } } @@ -1002,7 +1006,7 @@ impl Printer { self.w(" requirement "); self.print_feature_declaration(&u.declaration); } - self.print_value(&u.value); + self.print_value(u.value.as_deref()); if let Some(by) = by { self.w(" by "); self.print_target(by); @@ -1023,7 +1027,7 @@ impl Printer { self.w("constraint "); self.print_feature_declaration(&u.declaration); } - self.print_value(&u.value); + self.print_value(u.value.as_deref()); self.trim_trailing_space(); self.print_body(&u.body, span); } @@ -1192,9 +1196,9 @@ impl Printer { } else { ("allocation", "allocate") }; - let bare = !Self::decl_present(&u.declaration) - && u.value.is_none() - && matches!(u.detail, UsageDetail::Connector { .. }); + let ends = Self::connector_ends(&u.detail); + let clause = Self::clause_spells(ends); + let bare = !Self::decl_present(&u.declaration) && u.value.is_none() && clause; if bare { self.w(connect_kw); self.w(" "); @@ -1203,8 +1207,8 @@ impl Printer { self.w(kw); self.w(" "); self.print_feature_declaration(&u.declaration); - self.print_value(&u.value); - if matches!(u.detail, UsageDetail::Connector { .. }) { + self.print_value(u.value.as_deref()); + if clause { self.w(" "); self.w(connect_kw); self.w(" "); @@ -1212,50 +1216,44 @@ impl Printer { } } self.trim_trailing_space(); - self.print_body(&u.body, span); + self.print_connector_body(ends, &u.body, span); } UsageKind::Interface => { + let ends = Self::connector_ends(&u.detail); self.w("interface "); self.print_feature_declaration(&u.declaration); - self.print_value(&u.value); - if matches!(u.detail, UsageDetail::Connector { .. }) { + self.print_value(u.value.as_deref()); + if Self::clause_spells(ends) { if Self::decl_present(&u.declaration) { self.w(" connect "); } self.print_connector_part(&u.detail); } self.trim_trailing_space(); - self.print_body(&u.body, span); + self.print_connector_body(ends, &u.body, span); } UsageKind::Connector => { + let ends = Self::connector_ends(&u.detail); self.w("connector "); self.print_feature_declaration(&u.declaration); - self.print_value(&u.value); - if let UsageDetail::Connector { ends } = &u.detail { - if ends.len() == 2 { - self.w(" from "); - self.print_connector_end(&ends[0]); - self.w(" to "); - self.print_connector_end(&ends[1]); - } else { - self.w(" ("); - for (i, e) in ends.iter().enumerate() { - if i > 0 { - self.w(", "); - } - self.print_connector_end(e); - } - self.w(")"); - } + self.print_value(u.value.as_deref()); + if ends.len() == 2 { + self.w(" from "); + self.print_connector_end(&ends[0]); + self.w(" to "); + self.print_connector_end(&ends[1]); + } else if Self::clause_spells(ends) { + self.w(" "); + self.print_connector_ends(ends); } self.trim_trailing_space(); - self.print_body(&u.body, span); + self.print_connector_body(ends, &u.body, span); } UsageKind::Flow | UsageKind::Message | UsageKind::SuccessionFlow => { self.w(self.usage_keyword(u.kind).unwrap()); self.w(" "); self.print_feature_declaration(&u.declaration); - self.print_value(&u.value); + self.print_value(u.value.as_deref()); if let UsageDetail::Flow { payload, source, @@ -1356,7 +1354,7 @@ impl Printer { self.w(" "); self.print_feature_declaration(&u.declaration); } - self.print_value(&u.value); + self.print_value(u.value.as_deref()); if u.is_parallel { self.w(" parallel"); } @@ -1402,14 +1400,14 @@ impl Printer { } self.print_feature_declaration(&u.declaration); } - self.print_value(&u.value); + self.print_value(u.value.as_deref()); self.trim_trailing_space(); self.print_body(&u.body, span); } fn print_declaration_value_body(&mut self, u: &Usage, span: Span) { self.print_feature_declaration(&u.declaration); - self.print_value(&u.value); + self.print_value(u.value.as_deref()); if u.is_parallel { self.w(" parallel"); } @@ -1427,9 +1425,7 @@ impl Printer { let has_decl = Self::decl_present(&u.declaration); // A source end with no target and no name is textually unspelled // (the `then [mult]? x;` target-succession shorthand). - let unspelled_source = |src: &ConnectorEnd| { - src.name.is_none() && matches!(&src.target, TargetRef::Chain(links) if links.is_empty()) - }; + let unspelled_source = |src: &ConnectorEnd| src.name.is_none() && src.target.is_unspelled(); match source { Some(src) if !unspelled_source(src) => { if has_decl || self.kerml() { @@ -1459,33 +1455,146 @@ impl Printer { fn print_binding(&mut self, u: &Usage, span: Span) { let has_decl = Self::decl_present(&u.declaration); - if self.kerml() { - self.w("binding "); - if has_decl { - self.print_feature_declaration(&u.declaration); - } - if let UsageDetail::Binding { ends } = &u.detail { + // A binding binds exactly two ends, and that is what the parser + // builds; a usage assembled from a partial interchange document can + // carry another arity, held as a plain connector detail. Print the + // ends that are there instead of assuming the pair. + let ends = Self::connector_ends(&u.detail); + // The notation spells a *binding's* ends as one `a = b` pair and + // has no form for any other count. Printing what is there behind + // the binding keyword regardless would emit text that is not a + // binding: one end reads as a missing right side, three as a + // chain of two whose third end is quietly lost. + let pair = ends.len() == 2; + // Ends the head could not spell, carried into the body instead. + let mut ends_in_body: &[ConnectorEnd] = &[]; + if pair { + if self.kerml() { + // KerML spells the pair behind an optional `of`, and the + // declaration stands without it. + self.w("binding "); if has_decl { + self.print_feature_declaration(&u.declaration); self.w("of "); } - self.print_connector_end(&ends[0]); - self.w(" = "); - self.print_connector_end(&ends[1]); + } else { + if has_decl { + self.w("binding "); + self.print_feature_declaration(&u.declaration); + } + self.w("bind "); } } else { + // Neither dialect spells a binding that is not a pair. SysML + // requires the `bind` clause after its keyword (SysML.xtext + // `BindingConnectorAsUsage`), so a head without the clause + // does not parse at all; KerML does take the keyword alone, + // but a binding connector that does not bind two features + // draws a finding, so the text would parse and not check. + // + // What the member can keep is everything but the binding. Its + // declaration prints as a usage without the keyword, and every + // end prints as an `end ::> …;` body member — the form the + // notation gives a connector end that is written out rather + // than listed in a clause. That spelling parses, draws no + // finding, and re-lifts each end as an end membership at any + // count. What is lost is that the connector bound its ends + // rather than merely relating them. + // + // Another connector keyword would keep more of that, but none + // either dialect offers is both unconstrained and honest: the + // connection form demands an association structure as its + // type and refuses an ordinary one, and it spells one end not + // at all. + // + // KerML names a metaclass on every member, so the usage that + // keeps the declaration is spelled `feature` — with or without + // one, since a member whose whole text is a body does not + // parse there either. SysML takes the declaration as a head on + // its own and spells the keyword-less usage `ref` where there + // is nothing to declare. + // + // Such a usage only comes from a payload, where building it + // already records that its end count is not two. + if self.kerml() { + self.w("feature "); + } if has_decl { - self.w("binding "); self.print_feature_declaration(&u.declaration); + } else if !self.kerml() { + self.w("ref "); } - if let UsageDetail::Binding { ends } = &u.detail { - self.w("bind "); - self.print_connector_end(&ends[0]); - self.w(" = "); - self.print_connector_end(&ends[1]); + ends_in_body = ends; + } + if pair { + for (i, end) in ends.iter().enumerate() { + if i > 0 { + self.w(" = "); + } + self.print_connector_end(end); } } self.trim_trailing_space(); - self.print_body(&u.body, span); + if ends_in_body.is_empty() { + self.print_body(&u.body, span); + } else { + self.print_end_member_body(ends_in_body, &u.body, span); + } + } + + /// A body that leads with the connector's ends, each spelled as an + /// `end ::> …;` member, ahead of whatever members the usage carried. + /// The notation spells an end this way wherever a clause cannot hold + /// it, and the lift reads it back as an end membership. + fn print_end_member_body( + &mut self, + ends: &[ConnectorEnd], + body: &Option>, + span: Span, + ) { + self.w(" {\n"); + self.depth += 1; + for end in ends { + self.push_indent(); + self.w("end "); + if end.name.is_none() && end.target.is_unspelled() && end.multiplicity.is_none() { + // Nothing at all follows the prefix. SysML reads a member + // that is only its prefix; KerML wants an element after + // one, and `end;` stops it. Naming the metaclass the end + // has anyway gives both a member to read, and neither + // spells anything the bare form did not. + self.w("feature "); + } + if let Some(name) = &end.name { + self.print_name(name); + self.w(" "); + } + // An end that references no feature spells no subsetting. + if !end.target.is_unspelled() { + self.w("::> "); + self.print_target(&end.target); + } + if let Some(mult) = &end.multiplicity { + // Canonical position for a feature's multiplicity is after + // what it specializes; ahead of that, a `[` would open the + // cross feature an end may declare instead. + self.trim_trailing_space(); + self.print_multiplicity(mult); + } + self.trim_trailing_space(); + self.line_end(); + } + for m in body.iter().flatten() { + self.print_member(m); + } + self.flush_notes(span.end); + self.depth -= 1; + self.push_indent(); + self.w("}"); + if let Some(layout) = &self.layout { + self.prev_line = Some(layout.line(span.end.saturating_sub(1))); + } + self.out.push('\n'); } fn print_transition(&mut self, u: &Usage, span: Span) { @@ -1600,7 +1709,7 @@ impl Printer { self.w("action "); self.print_feature_declaration(&u.declaration); } - self.print_value(&u.value); + self.print_value(u.value.as_deref()); self.trim_trailing_space(); if terminated { self.print_body(&u.body, span); @@ -1624,6 +1733,37 @@ impl Printer { self.print_target(&end.target); } + /// The ends a usage's detail carries, if it carries any. + fn connector_ends(detail: &UsageDetail) -> &[ConnectorEnd] { + match detail { + UsageDetail::Binding { ends } | UsageDetail::Connector { ends } => ends, + _ => &[], + } + } + + /// Whether the notation's end clause spells this many ends. It reads + /// two or more — `from a to b`, `(a, b, c)` — so a connector that an + /// assembled tree gave fewer has no clause, and its ends go into the + /// body instead. + fn clause_spells(ends: &[ConnectorEnd]) -> bool { + ends.len() >= 2 + } + + /// A connector's body: its own members, behind the ends where no + /// clause could spell them. + fn print_connector_body( + &mut self, + ends: &[ConnectorEnd], + body: &Option>, + span: Span, + ) { + if ends.is_empty() || Self::clause_spells(ends) { + self.print_body(body, span); + } else { + self.print_end_member_body(ends, body, span); + } + } + fn print_connector_part(&mut self, detail: &UsageDetail) { let UsageDetail::Connector { ends } = detail else { return; @@ -1633,15 +1773,21 @@ impl Printer { self.w(" to "); self.print_connector_end(&ends[1]); } else { - self.w("("); - for (i, e) in ends.iter().enumerate() { - if i > 0 { - self.w(", "); - } - self.print_connector_end(e); + self.print_connector_ends(ends); + } + } + + /// The parenthesized end list, which spells any number of ends from + /// two up: `(a, b, c)`. + fn print_connector_ends(&mut self, ends: &[ConnectorEnd]) { + self.w("("); + for (i, e) in ends.iter().enumerate() { + if i > 0 { + self.w(", "); } - self.w(")"); + self.print_connector_end(e); } + self.w(")"); } fn print_payload(&mut self, p: &PayloadPart) { @@ -1800,7 +1946,7 @@ impl Printer { } } - fn print_value(&mut self, value: &Option) { + fn print_value(&mut self, value: Option<&FeatureValue>) { if let Some(v) = value { self.trim_trailing_space(); self.print_feature_value(v); @@ -1938,18 +2084,21 @@ impl Printer { } _ => return false, }; - fn flatten<'a>(e: &'a Expr, op: BinaryOp, out: &mut Vec<&'a Expr>) { - match &e.kind { - ExprKind::Binary { op: o, lhs, rhs } if *o == op => { - flatten(lhs, op, out); - out.push(rhs); - } - _ => out.push(e), + // Walk the left spine iteratively: a chain of a few hundred operands + // is ordinary in a generated constraint, and it is the same shape + // that would drive this apart one stack frame per operand. + let mut leaves: Vec<&Expr> = Vec::new(); + let mut cur = e; + while let ExprKind::Binary { op: o, lhs, rhs } = &cur.kind { + if *o != op { + break; } + leaves.push(rhs); + cur = lhs; } - let mut leaves: Vec<&Expr> = Vec::new(); - flatten(e, op, &mut leaves); - if (leaves.len() as u8) < min { + leaves.push(cur); + leaves.reverse(); + if leaves.len() < usize::from(min) { return false; } let (text, prec, _) = binary_op_info(op); @@ -2376,6 +2525,7 @@ fn expr_prec(e: &Expr) -> u8 { /// indented text nests with a tab, anything else with the canonical /// four spaces. A depth-0 owner has no indentation of its own to /// read, so the unit text decides. +#[must_use] pub fn indent_unit(indent: &str, src: &str) -> &'static str { let tabs = if indent.is_empty() { src.lines().any(|l| l.starts_with('\t')) @@ -2397,6 +2547,7 @@ pub fn indent_unit(indent: &str, src: &str) -> &'static str { /// This is both how the edit planner spells inserted members and how /// integrity checks reproduce that spelling — keep the two in one /// place. +#[must_use] pub fn reindent_member_text(text: &str, base: &str, unit: &str) -> String { let lines: Vec<&str> = text.split('\n').collect(); if lines.len() <= 1 { diff --git a/crates/sysmlv2-syntax/src/span.rs b/crates/sysmlv2-syntax/src/span.rs index b0dedda..a5f1be7 100644 --- a/crates/sysmlv2-syntax/src/span.rs +++ b/crates/sysmlv2-syntax/src/span.rs @@ -2,28 +2,42 @@ use std::fmt; +/// A byte offset as a span coordinate. +/// +/// Span coordinates are 32-bit, so a source text longer than `u32::MAX` +/// bytes cannot be addressed by one. Clamping keeps the spans of a text +/// that long ordered and in range instead of wrapping them around. +pub(crate) fn clamp_offset(byte: usize) -> u32 { + u32::try_from(byte).unwrap_or(u32::MAX) +} + /// A half-open byte range `[start, end)` into a source text. #[derive(Clone, Copy, PartialEq, Eq, Hash, Default)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct Span { pub start: u32, pub end: u32, } impl Span { + #[must_use] pub fn new(start: u32, end: u32) -> Self { debug_assert!(start <= end); Span { start, end } } + #[must_use] pub fn len(&self) -> u32 { self.end - self.start } + #[must_use] pub fn is_empty(&self) -> bool { self.start == self.end } /// The smallest span covering both `self` and `other`. + #[must_use] pub fn join(self, other: Span) -> Span { Span { start: self.start.min(other.start), @@ -31,6 +45,7 @@ impl Span { } } + #[must_use] pub fn slice<'a>(&self, text: &'a str) -> &'a str { &text[self.start as usize..self.end as usize] } @@ -44,6 +59,7 @@ impl fmt::Debug for Span { /// 1-based line and column position, computed on demand from a span offset. #[derive(Clone, Copy, PartialEq, Eq, Debug)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct LineCol { pub line: u32, pub col: u32, @@ -51,29 +67,32 @@ pub struct LineCol { /// Maps byte offsets to line/column positions for one source text. #[derive(Clone)] +#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))] pub struct LineIndex { /// Byte offset of the start of each line. line_starts: Vec, } impl LineIndex { + #[must_use] pub fn new(text: &str) -> Self { let mut line_starts = vec![0u32]; for (i, b) in text.bytes().enumerate() { if b == b'\n' { - line_starts.push(i as u32 + 1); + line_starts.push(clamp_offset(i).saturating_add(1)); } } LineIndex { line_starts } } + #[must_use] pub fn line_col(&self, offset: u32) -> LineCol { let line = match self.line_starts.binary_search(&offset) { Ok(l) => l, Err(l) => l - 1, }; LineCol { - line: line as u32 + 1, + line: clamp_offset(line).saturating_add(1), col: offset - self.line_starts[line] + 1, } } diff --git a/crates/sysmlv2-syntax/src/token.rs b/crates/sysmlv2-syntax/src/token.rs index 4601fc6..cfaf9b0 100644 --- a/crates/sysmlv2-syntax/src/token.rs +++ b/crates/sysmlv2-syntax/src/token.rs @@ -86,6 +86,7 @@ pub enum TokenKind { impl TokenKind { /// Trivia tokens are skipped by the parser (Xtext "hidden" terminals). + #[must_use] pub fn is_trivia(self) -> bool { matches!( self, @@ -101,16 +102,19 @@ pub struct Token { } impl Token { + #[must_use] pub fn new(kind: TokenKind, span: Span) -> Self { Token { kind, span } } /// The source text of this token. + #[must_use] pub fn text<'a>(&self, src: &'a str) -> &'a str { self.span.slice(src) } /// True if this token is the word `kw` (used for contextual keywords). + #[must_use] pub fn is_kw(&self, src: &str, kw: &str) -> bool { self.kind == TokenKind::Ident && self.text(src) == kw } diff --git a/crates/sysmlv2-transform/Cargo.toml b/crates/sysmlv2-transform/Cargo.toml index ada30e5..1d47d40 100644 --- a/crates/sysmlv2-transform/Cargo.toml +++ b/crates/sysmlv2-transform/Cargo.toml @@ -12,9 +12,9 @@ repository.workspace = true include = ["src/**", "Cargo.toml"] [dependencies] -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } -sysmlv2-cbor = { path = "../sysmlv2-cbor", version = "0.6.0" } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } +sysmlv2-cbor = { path = "../sysmlv2-cbor", version = "0.9.0" } uuid.workspace = true serde_json.workspace = true diff --git a/crates/sysmlv2-transform/examples/importbench.rs b/crates/sysmlv2-transform/examples/importbench.rs new file mode 100644 index 0000000..389077f --- /dev/null +++ b/crates/sysmlv2-transform/examples/importbench.rs @@ -0,0 +1,62 @@ +//! Reproducible checking-stage benchmark (release builds only). +//! cargo run --release -p sysmlv2-transform --example importbench -- MODEL_DIR [cold] +use serde_json::json; +use std::{fs, time::Instant}; +use sysmlv2_model::{ambient, check, json::ResolvedModel, model::Model}; + +fn main() { + let args: Vec<_> = std::env::args().collect(); + let path = std::path::Path::new(args.get(1).expect("MODEL_DIR required")); + let cold = args.get(2).is_some_and(|s| s == "cold"); + let library = sysmlv2_testkit::library_dir(); + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + ambient::add_to(&mut base); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let mut paths = Vec::new(); + sysmlv2_testkit::collect_files(path, &mut paths); + paths.sort(); + assert!(!paths.is_empty()); + let sources: Vec<_> = paths + .iter() + .map(|p| (p.display().to_string(), fs::read_to_string(p).unwrap())) + .collect(); + let mut rows = Vec::new(); + for _ in 0..3 { + let total = Instant::now(); + let mut model = Model::new(); + model.load_library_dir(&library).unwrap(); + ambient::add_to(&mut model); + if !cold { + model.set_library_cache(cache.clone()); + } + let offset = model.unit_count(); + let texts: Vec<_> = sources + .iter() + .enumerate() + .map(|(i, (name, text))| { + model.add_source(name, text); + (offset + i, text.clone()) + }) + .collect(); + let start = Instant::now(); + let mut resolved = ResolvedModel::build(&model); + let resolution = start.elapsed().as_secs_f64() * 1000.; + let start = Instant::now(); + let references = check::validate_model_with(&mut resolved, &model); + let referential = start.elapsed().as_secs_f64() * 1000.; + let start = Instant::now(); + let semantics = check::validate_semantics_with(&mut resolved, &model); + let semantic = start.elapsed().as_secs_f64() * 1000.; + let start = Instant::now(); + let unused = sysmlv2_transform::unused_private_imports_with(&mut resolved, &texts); + let imports = start.elapsed().as_secs_f64() * 1000.; + rows.push(json!({"resolution_ms": resolution, "referential_ms": referential, + "semantic_ms": semantic, "unused_imports_ms": imports, "total_ms": total.elapsed().as_secs_f64()*1000., + "referential_count": references.len(), "semantic_count": semantics.len(), + "findings": unused.into_iter().map(|(u, s)| json!({"file": sources[u-offset].0, "start": s.start, "end": s.end})).collect::>() })); + } + println!("{}", serde_json::to_string_pretty(&json!({"cold": cold, "files": sources.len(), "bytes": sources.iter().map(|(_, s)|s.len()).sum::(), "runs": rows})).unwrap()); +} diff --git a/crates/sysmlv2-transform/examples/preparedbench.rs b/crates/sysmlv2-transform/examples/preparedbench.rs new file mode 100644 index 0000000..c017aa2 --- /dev/null +++ b/crates/sysmlv2-transform/examples/preparedbench.rs @@ -0,0 +1,84 @@ +//! Stage timings for prepared-library startup and validation. +//! Append `reuse` to retain the library, `syntax` to request all library ASTs. +use std::{sync::Arc, time::Instant}; +use sysmlv2_model::{check, json::ResolvedModel, model::Model, prepared::PreparedLibrary}; +fn main() { + let path = std::env::args().nth(1).expect("MODEL_DIR"); + let mut files = Vec::new(); + sysmlv2_testkit::collect_files(std::path::Path::new(&path), &mut files); + files.sort(); + let sources: Vec<_> = files + .iter() + .map(|p| (p.display().to_string(), std::fs::read_to_string(p).unwrap())) + .collect(); + let mut base = Model::new(); + let start = Instant::now(); + base.load_library_dir(&sysmlv2_testkit::library_dir()) + .unwrap(); + let parse = start.elapsed(); + let start = Instant::now(); + let prepared = base.prepare_library().unwrap(); + let prepare = start.elapsed(); + let start = Instant::now(); + let bytes = prepared.to_bytes(1).unwrap(); + let encode = start.elapsed(); + eprintln!( + "library parse {:?}; prepare {:?}; encode {:?}; bytes {}", + parse, + prepare, + encode, + bytes.len() + ); + drop(base); + drop(prepared); + let reuse = std::env::args().skip(2).any(|s| s == "reuse"); + let syntax = std::env::args().skip(2).any(|s| s == "syntax"); + let retained = reuse.then(|| Arc::new(PreparedLibrary::from_bytes(&bytes, 1).unwrap())); + let mut rows = Vec::new(); + for _ in 0..3 { + let start = Instant::now(); + let prepared = retained + .clone() + .unwrap_or_else(|| Arc::new(PreparedLibrary::from_bytes(&bytes, 1).unwrap())); + let decode = start.elapsed(); + let mut model = Model::new(); + let start = Instant::now(); + prepared.clone().install(&mut model).unwrap(); + let install = start.elapsed(); + let start = Instant::now(); + if syntax { + std::hint::black_box(model.units()); + } + let syntax_time = start.elapsed(); + let start = Instant::now(); + let offset = model.unit_count(); + let texts: Vec<_> = sources + .iter() + .enumerate() + .map(|(i, (n, s))| { + model.add_source(n, s); + (offset + i, s.clone()) + }) + .collect(); + let user_parse = start.elapsed(); + let start = Instant::now(); + let mut r = ResolvedModel::build(&model); + let build = start.elapsed(); + let start = Instant::now(); + let refs = check::validate_model_with(&mut r, &model); + let referential = start.elapsed(); + let start = Instant::now(); + let semantics = check::validate_semantics_with(&mut r, &model); + let semantic = start.elapsed(); + let start = Instant::now(); + let unused = sysmlv2_transform::unused_private_imports_with(&mut r, &texts); + let imports = start.elapsed(); + let start = Instant::now(); + drop(r); + drop(model); + drop(prepared); + let destruction = start.elapsed(); + rows.push(serde_json::json!({"retained_library":reuse,"requested_syntax":syntax,"syntax_ms":syntax_time.as_secs_f64()*1000.,"decode_ms":decode.as_secs_f64()*1000.,"install_ms":install.as_secs_f64()*1000.,"user_parse_ms":user_parse.as_secs_f64()*1000.,"build_ms":build.as_secs_f64()*1000.,"referential_ms":referential.as_secs_f64()*1000.,"semantic_ms":semantic.as_secs_f64()*1000.,"imports_ms":imports.as_secs_f64()*1000.,"drop_ms":destruction.as_secs_f64()*1000.,"refs":refs.len(),"semantics":semantics.len(),"unused":unused.len()})); + } + println!("{}", serde_json::to_string_pretty(&rows).unwrap()); +} diff --git a/crates/sysmlv2-transform/src/eligibility.rs b/crates/sysmlv2-transform/src/eligibility.rs index bd45d46..f187861 100644 --- a/crates/sysmlv2-transform/src/eligibility.rs +++ b/crates/sysmlv2-transform/src/eligibility.rs @@ -65,6 +65,7 @@ const NOT_YET_GATED: &str = /// The matrix row for a usage kind, `None` when the kind has no textual /// ` def` counterpart at all (bindings, successions, control /// nodes, KerML feature kinds, …). +#[must_use] pub fn kind_rule(kind: UsageKind) -> Option { use UsageKind::*; Some(match kind { @@ -107,6 +108,7 @@ pub fn kind_rule(kind: UsageKind) -> Option { /// The matrix row keyed from the definition side (inline direction), by /// abstract-syntax metaclass. Same rows as [`kind_rule`]. +#[must_use] pub fn definition_kind_rule(metaclass: &str) -> Option { use UsageKind::*; let kind = match metaclass { @@ -376,6 +378,7 @@ pub struct InlineEligibility { /// empty = legal. This is the mechanism that keeps the matrix honest — /// `probe_body_in_definition_context("view", "expose P::*;")` fails /// while the same body is legal on a view *usage*. +#[must_use] pub fn probe_body_in_definition_context(keyword: &str, interior: &str) -> Vec { let probe = format!("{keyword} def __X {{{interior}}}"); let parse = parse_source(&probe); @@ -488,7 +491,7 @@ fn reparse_definition(text: &str) -> Result { } impl Session { - /// M29a0 extract gate: may `usage` be extracted into a definition, + /// Extract gate: may `usage` be extracted into a definition, /// and if so where is the moved region? Refusals are named header / /// kind / context policies — never a late failure downstream. pub fn extract_definition_eligibility( @@ -506,7 +509,7 @@ impl Session { return Err(ExtractRefusal::NotAUserElement); } let local = unit - self.unit_offset; - if self.sources[local].0.ends_with(".kerml") { + if crate::is_kerml_unit(&self.sources[local].0) { return Err(ExtractRefusal::UnsupportedDialect); } if !metaclass.ends_with("Usage") { @@ -598,11 +601,16 @@ impl Session { }) } - /// M29a0 inline gate: has `definition` exactly one direct, + /// The inline gate: has `definition` exactly one direct, /// non-conjugated typing usage, and does every other incoming /// reference classify as (a) internal to the body being moved or /// (b) reached through that usage? Class (c) — genuine outside /// references through the definition — refuses, naming each site. + /// + /// # Panics + /// + /// If the sole typing site is gone by the time the eligibility is + /// assembled, which the count check just above rules out. pub fn inline_definition_eligibility( &mut self, definition: ElementRef, @@ -617,12 +625,13 @@ impl Session { return Err(InlineRefusal::NotAUserElement); } let def_local = def_unit - self.unit_offset; - if self.sources[def_local].0.ends_with(".kerml") { + if crate::is_kerml_unit(&self.sources[def_local].0) { return Err(InlineRefusal::UnsupportedDialect); } - let rule = definition_kind_rule(&metaclass).ok_or(InlineRefusal::NotADefinition { - metaclass: metaclass.clone(), - })?; + let rule = + definition_kind_rule(&metaclass).ok_or_else(|| InlineRefusal::NotADefinition { + metaclass: metaclass.clone(), + })?; if !rule.enabled { return Err(InlineRefusal::UnsupportedKind { keyword: rule.keyword, @@ -818,13 +827,13 @@ impl Session { .resolved .owned_members(usage) .into_iter() - .filter_map(|m| self.resolved.element_effective_name(m)) + .filter_map(|m| self.resolved.element_lookup_name(m)) .collect(); let mut collisions: Vec = self .resolved .owned_members(definition) .into_iter() - .filter_map(|m| self.resolved.element_effective_name(m)) + .filter_map(|m| self.resolved.element_lookup_name(m)) .filter(|n| usage_names.contains(n)) .collect(); if !collisions.is_empty() { diff --git a/crates/sysmlv2-transform/src/lib.rs b/crates/sysmlv2-transform/src/lib.rs index 07effe2..4875ecb 100644 --- a/crates/sysmlv2-transform/src/lib.rs +++ b/crates/sysmlv2-transform/src/lib.rs @@ -18,7 +18,7 @@ pub mod eligibility; pub mod projection; -use std::collections::{HashMap, HashSet}; +use std::collections::{BTreeMap, HashMap, HashSet}; use std::fmt; use std::path::{Path, PathBuf}; @@ -27,7 +27,7 @@ pub use sysmlv2_model::model::Model as ModelHandle; use sysmlv2_model::libcache; use sysmlv2_model::model::Model; -use sysmlv2_syntax::ast::{Dialect, escape_name}; +use sysmlv2_syntax::ast::escape_name; use sysmlv2_syntax::diag::Diagnostic; pub use sysmlv2_syntax::diag::Severity; use sysmlv2_syntax::lexer::{tokenize, unescape}; @@ -52,16 +52,11 @@ fn decode_name(spelled: &str) -> String { /// Spell `name` as a source token: [`escape_name`] quoting for /// non-identifier characters, plus quotes for words reserved in *either* /// dialect (a rename batch can touch `.sysml` and `.kerml` units at -/// once, and a quoted spelling is legal everywhere). +/// once, and a quoted spelling is legal everywhere) — +/// [`sysmlv2_syntax::name::spell_name_in`] without a dialect. +#[must_use] pub fn spell_name(name: &str) -> String { - let escaped = escape_name(name); - if !escaped.starts_with('\'') - && (sysmlv2_syntax::parser::is_reserved(Dialect::Sysml, name) - || sysmlv2_syntax::parser::is_reserved(Dialect::Kerml, name)) - { - return format!("'{name}'"); - } - escaped + sysmlv2_syntax::name::spell_name_in(None, name) } /// Stable identity for one unresolved reference across a semantics-preserving @@ -160,9 +155,8 @@ fn validation_finding_key( diagnostic: &Diagnostic, map_qn: &dyn Fn(&str) -> String, ) -> ValidationFindingKey { - let elements: Vec = resolved.user_elements().collect(); - let source_anchor = elements - .into_iter() + let source_anchor = resolved + .user_elements() .filter_map(|e| { let (u, extent) = resolved.member_extent(e)?; (u == unit @@ -207,12 +201,27 @@ fn validation_finding_key( } } -fn syntax_validation(unit_name: &str, text: &str) -> Vec { - let parse = if unit_name.ends_with(".kerml") { +/// Whether a unit name spells the KerML dialect. The extension is read +/// without case, so a unit named `Model.KerML` is KerML like +/// `model.kerml` — the file systems these names come from do not +/// distinguish the two. +pub(crate) fn is_kerml_unit(name: &str) -> bool { + Path::new(name) + .extension() + .is_some_and(|e| e.eq_ignore_ascii_case("kerml")) +} + +/// Parse a unit's text in the dialect its name spells. +fn parse_unit_source(name: &str, text: &str) -> sysmlv2_syntax::parser::Parse { + if is_kerml_unit(name) { parse_kerml_source(text) } else { parse_source(text) - }; + } +} + +fn syntax_validation(unit_name: &str, text: &str) -> Vec { + let parse = parse_unit_source(unit_name, text); sysmlv2_syntax::check::validate(&parse.unit) } @@ -283,6 +292,7 @@ fn terminal_name_span(spelling: &str) -> Span { /// The definition name [`EditBuilder::extract_definition`] synthesizes /// when none is given — exposed so surfaces (the LSP action title, the /// CLI's dry-run output) can spell the name the engine will use. +#[must_use] pub fn synthesized_definition_name(usage_name: &str) -> String { upper_camel(usage_name) } @@ -307,8 +317,21 @@ fn upper_camel(name: &str) -> String { // Errors // --------------------------------------------------------------------------- -/// Failure opening (or rebuilding) a session. +/// The leading diagnostic's message, for the error messages that quote +/// one. The diagnostic list belongs to whoever built the error, so an +/// empty one reads as a missing detail instead of ending the message +/// in a fault. +fn first_message(diagnostics: &[Diagnostic]) -> &str { + diagnostics + .first() + .map_or("no diagnostic reported", |d| d.message.as_str()) +} + +/// Failure opening (or rebuilding) a session. Variants are added as +/// new ways to refuse a session appear, so a host matches with a +/// fallback arm. #[derive(Debug)] +#[non_exhaustive] pub enum SessionError { Io(std::io::Error), /// A unit does not parse; the session cannot be built. @@ -318,16 +341,30 @@ pub enum SessionError { }, /// A compact-form CBOR payload does not decode. Cbor(sysmlv2_cbor::Error), + /// The session holds explicit ids, which an id-elided encoding + /// would lose. + ExplicitIds, + /// A unit name is blank. Every unit is laid out under its name (the + /// binary payloads carry it), so a blank one is refused when the + /// session is built rather than when it is emitted. + InvalidUnitName(String), } impl fmt::Display for SessionError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self { + SessionError::ExplicitIds => write!( + f, + "the session holds explicit ids; an id-elided payload would lose them" + ), SessionError::Io(e) => write!(f, "{e}"), SessionError::Parse { unit, diagnostics } => { - write!(f, "{unit} does not parse: {}", diagnostics[0].message) + write!(f, "{unit} does not parse: {}", first_message(diagnostics)) } SessionError::Cbor(e) => write!(f, "invalid CBOR payload: {e}"), + SessionError::InvalidUnitName(n) => { + write!(f, "invalid unit name {n:?}: a unit name must not be blank") + } } } } @@ -338,9 +375,17 @@ impl From for SessionError { } } +impl From for SessionError { + fn from(e: sysmlv2_cbor::Error) -> Self { + SessionError::Cbor(e) + } +} + /// Failure planning or committing an edit batch. The session is left in -/// its pre-commit state in every case. +/// its pre-commit state in every case. Variants are added as new +/// refusals appear, so a host matches with a fallback arm. #[derive(Debug)] +#[non_exhaustive] pub enum TransformError { /// The element has no declaration site (anonymous or synthesized). NotDeclared(ElementRef), @@ -369,6 +414,8 @@ pub enum TransformError { UnknownUnit(String), /// `add_unit` with a name the session already holds. UnitExists(String), + /// A package cannot be split as asked; the reason names the member. + SplitIneligible { reason: String }, /// Two edits touch overlapping text. OverlappingEdits { unit: usize, at: Span }, /// Removing the element would strand references outside the removed @@ -397,10 +444,10 @@ pub enum TransformError { /// not admit definitions. `rebuild` only parses; relocation ops /// additionally hold the syntax checker's verdict constant. NewValidationFindings { findings: Vec }, - /// `extract_definition` on a usage the M29a0 eligibility policy + /// `extract_definition` on a usage the eligibility policy /// refuses (kind, header shape, dialect, body context, …). ExtractIneligible { reason: eligibility::ExtractRefusal }, - /// `inline_definition` on a definition the M29a0 eligibility policy + /// `inline_definition` on a definition the eligibility policy /// refuses (kind, header, usage count, provenance, collisions, …). InlineIneligible { reason: eligibility::InlineRefusal }, /// The requested definition name is already declared by a sibling @@ -427,6 +474,7 @@ impl fmt::Display for TransformError { TransformError::InvalidMember { text, message } => { write!(f, "member text `{text}` does not parse: {message}") } + TransformError::SplitIneligible { reason } => write!(f, "cannot split: {reason}"), TransformError::NoEditableValue(e) => { write!(f, "element {e:?} has no editable feature value") } @@ -465,7 +513,7 @@ impl fmt::Display for TransformError { write!( f, "edited {unit} does not parse: {}", - diagnostics[0].message + first_message(diagnostics) ) } TransformError::SemanticIdentity { broken } => write!( @@ -507,7 +555,18 @@ impl fmt::Display for TransformError { } } -impl std::error::Error for SessionError {} +impl std::error::Error for SessionError { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + match self { + SessionError::Io(e) => Some(e), + SessionError::Cbor(e) => Some(e), + SessionError::Parse { .. } + | SessionError::InvalidUnitName(_) + | SessionError::ExplicitIds => None, + } + } +} + impl std::error::Error for TransformError {} // --------------------------------------------------------------------------- @@ -529,6 +588,18 @@ pub struct Session { /// Non-fatal problems from lifting interchange JSON (unknown /// constructs, unresolvable references) — empty for text sessions. warnings: Vec, + /// Explicit ids: graph-derived id → (the id the loaded document + /// carried, the element's metaclass) for every element whose given + /// id is not its derivation. Re-applied after every rebuild, keyed by + /// the derived id, and pruned to the entries that still land on an + /// element of the recorded metaclass: an edit that restructures an + /// element's ownership path (rename, move, delete) retires that + /// subtree's entries, so a later element deriving the same key never + /// inherits a vanished element's identity. + explicit_ids: HashMap, + /// Whether the loaded document carried references the lift could only + /// spell as ids, so emissions must bind them. + binds_ids: bool, } /// Where a session's standard library comes from: a directory on disk @@ -538,6 +609,8 @@ pub struct Session { #[derive(Clone)] pub enum Library { Dir(PathBuf), + /// An immutable graph shared across session builds and edits. + Prepared(std::sync::Arc), Sources { units: std::sync::Arc>, /// A sealed snapshot (`LibraryCache::to_bytes`) recorded against @@ -550,12 +623,30 @@ pub enum Library { } impl Library { + /// Prepare ordered in-memory library sources once for repeated session builds. + /// The optional resolution snapshot has the same fallback behavior as + /// [`Self::sources_with_snapshot`]. Changed or appended sources require a new + /// library; sessions cloned from this value share only immutable library data. + pub fn prepared_sources( + units: Vec<(String, String)>, + snapshot: Option>, + ) -> Result { + let source = Library::Sources { + units: std::sync::Arc::new(units), + snapshot: snapshot.map(std::sync::Arc::new), + }; + let mut model = Model::new(); + load_library_into(&mut model, &source)?; + Ok(Library::Prepared(model.prepare_library()?)) + } + pub fn dir(path: impl Into) -> Library { Library::Dir(path.into()) } /// An in-memory library from `(unit name, text)` pairs. Unit names /// ending in `.kerml` parse as KerML. + #[must_use] pub fn sources(units: Vec<(String, String)>) -> Library { Library::Sources { units: std::sync::Arc::new(units), @@ -566,6 +657,7 @@ impl Library { /// [`Self::sources`] with a sealed resolution snapshot /// ([`sysmlv2_model::libcache::LibraryCache::to_bytes`]) recorded /// against the same units in the same order. + #[must_use] pub fn sources_with_snapshot(units: Vec<(String, String)>, snapshot: Vec) -> Library { Library::Sources { units: std::sync::Arc::new(units), @@ -574,13 +666,16 @@ impl Library { } } -/// Load a [`Library`] into `model`. For a directory, the sealed-snapshot -/// cache is wired exactly like the CLI (replay when present, record when -/// not) and the cache path to save a fresh recording to is returned; -/// in-memory sources have no disk cache. +/// Load a [`Library`] into `model`. Directories share the CLI's prepared +/// graph cache; a returned path is for saving a legacy resolution recording +/// when preparation is unavailable. In-memory sources have no disk cache. fn load_library_into(model: &mut Model, lib: &Library) -> Result, SessionError> { match lib { Library::Dir(dir) => load_library_with_cache(model, dir), + Library::Prepared(library) => { + library.clone().install(model)?; + Ok(None) + } Library::Sources { units, snapshot } => { for (name, src) in units.iter() { model.add_library_source(name.clone(), src); @@ -596,27 +691,43 @@ fn load_library_into(model: &mut Model, lib: &Library) -> Result } } -/// Load the standard library into `model` with the sealed-snapshot -/// cache wired exactly like the CLI: replay when present, record when -/// not. Returns the cache path to save a fresh recording to. +/// Use the same prepared-library loader as the CLI. Live models keep the shared +/// library alive across session edits; changing its content selects a new base. +/// +/// A cache the loader could not write is dropped here for the same reason the +/// recording's own `save` result is: a session's hosts (a language server, a +/// browser, an embedding process) have no stream this could be written to, and +/// the cache is an optimization the session never depends on. fn load_library_with_cache(model: &mut Model, dir: &Path) -> Result, SessionError> { - model.load_library_dir(dir)?; - // The ambient libraries load with every directory library (an - // in-memory bundle carries them itself — see gen_stdlib_bundle). - sysmlv2_model::ambient::add_to(model); - let mut cache_path = None; - if std::env::var_os("SYSMLV2_LIB_CACHE").is_none_or(|v| v != "off") { - if let Ok(key) = libcache::hash_library_dir(dir).map(sysmlv2_model::ambient::mix_key) { - if let Some(path) = libcache::default_cache_path(key) { - match libcache::LibraryCache::load(&path) { - Some(cache) => model.set_library_cache(cache), - None => model.record_library_cache(), - } - cache_path = Some(path); - } + Ok(sysmlv2_model::prepared::load_library_with_cache(model, dir)?.recording_path) +} + +/// The pipeline stage a check finding came from. A session refuses only +/// units with `Parse` findings; a host that degrades gracefully keys on +/// this rather than on severity alone. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum CheckStage { + /// The unit did not parse; the remaining stages did not run on it. + Parse, + /// Body-context legality (a member the grammar does not allow in its + /// surrounding body). + Context, + /// Reference resolution against the model and library. + Referential, + /// Semantic constraints on a resolved model. + Semantic, +} + +impl CheckStage { + #[must_use] + pub fn as_str(self) -> &'static str { + match self { + CheckStage::Parse => "parse", + CheckStage::Context => "context", + CheckStage::Referential => "referential", + CheckStage::Semantic => "semantic", } } - Ok(cache_path) } /// One finding from [`check_sources`]: the CLI `check` verdict shape with @@ -633,12 +744,539 @@ pub struct CheckFinding { pub col: u32, /// The diagnostic's byte span in the unit's text. pub span: Span, + /// The stage that produced the finding. + pub stage: CheckStage, } -/// Check in-memory sources the way `sysmlv2 check` does: per-unit parse +/// Text a lenient parse removed from a unit, or closers it appended — +/// see [`lenient_sources`]. Offsets are bytes and columns byte-based, as +/// in [`CheckFinding`]. +#[derive(Clone, Debug)] +pub struct DroppedText { + pub unit: String, + /// Byte span in the unit's original text (empty when text was + /// appended). + pub start: u32, + pub end: u32, + /// 1-based positions of the span's start and end in the original + /// text. + pub line: u32, + pub col: u32, + pub end_line: u32, + pub end_col: u32, + /// The removed text (empty when text was appended). + pub text: String, + /// Line breaks the removal took out of the text as it stood (so the + /// counts of a unit's records are disjoint even when a later removal + /// encloses an earlier one), and whether it took whole lines (the + /// indentation before the text and the line break after it): what + /// maps a line of the repaired text back to the original, records + /// taken in order of `start`. + pub lines_removed: u32, + pub whole_lines: bool, + /// Text appended at `start`: the closers of bodies left open at the + /// end of the unit (empty when text was removed). + pub inserted: String, + /// The parse message the repair answered. + pub message: String, +} + +/// A unit a lenient parse could not repair — see [`lenient_sources`]. +#[derive(Clone, Debug)] +pub struct UnrepairedUnit { + pub unit: String, + /// The first parse message still standing, at its 1-based position + /// in the repaired text. + pub message: String, + pub line: u32, + pub col: u32, +} + +/// What [`lenient_sources`] produced. +#[derive(Clone, Debug, Default)] +pub struct LenientSources { + /// Every unit in input order, repaired where it had to be. + pub sources: Vec<(String, String)>, + /// What the repairs removed or appended, in unit order. + pub dropped: Vec, + /// Units still failing to parse after the repair; their entry in + /// `sources` carries the partially repaired text. + pub unrepaired: Vec, +} + +/// Rounds of parse-and-cut per unit: each round answers every diagnostic +/// of one parse, so a unit needs several only when a cut uncovers new +/// errors. +const LENIENT_ROUNDS: usize = 64; + +/// The sources with every unit that fails to parse repaired so that a +/// session can be built over what parsed. Each round parses the unit and +/// answers every diagnostic at once. An error inside a member's +/// declaration removes that member; a zero-width error at a member's end +/// (the parser kept the member but it lacks its `;`) removes that member; +/// an error inside a body where the parser skipped a failed member +/// removes that member's text, recovered from the trivia-free tokens +/// between the end of the previous sibling (or the body's `{`) and the +/// `;` that ends it, the body it opens, or the `}` that closes the +/// enclosing body — the way the parser skips it; an error at the end of +/// the unit with bodies left open appends the missing closers. Text that +/// stands alone on its lines goes with its indentation and line break. +/// The unit is parsed again until it is clean; a unit that stays broken +/// is named in [`LenientSources::unrepaired`]. Every record is in the +/// original text's coordinates. The syntax tree is partial, never +/// absent, so a broken file is not a blank file. +#[must_use] +pub fn lenient_sources(sources: &[(String, String)]) -> LenientSources { + use sysmlv2_syntax::token::TokenKind; + let mut out = LenientSources::default(); + for (name, text) in sources { + let parse_unit = |t: &str| parse_unit_source(name, t); + let original = text.as_str(); + let orig_len = original.len() as u32; + let index = LineIndex::new(original); + let mut current = text.clone(); + // Removed spans in original coordinates: disjoint and sorted, so + // a position in the current text maps back by adding the length + // of every removal before it. Appended closers sit past the end. + let mut drops: Vec<(u32, u32)> = Vec::new(); + let to_original = |pos: u32, drops: &[(u32, u32)], exclusive_end: bool| -> u32 { + let mut p = pos; + for (s, e) in drops { + let before = if exclusive_end { *s < p } else { *s <= p }; + if before { + p += e - s; + } else { + break; + } + } + p.min(orig_len) + }; + let record_drop = |drops: &mut Vec<(u32, u32)>, mut s: u32, mut e: u32| { + // A removal enclosing or touching earlier ones absorbs them. + drops.retain(|(a, b)| { + let touches = *a <= e && *b >= s; + if touches { + s = s.min(*a); + e = e.max(*b); + } + !touches + }); + drops.push((s, e)); + drops.sort_unstable(); + }; + let mut remaining: Option = None; + for round in 0..=LENIENT_ROUNDS { + let parse = parse_unit(¤t); + let Some(first) = parse.diagnostics.first().cloned() else { + remaining = None; + break; + }; + if round == LENIENT_ROUNDS { + remaining = Some(first); + break; + } + let len = current.len() as u32; + let (mut tokens, _) = tokenize(¤t); + tokens.retain(|t| !t.kind.is_trivia() && t.kind != TokenKind::Eof); + // Plan this round's cuts against the current text: the + // recorded span, the widened cut, and the message. + let mut cuts: Vec<(Span, Span, String)> = Vec::new(); + let mut closers = 0usize; + let mut closer_message = String::new(); + for d in &parse.diagnostics { + let mut at = d.span.start.min(len); + if at >= len { + let depth = tokens.iter().fold(0i64, |n, t| match t.kind { + TokenKind::LBrace => n + 1, + TokenKind::RBrace => (n - 1).max(0), + _ => n, + }); + if depth > 0 { + if closers == 0 { + closer_message = d.message.clone(); + } + closers = closers.max(depth as usize); + continue; + } + if len == 0 { + continue; + } + at = len - 1; + } + let zero_width = d.span.end <= d.span.start; + let span = failed_extent(&parse.unit.members, &tokens, at, zero_width); + if span.end <= span.start { + continue; + } + cuts.push((span, widen_to_own_lines(¤t, span), d.message.clone())); + } + // Disjoint cuts: ones that overlap, touch, or sit on one line + // with only blanks between them become one record, widened + // again as a whole (three stray closers on one line go with + // their line). A cut that already took its line break is a + // record of its own. + cuts.sort_by_key(|(s, _, _)| (s.start, s.end)); + let bytes = current.as_bytes(); + cuts.dedup_by(|later, earlier| { + let end = earlier.1.end as usize; + let joins = later.1.start < earlier.1.end + || (end > 0 + && bytes[end - 1] != b'\n' + && bytes[end..later.1.start as usize] + .iter() + .all(|b| matches!(b, b' ' | b'\t'))); + if joins { + earlier.0 = Span::new( + earlier.0.start.min(later.0.start), + earlier.0.end.max(later.0.end), + ); + earlier.1 = Span::new( + earlier.1.start.min(later.1.start), + earlier.1.end.max(later.1.end), + ); + } + joins + }); + for cut in &mut cuts { + cut.1 = widen_to_own_lines(¤t, cut.1); + } + // Records in original coordinates, planned before any cut. A + // cut lying entirely in appended closers has nothing original + // to record and is applied silently. + let mut planned: Vec<(u32, u32, u32, u32, u32, String)> = Vec::new(); + for (span, cut, message) in &cuts { + let cs = to_original(cut.start, &drops, false); + if cs >= orig_len { + // Appended closers being cut again: the record that + // appended them gives the text back. + let text = ¤t[cut.start as usize..cut.end as usize]; + if let Some(rec) = out + .dropped + .iter_mut() + .rev() + .find(|d| d.unit == *name && !d.inserted.is_empty()) + { + rec.inserted = rec.inserted.replacen(text, "", 1); + } + continue; + } + let os = to_original(span.start, &drops, false); + let oe = to_original(span.end, &drops, true); + let ce = to_original(cut.end, &drops, true); + let lines = current[cut.start as usize..cut.end as usize] + .matches('\n') + .count() as u32; + planned.push((os, oe, cs, ce, lines, message.clone())); + } + if cuts.is_empty() && closers == 0 { + remaining = Some(first); + break; + } + // Closers were counted over tokens this round's cuts may take + // away: the next parse decides on the cut text. + if !cuts.is_empty() { + closers = 0; + } + for (os, oe, cs, ce, lines, message) in &planned { + let start = index.line_col(*os); + let end = index.line_col(*oe); + out.dropped.push(DroppedText { + unit: name.clone(), + start: *os, + end: *oe, + line: start.line, + col: start.col, + end_line: end.line, + end_col: end.col, + text: original[*os as usize..*oe as usize].to_string(), + lines_removed: *lines, + whole_lines: (*cs, *ce) != (*os, *oe), + inserted: String::new(), + message: message.clone(), + }); + record_drop(&mut drops, *cs, *ce); + } + for (_, cut, _) in cuts.iter().rev() { + current.replace_range(cut.start as usize..cut.end as usize, ""); + } + if closers > 0 { + let mut inserted = String::new(); + if !current.is_empty() && !current.ends_with('\n') { + inserted.push('\n'); + } + for _ in 0..closers { + inserted.push_str("}\n"); + } + let pos = index.line_col(orig_len); + out.dropped.push(DroppedText { + unit: name.clone(), + start: orig_len, + end: orig_len, + line: pos.line, + col: pos.col, + end_line: pos.line, + end_col: pos.col, + text: String::new(), + lines_removed: 0, + whole_lines: false, + inserted: inserted.clone(), + message: closer_message.clone(), + }); + current.push_str(&inserted); + } + } + if let Some(d) = remaining { + let pos = LineIndex::new(¤t).line_col(d.span.start.min(current.len() as u32)); + out.unrepaired.push(UnrepairedUnit { + unit: name.clone(), + message: d.message, + line: pos.line, + col: pos.col, + }); + } + out.sources.push((name.clone(), current)); + } + out +} + +/// The start of the run of spaces and tabs ending at `pos` — where the +/// line's indentation begins, when only indentation precedes `pos`. +fn indent_start(bytes: &[u8], pos: u32) -> u32 { + let mut start = pos; + while start > 0 && matches!(bytes[start as usize - 1], b' ' | b'\t') { + start -= 1; + } + start +} + +/// The text a removal takes with the member at `extent`: its own lines, +/// indentation and line break included (either line ending), when the +/// member stands alone on them. A member that shares its line keeps the +/// line as written, and so does one with no line break after it — +/// there, only the blanks trailing the member go with it. +/// +/// Sibling of [`widen_to_own_lines`], which repairs unparseable text +/// rather than planning an edit and so also takes the indentation of a +/// member that ends the file. +fn cut_whole_lines(src: &str, extent: Span) -> Span { + let bytes = src.as_bytes(); + let start = indent_start(bytes, extent.start); + if start > 0 && bytes[start as usize - 1] != b'\n' { + return extent; + } + let mut end = extent.end; + while (end as usize) < bytes.len() && matches!(bytes[end as usize], b' ' | b'\t') { + end += 1; + } + let rest = &bytes[end as usize..]; + if rest.starts_with(b"\r\n") { + Span::new(start, end + 2) + } else if rest.starts_with(b"\n") { + Span::new(start, end + 1) + } else { + // Nothing closes the line, so the indentation stays where it is. + Span::new(extent.start, end) + } +} + +/// Widen `span` to whole lines when its text stands alone on them: the +/// indentation before it and the line break after it go with it. +fn widen_to_own_lines(text: &str, span: Span) -> Span { + let bytes = text.as_bytes(); + let start = indent_start(bytes, span.start); + if start > 0 && bytes[start as usize - 1] != b'\n' { + return span; + } + let mut end = span.end; + while (end as usize) < bytes.len() && matches!(bytes[end as usize], b' ' | b'\t') { + end += 1; + } + let rest = &bytes[end as usize..]; + if rest.starts_with(b"\r\n") { + Span::new(start, end + 2) + } else if rest.starts_with(b"\n") { + Span::new(start, end + 1) + } else if rest.is_empty() { + Span::new(start, end) + } else { + span + } +} + +/// The body members of a member, for every kind that owns a body. The +/// sub-bodies of control usages (`if`/`while`/`for` branches) are not +/// descended: an error in one charges the whole control usage. +fn member_body(m: &sysmlv2_syntax::ast::Member) -> Option<&[sysmlv2_syntax::ast::Member]> { + use sysmlv2_syntax::ast::MemberKind; + match &m.kind { + MemberKind::Package(p) => p.body.as_deref(), + MemberKind::Definition(d) => d.body.as_deref(), + MemberKind::Usage(u) + | MemberKind::Subject(u) + | MemberKind::Actor(u) + | MemberKind::Stakeholder(u) + | MemberKind::Objective(u) + | MemberKind::FramedConcern(u) + | MemberKind::RequirementVerification(u) + | MemberKind::Render(u) + | MemberKind::Return(u) + | MemberKind::RequirementConstraint { usage: u, .. } + | MemberKind::StateSubaction { + action: Some(u), .. + } => u.body.as_deref(), + MemberKind::MultiplicityDecl(d) => d.body.as_deref(), + _ => None, + } +} + +/// The innermost member whose span holds `offset`, across nested bodies. +fn innermost_member( + members: &[sysmlv2_syntax::ast::Member], + offset: u32, +) -> Option<&sysmlv2_syntax::ast::Member> { + for m in members { + if m.span.start <= offset && offset < m.span.end { + if let Some(inner) = member_body(m).and_then(|b| innermost_member(b, offset)) { + return Some(inner); + } + return Some(m); + } + } + None +} + +/// The deepest member whose span ends exactly at `offset`: where the +/// parser reports a missing terminator. +fn deepest_member_ending_at( + members: &[sysmlv2_syntax::ast::Member], + offset: u32, +) -> Option<&sysmlv2_syntax::ast::Member> { + let m = members.iter().find(|m| m.span.end == offset)?; + Some( + member_body(m) + .and_then(|b| deepest_member_ending_at(b, offset)) + .unwrap_or(m), + ) +} + +/// The end offset of the `{` that opens the member's own body: the one +/// the member's last `}` closes, or — for a member the parser left open +/// at the end of the unit — the outermost `{` inside it without a match. +/// `None` when the member has no braces. +fn member_body_open( + m: &sysmlv2_syntax::ast::Member, + tokens: &[sysmlv2_syntax::token::Token], +) -> Option { + use sysmlv2_syntax::token::TokenKind; + let first = tokens.partition_point(|t| t.span.start < m.span.start); + let mut open: Vec = Vec::new(); + let mut last_closed: Option = None; + for t in tokens[first..] + .iter() + .take_while(|t| t.span.start < m.span.end) + { + match t.kind { + TokenKind::LBrace => open.push(t.span.end), + TokenKind::RBrace => { + if let Some(o) = open.pop() { + last_closed = Some(o); + } + } + _ => {} + } + } + open.first().copied().or(last_closed) +} + +/// The text a diagnostic at `at` condemns: the member whose declaration +/// holds it; the member ending there when the diagnostic is zero-width +/// (it lacks its terminator); otherwise the failed statement the parser +/// skipped in the enclosing body, recovered from the tokens after the +/// previous sibling (or the body's `{`). +fn failed_extent( + members: &[sysmlv2_syntax::ast::Member], + tokens: &[sysmlv2_syntax::token::Token], + at: u32, + zero_width: bool, +) -> Span { + let (siblings, floor): (&[sysmlv2_syntax::ast::Member], u32) = + match innermost_member(members, at) { + Some(m) => match (member_body(m), member_body_open(m, tokens)) { + (Some(body), Some(open_end)) if at >= open_end => (body, open_end), + _ => return m.span, + }, + None => (members, 0), + }; + if zero_width { + if let Some(c) = deepest_member_ending_at(siblings, at) { + return c.span; + } + } + let anchor = siblings + .iter() + .filter(|c| c.span.end <= at) + .map(|c| c.span.end) + .max() + .unwrap_or(floor) + .max(floor); + statement_extent(tokens, anchor, at) +} + +/// The failed statement between `anchor` (the end of the last parsed +/// text before it) and the diagnostic at `at`, recovered from the +/// trivia-free tokens the way the parser skips it: from the first token +/// at or after `anchor`, forward through the next `;` at depth zero or +/// the end of a body opened inside it, stopping before the `}` that +/// closes the enclosing body. A diagnostic sitting on a brace at the +/// statement's start names a stray brace: that token alone. +fn statement_extent(tokens: &[sysmlv2_syntax::token::Token], anchor: u32, at: u32) -> Span { + use sysmlv2_syntax::token::TokenKind; + let start = tokens.partition_point(|t| t.span.start < anchor); + let i = tokens.partition_point(|t| t.span.end <= at); + if start >= tokens.len() { + return Span::new(at, at); + } + let i = i.max(start).min(tokens.len() - 1); + if i == start && matches!(tokens[i].kind, TokenKind::LBrace | TokenKind::RBrace) { + return tokens[i].span; + } + let mut end = i; + let mut depth = 0i64; + let mut k = i; + while k < tokens.len() { + match tokens[k].kind { + TokenKind::LBrace => depth += 1, + TokenKind::RBrace => { + if depth == 0 { + break; + } + depth -= 1; + if depth == 0 { + end = k + 1; + break; + } + } + TokenKind::Semi if depth == 0 => { + end = k + 1; + break; + } + _ => {} + } + k += 1; + end = k; + } + if end <= start { + return tokens[i].span; + } + Span::new(tokens[start].span.start, tokens[end - 1].span.end) +} + +/// Check in-memory sources: per-unit parse /// and body-context validation always; referential and semantic checks /// against the standard library when `lib_dir` is given (loaded through -/// the same sealed-snapshot cache as [`Session`]). Unit names ending in +/// the same prepared-library cache as [`Session`]). Unlike CLI `check`, +/// model-level checks require a library here, and unused-import analysis is +/// not included. Unit names ending in /// `.kerml` parse as KerML. /// /// Model problems come back as [`CheckFinding`]s — a broken parse is a @@ -657,85 +1295,184 @@ pub fn check_sources_with_library( sources: &[(String, String)], lib: Option<&Library>, ) -> Result, SessionError> { - fn findings_for(name: &str, src: &str, diags: &[Diagnostic]) -> Vec { - let index = LineIndex::new(src); - diags - .iter() - .map(|d| { - let pos = index.line_col(d.span.start); - CheckFinding { - severity: d.severity, - message: d.message.clone(), - unit: name.to_string(), - line: pos.line, - col: pos.col, - span: d.span, - } - }) - .collect() - } - - let mut findings = Vec::new(); - // Per-unit stages: parse diagnostics; body-context checks only on a - // clean parse (context checks on a broken parse would mislead). - let mut parsed: Vec<&(String, String)> = Vec::new(); - for entry in sources { - let (name, src) = entry; - let parse = if name.ends_with(".kerml") { - parse_kerml_source(src) - } else { - parse_source(src) - }; - if !parse.diagnostics.is_empty() { - findings.extend(findings_for(name, src, &parse.diagnostics)); - continue; + let mut parsed = Vec::new(); + let mut findings = syntax_findings(sources, |source| { + if lib.is_some() { + parsed.push(source); } - findings.extend(findings_for( - name, - src, - &sysmlv2_syntax::check::validate(&parse.unit), - )); - parsed.push(entry); - } + }); // Referential + semantic checks: all cleanly-parsed units as one // model against the library. if let Some(lib) = lib { let mut model = Model::new(); let cache_path = load_library_into(&mut model, lib)?; - let boundary = model.units().len(); - for (name, src) in &parsed { - model.add_source(name.clone(), src); + for source in parsed { + model.add_parsed_source(source); } let mut resolved = ResolvedModel::build(&model); if let (Some(path), Some(cache)) = (cache_path, model.take_recorded_library_cache()) { let _ = cache.save(&path); } - for (unit, d) in sysmlv2_model::check::validate_model_with(&mut resolved, &model) - .into_iter() - .chain(sysmlv2_model::check::validate_semantics_with( - &mut resolved, - &model, - )) - { - let (name, src) = parsed[unit - boundary]; - findings.extend(findings_for(name, src, &[d])); + for (unit, d) in sysmlv2_model::check::validate_model_with(&mut resolved, &model) { + let name = &model.unit(unit).name; + let index = &model.unit(unit).lines; + findings.extend(findings_for(name, index, &[d], CheckStage::Referential)); + } + for (unit, d) in sysmlv2_model::check::validate_semantics_with(&mut resolved, &model) { + let name = &model.unit(unit).name; + let index = &model.unit(unit).lines; + findings.extend(findings_for(name, index, &[d], CheckStage::Semantic)); } } Ok(findings) } +/// Re-apply a session's explicit ids after a rebuild and bind the +/// references the lift could only spell as ids. +fn apply_explicit_ids( + resolved: &mut ResolvedModel, + explicit_ids: &mut HashMap, + binds_ids: bool, + warnings: &mut Vec, +) { + if explicit_ids.is_empty() && !binds_ids { + // A text session: nothing to overlay, and a quoted name that + // happens to look like an id stays a name. + return; + } + let map: HashMap = explicit_ids.iter().map(|(d, (g, _))| (*d, *g)).collect(); + let applied = resolved.override_ids(&map); + // Prune: an entry survives only while it lands on an element of the + // metaclass it was recorded for; a vanished or restructured element's + // entry dies with it. + let kept: HashMap = applied + .into_iter() + .filter(|(d, _, ty)| explicit_ids.get(d).is_some_and(|(_, t)| t == ty)) + .map(|(d, g, ty)| (d, (g, ty))) + .collect(); + let stale: Vec = explicit_ids + .keys() + .filter(|d| !kept.contains_key(*d)) + .copied() + .collect(); + if !stale.is_empty() { + // Undo any override applied to an element of another metaclass. + let undo: HashMap = stale + .iter() + .filter_map(|d| explicit_ids.get(d).map(|(g, _)| (*g, *d))) + .collect(); + resolved.override_ids(&undo); + } + *explicit_ids = kept; + if !binds_ids { + return; + } + let bound = resolved.bind_id_spelled_references(); + if !bound.is_empty() { + // The lift's "cannot name reference target" notes for the ids + // that are now bound no longer apply. A bound id with no element + // in the model (a library element with no library loaded) is + // kept as spelled and reported once, so a library-typed payload + // loaded without its library still says so. + let spellings: Vec = bound.iter().map(|u| u.to_string()).collect(); + warnings.retain(|w| { + !(w.contains("cannot name reference target") && spellings.iter().any(|s| w.contains(s))) + }); + let outside = bound + .iter() + .filter(|id| resolved.element_by_id(&id.to_string()).is_none()) + .count(); + // Re-applied after every rebuild: state the count once. + warnings.retain(|w| !w.contains("target elements outside the document")); + if outside > 0 { + warnings.push(format!( + "{outside} reference(s) target elements outside the document and are kept by id \ + (load the library to resolve them)" + )); + } + } +} + +/// The per-unit stages of [`check_sources_with_library`] alone: parse +/// diagnostics, and body-context checks on every unit that parsed +/// cleanly (context checks on a broken parse would mislead). No model +/// is built — the host that goes on to open a [`Session`] over the +/// units that parsed gets the resolution stages from +/// [`Session::check_findings`] without resolving the sources twice. +#[must_use] +pub fn check_sources_syntax(sources: &[(String, String)]) -> Vec { + syntax_findings(sources, |_| {}) +} + +fn findings_for( + name: &str, + index: &LineIndex, + diags: &[Diagnostic], + stage: CheckStage, +) -> Vec { + diags + .iter() + .map(|d| { + let pos = index.line_col(d.span.start); + CheckFinding { + severity: d.severity, + message: d.message.clone(), + unit: name.to_string(), + line: pos.line, + col: pos.col, + span: d.span, + stage, + } + }) + .collect() +} + +/// Report syntax findings and pass each clean parse to its consumer. A +/// syntax-only caller drops each tree before the next source is parsed. +fn syntax_findings( + sources: &[(String, String)], + mut clean: impl FnMut(sysmlv2_model::model::ParsedSource), +) -> Vec { + let mut findings = Vec::new(); + for (name, src) in sources { + let parsed = sysmlv2_model::model::ParsedSource::new(name.clone(), src); + if !parsed.diagnostics().is_empty() { + findings.extend(findings_for( + name, + parsed.lines(), + parsed.diagnostics(), + CheckStage::Parse, + )); + continue; + } + findings.extend(findings_for( + name, + parsed.lines(), + &sysmlv2_syntax::check::validate(parsed.unit()), + CheckStage::Context, + )); + clean(parsed); + } + findings +} + fn rebuild( sources: &[(String, String)], lib: Option<&Library>, ) -> Result<(Model, ResolvedModel, usize), SessionError> { + // Checked before the library loads: the payload emitters key every + // unit by its name, so a blank one has no place to be laid out. + if let Some((name, _)) = sources.iter().find(|(name, _)| name.trim().is_empty()) { + return Err(SessionError::InvalidUnitName(name.clone())); + } let mut model = Model::new(); let mut cache_path = None; if let Some(lib) = lib { cache_path = load_library_into(&mut model, lib)?; } - let unit_offset = model.units().len(); + let unit_offset = model.unit_count(); for (name, src) in sources { let unit = model.add_source(name.clone(), src); if !unit.diagnostics.is_empty() { @@ -762,16 +1499,27 @@ pub fn unused_private_imports_with( resolved: &mut ResolvedModel, texts: &[(usize, String)], ) -> Vec<(usize, Span)> { - let candidates = resolved.unused_private_imports(); + let units: Vec<_> = texts.iter().map(|(unit, _)| *unit).collect(); + let candidates = resolved.unused_private_imports_for_units(&units); + let mut by_unit = std::collections::HashMap::new(); + for (unit, text) in texts { + by_unit.entry(*unit).or_insert(text); + } + let targets: Vec<_> = candidates.iter().map(|(_, target, _, _)| *target).collect(); + let names = resolved.namespace_member_names_many(&targets); + let mut occurrences = std::collections::HashMap::new(); let mut out = Vec::new(); for (_, target, unit, span) in candidates { - let Some((_, text)) = texts.iter().find(|(i, _)| *i == unit) else { - continue; // library unit — never reported + let Some(text) = by_unit.get(&unit) else { + continue; }; - let names = resolved.namespace_member_names(target); - let mentioned = names - .iter() - .any(|name| !name.is_empty() && mentions_outside(text, name, span)); + let names = &names[&target]; + let mentioned = names.iter().any(|name| { + occurrences + .entry((unit, name.clone())) + .or_insert_with(|| mention_extent(text, name)) + .is_some_and(|(start, end)| start < span.start as usize || end > span.end as usize) + }); if !mentioned { out.push((unit, span)); } @@ -789,24 +1537,29 @@ fn line_col(text: &str, pos: usize) -> (usize, usize) { } } -fn mentions_outside(text: &str, name: &str, skip: Span) -> bool { +// Whole-source ASCII word boundaries intentionally include comments and +// restricted names. Changing to identifier tokens would change the contract. +fn mention_extent(text: &str, name: &str) -> Option<(usize, usize)> { + if name.is_empty() { + return None; + } let bytes = text.as_bytes(); let is_word = |b: u8| b.is_ascii_alphanumeric() || b == b'_'; let mut from = 0; + let mut extent: Option<(usize, usize)> = None; while let Some(i) = text[from..].find(name) { let start = from + i; let end = start + name.len(); - from = start + 1; - if start >= skip.start as usize && end <= skip.end as usize { - continue; - } + // Include overlapping occurrences, without slicing inside a UTF-8 + // character when a restricted name starts with a non-ASCII letter. + from = start + name.chars().next().unwrap().len_utf8(); let left_ok = start == 0 || !is_word(bytes[start - 1]); let right_ok = end >= bytes.len() || !is_word(bytes[end]); if left_ok && right_ok { - return true; + extent = Some(extent.map_or((start, end), |(first, _)| (first, end))); } } - false + extent } impl Session { @@ -822,14 +1575,26 @@ impl Session { /// Open a session over in-memory sources: `(unit name, text)` pairs. /// Unit names ending in `.kerml` parse as KerML. pub fn from_sources(sources: Vec<(String, String)>) -> Result { - let (model, resolved, unit_offset) = rebuild(&sources, None)?; + Self::from_sources_with_library(sources, None) + } + + /// [`Self::from_sources`] resolved against a library in the same + /// build — [`Self::from_sources`] followed by + /// [`Self::load_library_from`] would resolve the user units twice. + pub fn from_sources_with_library( + sources: Vec<(String, String)>, + lib: Option, + ) -> Result { + let (model, resolved, unit_offset) = rebuild(&sources, lib.as_ref())?; Ok(Session { sources, - lib: None, + lib, unit_offset, model, resolved, warnings: Vec::new(), + explicit_ids: HashMap::new(), + binds_ids: false, }) } @@ -944,7 +1709,24 @@ impl Session { ), )); } - let (model, resolved, unit_offset) = rebuild(&sources, lib)?; + let (model, mut resolved, unit_offset) = rebuild(&sources, lib)?; + // Explicit ids: pair the loaded document's elements with the + // rebuilt model's by ownership path (roots by document order), + // and keep every id the document carried that the derivation + // would have replaced. + let external = |s: &str| names.get(s).and_then(|segs| segs.last().cloned()); + let (mut explicit_ids, unmatched) = + sysmlv2_model::loader::explicit_id_map(&value, &model, &external, &mut warnings); + if unmatched > 0 { + warnings.push(format!( + "{unmatched} element(s) of the document have no structural counterpart in the \ + rebuilt model; their ids are not preserved" + )); + } + let binds_ids = warnings + .iter() + .any(|w| w.contains("cannot name reference target")); + apply_explicit_ids(&mut resolved, &mut explicit_ids, binds_ids, &mut warnings); Ok(Session { sources, lib: lib.cloned(), @@ -952,9 +1734,39 @@ impl Session { model, resolved, warnings, + explicit_ids, + binds_ids, }) } + /// The session's compact element array with the explicit-id overlay. + fn compact_json_overlaid(&self) -> serde_json::Value { + let mut v = sysmlv2_model::json::model_to_compact_json(&self.model); + self.overlay(&mut v); + v + } + + fn compact_json_with_units_overlaid(&self) -> (serde_json::Value, Vec<(usize, String)>) { + let (mut v, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); + self.overlay(&mut v); + (v, units) + } + + fn overlay(&self, v: &mut serde_json::Value) { + if self.explicit_ids.is_empty() && !self.binds_ids { + return; + } + sysmlv2_model::loader::overlay_explicit_ids(v, &self.explicit_ids); + } + + /// Whether the session holds **explicit ids** — ids the loaded + /// document carried that are not this toolkit's graph derivation + /// (IDS.md). Such a session's compact payloads carry + /// [`sysmlv2_cbor::FLAG_EXPLICIT_IDS`], and id elision is refused. + pub fn has_explicit_ids(&self) -> bool { + !self.explicit_ids.is_empty() + } + /// Non-fatal problems from lifting interchange JSON (empty for /// sessions opened over text). pub fn warnings(&self) -> &[String] { @@ -977,32 +1789,52 @@ impl Session { /// [`Self::load_library`] over any [`Library`] source — in-memory /// `(unit name, text)` library units included (the WASM shape). pub fn load_library_from(&mut self, lib: Library) -> Result<(), SessionError> { - let (model, resolved, unit_offset) = rebuild(&self.sources, Some(&lib))?; + let (model, mut resolved, unit_offset) = rebuild(&self.sources, Some(&lib))?; + apply_explicit_ids( + &mut resolved, + &mut self.explicit_ids, + self.binds_ids, + &mut self.warnings, + ); self.lib = Some(lib); self.unit_offset = unit_offset; self.model = model; + // The closure policy is a session setting: it survives a rebuild. + let policy = self.resolved.closure_policy(); self.resolved = resolved; + self.resolved.set_closure_policy(policy); Ok(()) } /// Emit the session's model as compact interchange JSON (KerML 10.4; /// user units only — library elements resolve but never serialize). pub fn to_compact_json(&self) -> serde_json::Value { - sysmlv2_model::json::model_to_compact_json(&self.model) + self.compact_json_overlaid() } /// Emit the session's model as compact-form CBOR — the /// deterministic binary re-encoding of [`Self::to_compact_json`], /// decodable back to the identical element array. + /// + /// # Panics + /// + /// If the model's compact form falls outside the codec tables. The + /// codec's corpus gate pins the compact emitter to those tables, and + /// a session refuses a blank unit name, which is the one input the + /// encoder rejects outright. pub fn to_compact_cbor(&self) -> Vec { // The corpus gate in sysmlv2-cbor pins the compact emitter's // output to the codec tables, so the session's own compact form // always encodes. Payloads carry the model's unit structure — // each unit root's element index paired with its source path — // so decoders can lay the model back out as its original files. - let (json, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); - sysmlv2_cbor::to_compact_cbor_with_units(&json, &units) - .expect("session compact form is covered by the codec tables") + let (json, units) = self.compact_json_with_units_overlaid(); + if self.has_explicit_ids() { + sysmlv2_cbor::to_compact_cbor_with_units_explicit(&json, &units) + } else { + sysmlv2_cbor::to_compact_cbor_with_units(&json, &units) + } + .expect("session compact form is covered by the codec tables") } /// The unit structure the session's binary payloads carry: for @@ -1019,11 +1851,22 @@ impl Session { /// targets, so the exception map stays roots-only; decode against /// the **same library version** (`from_compact_cbor_elided` / /// `from_cbor_with`), or the digest refuses the payload. - pub fn to_compact_cbor_elided(&self) -> Vec { + /// + /// Refused (`Err`) for a session holding explicit ids: every given id + /// would ride the exception map anyway, and the payload must carry + /// the explicit-id flag, which the elided form does not. + pub fn to_compact_cbor_elided(&self) -> Result, SessionError> { + if self.has_explicit_ids() { + return Err(SessionError::ExplicitIds); + } let names = self.library_id_names(); - let (json, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); - sysmlv2_cbor::to_compact_cbor_elided_with_units(&json, &|s| names.get(s).cloned(), &units) - .expect("session compact form is covered by the codec tables") + let (json, units) = self.compact_json_with_units_overlaid(); + Ok(sysmlv2_cbor::to_compact_cbor_elided_with_units( + &json, + &|s| names.get(s).cloned(), + &units, + ) + .expect("session compact form is covered by the codec tables")) } /// Encode the delta from `base` (a compact element array, any @@ -1039,16 +1882,14 @@ impl Session { // One emission feeds both the target and its unit table so the // indices line up by construction. Unit paths ride strict // deltas only — portable result indices are not exact. - let (target, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); + let (target, units) = self.compact_json_with_units_overlaid(); let units = if portable { Vec::new() } else { units }; sysmlv2_cbor::delta_compact_cbor( base, &target, - &sysmlv2_cbor::DeltaOptions { - portable, - units, - ..Default::default() - }, + &sysmlv2_cbor::DeltaOptions::new() + .with_portable(portable) + .with_units(units), ) .map_err(SessionError::Cbor) } @@ -1064,15 +1905,17 @@ impl Session { &self, base: &serde_json::Value, ) -> Result, SessionError> { + // Same policy as the elided snapshot: an explicit-id session + // produces no elided form. + if self.has_explicit_ids() { + return Err(SessionError::ExplicitIds); + } let names = self.library_id_names(); - let (target, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); + let (target, units) = self.compact_json_with_units_overlaid(); sysmlv2_cbor::delta_compact_cbor_elided( base, &target, - &sysmlv2_cbor::DeltaOptions { - units, - ..Default::default() - }, + &sysmlv2_cbor::DeltaOptions::new().with_units(units), &|s| names.get(s).cloned(), ) .map_err(SessionError::Cbor) @@ -1091,6 +1934,11 @@ impl Session { /// The model's **state digest** — the content identity /// a delta names its base by. Emission-order-independent: the same /// model state digests identically however it was produced. + /// + /// # Panics + /// + /// As [`Self::to_compact_cbor`] — the digest runs over the same + /// compact form. pub fn state_digest(&self) -> Uuid { sysmlv2_cbor::state_digest(&self.to_compact_json()) .expect("session compact form is covered by the codec tables") @@ -1124,11 +1972,11 @@ impl Session { /// [`Self::apply_delta_cbor`] against a caller-held base document /// (a compact element array) instead of the session's own model — - /// the payload-file base path. A file base's identity is the - /// file's content: lifting it into a session re-derives ids and - /// re-seeds units, so the lifted model digests differently and a - /// strict delta would refuse its own true base. The session still - /// serves as the library context for elided created ids. + /// the payload-file base path, for a caller that holds the base + /// document without having loaded it into a session (a loaded + /// session keeps the document's ids, so [`Self::apply_delta_cbor`] + /// serves that case). The session still serves as the library + /// context for elided created ids. pub fn apply_delta_cbor_to( &self, bytes: &[u8], @@ -1180,8 +2028,7 @@ impl Session { lib: Option<&Library>, indent: Indent, ) -> Result { - let (value, units) = - sysmlv2_cbor::from_compact_cbor_units(bytes).map_err(SessionError::Cbor)?; + let (value, units) = sysmlv2_cbor::from_compact_cbor_units(bytes)?; // Payloads carrying their unit structure restore the model's // original file layout: unit-path order is document order. let unit_names: Vec = units.into_iter().map(|(_, path)| path).collect(); @@ -1200,18 +2047,24 @@ impl Session { /// a partial model survives emit → lift losslessly (the Flexo /// change-record path). pub fn to_full_json_with(&self, recover_refs: bool) -> serde_json::Value { - sysmlv2_model::full::model_to_full_json_with(&self.model, recover_refs) + let mut v = sysmlv2_model::full::model_to_full_json_with(&self.model, recover_refs); + self.overlay(&mut v); + v } /// Emit the session's model as **full-form CBOR** — the binary /// re-encoding of [`Self::to_full_json_with`]. An emit view /// only: transport the compact form; expand at the edge. + /// + /// # Panics + /// + /// As [`Self::to_compact_cbor`], for the full form's tables. pub fn to_full_cbor(&self, recover_refs: bool) -> Vec { let full = self.to_full_json_with(recover_refs); // Root indices differ between the compact and full arrays // (implied relationships join the full form): re-locate each // unit root by element id. - let (compact, units) = sysmlv2_model::json::model_to_compact_json_with_units(&self.model); + let (compact, units) = self.compact_json_with_units_overlaid(); let by_id: HashMap<&str, usize> = full .as_array() .map(|arr| { @@ -1234,10 +2087,12 @@ impl Session { } /// Map an interchange document's element ids to this session's ids - /// by qualified name — the identity mapping a change record needs - /// when a payload from another producer (or another unit naming) was - /// lifted into this session: `(input id, session id)` for every - /// named input element present here under a different id. + /// by qualified name — `(input id, session id)` for every named + /// input element present here under a different id. A document + /// loaded into this session keeps its ids and maps nothing; the + /// mapping is for an input whose structure the session no longer + /// has (after a rename, or a text session compared with an earlier + /// export). pub fn id_map_from(&mut self, input: &serde_json::Value) -> Vec<(Uuid, Uuid)> { let input = unwrap_flexo(input); let names = sysmlv2_model::lift::document_name_map(&input); @@ -1268,6 +2123,50 @@ impl Session { out } + /// The check findings of the session's own model: what + /// [`check_sources_with_library`] reports for the same sources and + /// library, read off the session's build instead of a second one. + /// Parse findings never occur (a session holds only units that + /// parsed); context findings come from each unit's syntax, and the + /// referential and semantic stages — like `check`, only with a + /// library — from the resolved model, whose unresolved list and + /// import provenance both passes leave intact. Same order as + /// `check`: each unit's context findings, then referential, then + /// semantic. + pub fn check_findings(&mut self) -> Vec { + let mut findings = Vec::new(); + for (unit, name, _) in self.units() { + let mu = self.model.unit(unit); + findings.extend(findings_for( + name, + &mu.lines, + &sysmlv2_syntax::check::validate(&mu.unit), + CheckStage::Context, + )); + } + if self.lib.is_none() { + return findings; + } + let stage = + |diags: Vec<(usize, Diagnostic)>, stage: CheckStage, out: &mut Vec| { + for (unit, d) in diags { + let Some(i) = unit.checked_sub(self.unit_offset) else { + continue; + }; + let name = &self.sources[i].0; + let index = &self.model.unit(unit).lines; + out.extend(findings_for(name, index, &[d], stage)); + } + }; + let referential = + sysmlv2_model::check::validate_model_with(&mut self.resolved, &self.model); + stage(referential, CheckStage::Referential, &mut findings); + let semantic = + sysmlv2_model::check::validate_semantics_with(&mut self.resolved, &self.model); + stage(semantic, CheckStage::Semantic, &mut findings); + findings + } + /// The resolved model — navigation, `query`, evaluation. pub fn resolved(&mut self) -> &mut ResolvedModel { &mut self.resolved @@ -1310,6 +2209,7 @@ impl Session { return None; } match &self.lib { + Some(Library::Prepared(library)) => library.source(unit), Some(Library::Sources { units, .. }) => { units.get(unit).map(|(n, s)| (n.as_str(), s.as_str())) } @@ -1333,6 +2233,120 @@ impl Session { } } + /// Plan splitting `root` (a package in a user unit) into one unit + /// per directly nested package: the file tree, the root-level name + /// collisions and their renames. Apply it with + /// [`EditBuilder::split`]. Deeper levels split by running the plan + /// again on a hoisted package. + /// + /// New units take the root unit's extension; a root named without one + /// parses as SysML, so its new units take `.sysml`. + pub fn split_plan( + &mut self, + root: ElementRef, + options: &SplitOptions, + ) -> Result { + let unit_offset = self.unit_offset; + let r = &mut self.resolved; + if r.element_type(root) != "Package" { + return Err(TransformError::SplitIneligible { + reason: format!("`{}` is not a package", r.element_type(root)), + }); + } + let (unit, _) = r + .member_extent(root) + .ok_or(TransformError::NoExtent(root))?; + if unit < unit_offset { + return Err(TransformError::NotDeclared(root)); + } + let root_name = r + .element_name(root) + .ok_or(TransformError::NotDeclared(root))? + .to_string(); + let unit_name = self.sources[unit - unit_offset].0.clone(); + // The file segment alone carries the extension: a dot in a + // directory name must not be read as one. + let (dir_prefix, file) = unit_name + .rsplit_once('/') + .map_or(("", unit_name.as_str()), |(d, f)| (d, f)); + let (stem, extension) = file + .rsplit_once('.') + .filter(|(stem, ext)| !stem.is_empty() && !ext.is_empty()) + .unwrap_or((file, "sysml")); + let directory = match &options.directory { + Some(d) => d.trim_end_matches('/').to_string(), + None if dir_prefix.is_empty() => stem.to_string(), + None => format!("{dir_prefix}/{stem}"), + }; + let children: Vec = r + .owned_members(root) + .into_iter() + .filter(|&m| r.element_type(m) == "Package" && r.element_name(m).is_some()) + .collect(); + if children.is_empty() { + return Err(TransformError::SplitIneligible { + reason: format!("`{root_name}` owns no nested package"), + }); + } + let mut entries: Vec = Vec::new(); + let mut taken_names: Vec = Vec::new(); + let mut taken_units: Vec = Vec::new(); + for child in children { + let name = r.element_name(child).unwrap_or_default().to_string(); + let qualified = r + .element_qualified_name(child) + .ok_or(TransformError::NotDeclared(child))?; + let (_, extent) = r + .member_extent(child) + .ok_or(TransformError::NoExtent(child))?; + // A hoisted package becomes a root-level name: it must not + // collide with one the model already resolves (user or + // library) or with another hoisted package. + let mut top = name.clone(); + let mut attempt = 0; + while r.resolve_qualified(&escape_name(&top)).is_some() || taken_names.contains(&top) { + attempt += 1; + top = if attempt == 1 { + format!("{root_name} {name}") + } else { + format!("{root_name} {name} {attempt}") + }; + } + taken_names.push(top.clone()); + let new_name = (top != name).then_some(top.clone()); + let file = match options.naming { + SplitNaming::Keep => file_segment(&top), + SplitNaming::Slug => slug(&top), + }; + let file = if options.uri_units { + uri_segment(&file) + } else { + file + }; + let mut unit = format!("{directory}/{file}.{extension}"); + let mut n = 1; + while taken_units.contains(&unit) || self.sources.iter().any(|(u, _)| *u == unit) { + n += 1; + unit = format!("{directory}/{file}-{n}.{extension}"); + } + taken_units.push(unit.clone()); + entries.push(SplitEntry { + package: child, + qualified, + name, + new_name, + unit, + bytes: (extent.end - extent.start) as usize, + }); + } + Ok(SplitPlan { + root, + root_unit: unit_name, + directory, + entries, + }) + } + /// Textual `private import` members that provably feed nothing in /// their unit — the unused-import check. Three conditions, all /// required (each alone over-reports): @@ -1361,6 +2375,7 @@ impl Session { EditBuilder { session: self, ops: Vec::new(), + skip_colliding_renames: false, } } @@ -1374,12 +2389,11 @@ impl Session { /// as [`Self::minimize_qualifications`], without any rewriting. pub fn minimal_spelling(&mut self, context: ElementRef, target: ElementRef) -> Option { use sysmlv2_syntax::ast::{Name, QualifiedName}; - let full_qn = self.resolved.element_qualified_name(target)?; - let full = full_qn - .split("::") - .map(|s| spell_name(&decode_name(s))) - .collect::>() - .join("::"); + // The lookup-name spelling: it re-resolves, where the + // specification's `qualifiedName` may name an unnamed end by its + // implied positional name. + let full_qn = self.resolved.element_reference_spelling(target)?; + let full = sysmlv2_syntax::name::respell_canonical(None, &full_qn); let Some((unit, extent)) = self.resolved.member_extent(context) else { return Some(full); }; @@ -1392,7 +2406,7 @@ impl Session { let Some(scope) = scope else { return Some(full); }; - let segs: Vec = full_qn.split("::").map(decode_name).collect(); + let segs = sysmlv2_syntax::name::split_canonical(&full_qn); for k in 1..=segs.len() { let suffix = &segs[segs.len() - k..]; let qn = QualifiedName { @@ -1431,6 +2445,11 @@ impl Session { /// every untouched site must be unaffected, or the offending /// respells are dropped and the pass retried. Declarations never /// move, so interchange ids are untouched by construction. + /// + /// # Panics + /// + /// If a feature-chain run is assembled with no sites in it, which + /// the grouping cannot produce. pub fn minimize_qualifications(&mut self) -> Result { use sysmlv2_syntax::ast::{Name, QualifiedName}; struct Cand { @@ -1441,6 +2460,11 @@ impl Session { qn: String, name_len: u32, } + impl Cand { + fn range(&self) -> (usize, u32, u32) { + (self.unit, self.start, self.end) + } + } // Candidate respells: per plain site, the shortest suffix of the // target's qualified name that resolves back to the same element // from the site's scope, when strictly shorter than the written @@ -1514,7 +2538,7 @@ impl Session { let Some(head_qn) = self.resolved.element_qualified_name(first.target) else { continue; }; - let segs: Vec = head_qn.split("::").map(decode_name).collect(); + let segs = sysmlv2_syntax::name::split_canonical(&head_qn); let mut head: Option = None; for k in 1..=segs.len() { let suffix = &segs[segs.len() - k..]; @@ -1577,6 +2601,14 @@ impl Session { let mut report = MinimizeReport::default(); let mut banned: HashSet<(usize, u32)> = HashSet::new(); + // Candidates come from disjoint reference spans, so they should + // not overlap — but the pass below splices them in one cursor + // sweep per unit, which would slice backwards if two ever did. + // An overlapping candidate is banned outright: the first of the + // run is respelled and the rest keep their printed spelling. + for i in overlapping_candidates(&cands.iter().map(Cand::range).collect::>()) { + banned.insert((cands[i].unit, cands[i].start)); + } loop { let active: Vec<&Cand> = cands .iter() @@ -1690,13 +2722,40 @@ impl Session { } report.respelled = active.len(); self.sources = new_sources; + apply_explicit_ids( + &mut new_resolved, + &mut self.explicit_ids, + self.binds_ids, + &mut self.warnings, + ); self.model = new_model; + let policy = self.resolved.closure_policy(); self.resolved = new_resolved; + self.resolved.set_closure_policy(policy); return Ok(report); } } } +/// Indexes of the ranges that overlap one kept before them, over +/// `(unit, start, end)` ranges sorted by `(unit, start)`: the first +/// range of an overlapping run is kept and every later range that +/// reaches back into it is reported. Applying the kept ranges in order +/// is then a single forward sweep per unit. +fn overlapping_candidates(ranges: &[(usize, u32, u32)]) -> Vec { + let mut overlapping = Vec::new(); + let mut kept: Option<(usize, u32, u32)> = None; + for (i, &r) in ranges.iter().enumerate() { + match kept { + // A later range that starts before the kept one ends — + // nested in it, or straddling its end. + Some((unit, _, end)) if unit == r.0 && r.1 < end => overlapping.push(i), + _ => kept = Some(r), + } + } + overlapping +} + /// Outcome of a [`Session::minimize_qualifications`] pass. #[derive(Debug, Default, Clone)] pub struct MinimizeReport { @@ -1750,6 +2809,11 @@ enum Op { usage: ElementRef, name: Option, }, + HoistToUnit { + e: ElementRef, + unit_name: String, + new_name: Option, + }, InlineDefinition { definition: ElementRef, }, @@ -1760,43 +2824,208 @@ enum Op { }, } -/// One committed batch's outcome. -#[derive(Debug, Default)] -pub struct CommitReport { - /// Interchange `@id` changes for elements whose ownership path moved - /// (renames rewrite the paths of the element and its descendants): - /// `(old id, new id)`, matched by qualified name through the rename - /// map. Unchanged elements keep their deterministic ids and do not - /// appear. - pub id_map: Vec<(Uuid, Uuid)>, - /// Non-fatal observations (e.g. the unresolved-reference count moved - /// because inserted text references something absent). - pub findings: Vec, - /// The text replacements the commit applied, in **pre-commit** - /// coordinates (byte offsets into each unit's previous source), - /// ordered by (unit, start) and non-overlapping. A caller mirroring - /// the session's sources elsewhere (an editor buffer, a review UI) - /// can replay exactly these instead of diffing whole units. - pub splices: Vec, +impl Op { + /// The element whose text the edit reads or rewrites, when it has + /// one — the handle the library guard checks. A move's destination + /// and a retarget's new target are checked by their own planners; + /// extract and inline answer through their eligibility gates, which + /// name the refusal precisely. + fn subject(&self) -> Option { + match self { + Op::Rename { e, .. } + | Op::SetFeatureValue { e, .. } + | Op::SetFeatureType { e, .. } + | Op::Remove { e } + | Op::ReplaceMember { e, .. } + | Op::HoistToUnit { e, .. } + | Op::MoveMember { e, .. } => Some(*e), + Op::InsertMember { owner, .. } => Some(*owner), + Op::Retarget { site, .. } => Some(site.owner), + Op::InsertTopLevel { .. } + | Op::AddUnit { .. } + | Op::ExtractDefinition { .. } + | Op::InlineDefinition { .. } => None, + } + } +} + +/// One committed batch's outcome. +#[derive(Debug, Default)] +pub struct CommitReport { + /// Interchange `@id` changes for elements whose ownership path moved + /// (renames rewrite the paths of the element and its descendants): + /// `(old id, new id)`, matched by qualified name through the rename + /// map. Unchanged elements keep their deterministic ids and do not + /// appear. + pub id_map: Vec<(Uuid, Uuid)>, + /// Non-fatal observations (e.g. the unresolved-reference count moved + /// because inserted text references something absent). + pub findings: Vec, + /// The text replacements the commit applied, in **pre-commit** + /// coordinates (byte offsets into each unit's previous source), + /// ordered by (unit, start) and non-overlapping. A caller mirroring + /// the session's sources elsewhere (an editor buffer, a review UI) + /// can replay exactly these instead of diffing whole units. + pub splices: Vec, +} + +/// One applied text replacement from a committed edit batch, in +/// pre-commit coordinates. +#[derive(Debug, Clone)] +pub struct AppliedSplice { + /// Unit name (as given to the session), not a resolver index. + pub unit: String, + /// Replaced byte range in the unit's pre-commit source. + pub start: u32, + pub end: u32, + /// Replacement text. + pub text: String, +} + +/// How a split names the files it creates. +#[derive(Clone, Copy, Debug, PartialEq, Eq, Default)] +pub enum SplitNaming { + /// The package name as written (`02 JPL.sysml`). + #[default] + Keep, + /// Letters, digits, `.`, `_` and `-` only; runs of anything else + /// become one `-` (`02-JPL.sysml`). + Slug, +} + +/// Options for [`Session::split_plan`]. +#[derive(Clone, Debug, Default)] +pub struct SplitOptions { + pub naming: SplitNaming, + /// Directory (unit-name prefix) for the new units; by default the + /// root's unit name without its extension (`models/TMT.sysml` → + /// `models/TMT`). + pub directory: Option, + /// Unit names are URIs (an editor's workspace): the new units' file + /// segments are percent-encoded the way editors spell a path + /// segment — every byte outside the unreserved set (letters, + /// digits, `-` `.` `_` `~`) as `%XX` — so a name with a space or a + /// sub-delimiter yields the exact string the editor opens the + /// created file under. Off for path-named (CLI) sessions. + pub uri_units: bool, +} + +/// One package of a split: where it goes and what it is called there. +#[derive(Clone, Debug)] +pub struct SplitEntry { + pub package: ElementRef, + /// Qualified name before the split. + pub qualified: String, + pub name: String, + /// The root-level name the package takes when its own would collide + /// with a name the model already resolves or another hoisted package. + pub new_name: Option, + /// Name of the new unit (a relative file path for CLI sessions). + pub unit: String, + /// Size of the package's text, for reporting. + pub bytes: usize, +} + +/// A planned split — see [`Session::split_plan`]. +#[derive(Clone, Debug)] +pub struct SplitPlan { + pub root: ElementRef, + /// Unit the root package is declared in. + pub root_unit: String, + pub directory: String, + pub entries: Vec, +} + +/// A name as one path segment: path separators and NUL become `-`, and +/// a name that would climb or vanish becomes `package`. +fn file_segment(name: &str) -> String { + let out: String = name + .chars() + .map(|c| { + if matches!(c, '/' | '\\' | '\0') { + '-' + } else { + c + } + }) + .collect(); + if out.is_empty() || out == "." || out == ".." { + "package".to_string() + } else { + out + } +} + +/// A file segment as a URI path segment: bytes outside the unreserved +/// set (`A-Z a-z 0-9 - . _ ~`) become `%XX` (uppercase hex, UTF-8 +/// bytes), the spelling editors give a created file's uri. +fn uri_segment(name: &str) -> String { + const HEX: &[u8; 16] = b"0123456789ABCDEF"; + let mut out = String::with_capacity(name.len()); + for b in name.bytes() { + if b.is_ascii_alphanumeric() || matches!(b, b'-' | b'.' | b'_' | b'~') { + out.push(b as char); + } else { + out.push('%'); + out.push(HEX[usize::from(b >> 4)] as char); + out.push(HEX[usize::from(b & 0x0F)] as char); + } + } + out +} + +/// A file-name slug: letters, digits, `.`, `_`, `-`; anything else +/// collapses to one `-`. +fn slug(name: &str) -> String { + let mut out = String::with_capacity(name.len()); + let mut dash = false; + for c in name.chars() { + if c.is_alphanumeric() || matches!(c, '.' | '_' | '-') { + out.push(c); + dash = false; + } else if !dash && !out.is_empty() { + out.push('-'); + dash = true; + } + } + let out = out.trim_end_matches('-').to_string(); + if out.is_empty() { + "package".to_string() + } else { + out + } } -/// One applied text replacement from a committed edit batch, in -/// pre-commit coordinates. -#[derive(Debug, Clone)] -pub struct AppliedSplice { - /// Unit name (as given to the session), not a resolver index. - pub unit: String, - /// Replaced byte range in the unit's pre-commit source. - pub start: u32, - pub end: u32, - /// Replacement text. - pub text: String, +/// Remove `indent` from the start of every line after the first that +/// carries it. Returns the text and, per line, (old start, new start) +/// offsets for mapping positions. +fn dedent_lines(text: &str, indent: &str) -> (String, Vec<(u32, u32)>) { + let mut out = String::with_capacity(text.len()); + let mut lines = Vec::new(); + let mut old_pos = 0u32; + for (i, line) in text.split_inclusive('\n').enumerate() { + let stripped = if i > 0 && !indent.is_empty() && line.starts_with(indent) { + &line[indent.len()..] + } else { + line + }; + let new_start = out.len() as u32; + let old_start = old_pos + (line.len() - stripped.len()) as u32; + lines.push((old_start, new_start)); + out.push_str(stripped); + old_pos += line.len() as u32; + } + (out, lines) } /// An accumulating edit batch over a [`Session`]. +#[must_use = "an edit batch does nothing until committed"] pub struct EditBuilder<'s> { session: &'s mut Session, ops: Vec, + /// Colliding renames (see [`Self::skip_colliding_renames`]) are + /// dropped from the batch and reported instead of refusing it. + skip_colliding_renames: bool, } /// One planned text replacement, in pre-commit coordinates. @@ -1842,6 +3071,21 @@ impl EditBuilder<'_> { self } + /// Drop, instead of refusing on, every rename whose new name a + /// sibling in the same owner already carries after the batch (a + /// declared or short name the batch leaves in place, or a name + /// another rename in the batch gives a sibling). By default such a + /// rename refuses the whole batch with + /// [`TransformError::NameTaken`] before anything is planned; with + /// this policy the rest of the batch commits and each dropped + /// rename is one line of [`CommitReport::findings`]. Built for + /// bulk fix-all batches, where one clashing suggestion must not + /// hold up thousands of legal renames. + pub fn skip_colliding_renames(&mut self) -> &mut Self { + self.skip_colliding_renames = true; + self + } + /// Replace `e`'s feature value expression (`= …`), or add one before /// the terminating `;` when the declaration has none. pub fn set_feature_value(&mut self, e: ElementRef, expr: &str) -> &mut Self { @@ -1888,9 +3132,9 @@ impl EditBuilder<'_> { } /// Create a new, empty unit under `name`. Refuses a name the - /// session already holds. Ops are planned against the pre-commit - /// state, so an `insert_top_level` into the born unit belongs in a - /// *following* batch, not this one. + /// session already holds. Later ops in the same batch may write into + /// it (`insert_top_level`, `hoist_to_unit`); it joins the session at + /// commit. pub fn add_unit(&mut self, name: &str) -> &mut Self { self.ops.push(Op::AddUnit { name: name.to_string(), @@ -1955,6 +3199,54 @@ impl EditBuilder<'_> { self } + /// Hoist the member declaration that created `e` (a package, as a + /// rule) to the top level of `unit_name` — an existing unit, or one + /// this batch adds — under `new_name` when given. The moved text is + /// dedented to the top level and every reference written inside it + /// to something outside it is respelled by its reference spelling, + /// so the moved body resolves on its own; references from elsewhere + /// keep resolving when the old owner re-exports the moved package + /// (see [`Session::split_plan`]). Verified like a move. + pub fn hoist_to_unit( + &mut self, + e: ElementRef, + unit_name: &str, + new_name: Option<&str>, + ) -> &mut Self { + self.ops.push(Op::HoistToUnit { + e, + unit_name: unit_name.to_string(), + new_name: new_name.map(str::to_string), + }); + self + } + + /// Apply a [`SplitPlan`]: every entry's package is hoisted into its + /// own new unit and the root package re-exports it — `public import + /// ;`, or `public alias for ;` when the package was + /// renamed to avoid a root-level collision — so every qualified + /// reference through the root keeps resolving. + pub fn split(&mut self, plan: &SplitPlan) -> &mut Self { + for entry in &plan.entries { + self.add_unit(&entry.unit); + } + for entry in &plan.entries { + self.hoist_to_unit(entry.package, &entry.unit, entry.new_name.as_deref()); + } + for entry in &plan.entries { + let text = match &entry.new_name { + Some(new) => format!( + "public alias {} for {};", + spell_name(&entry.name), + spell_name(new) + ), + None => format!("public import {};", spell_name(&entry.name)), + }; + self.insert_member(plan.root, &text); + } + self + } + /// Extract `usage`'s inline body into a fresh definition: the /// body region moves byte-preserved into a /// ` def` inserted as the sibling immediately before the @@ -1966,7 +3258,7 @@ impl EditBuilder<'_> { /// `name` `None` synthesizes UpperCamel from the usage's declared /// name (`fuel_tank` → `FuelTank`); a sibling already declaring the /// name refuses with [`TransformError::NameTaken`]. Eligibility is - /// the M29a0 policy ([`eligibility::ExtractRefusal`] via + /// the eligibility policy ([`eligibility::ExtractRefusal`] via /// [`TransformError::ExtractIneligible`]). The commit runs under /// relocation discipline: every generated reference target is /// expectation-verified, any newly unresolved reference refuses, @@ -1991,7 +3283,7 @@ impl EditBuilder<'_> { /// Inlining a definition just produced by /// [`Self::extract_definition`] restores the original usage /// byte-for-byte; no reverse-placement or body-partition promise is - /// made for arbitrary definitions. Eligibility is the M29a0 policy + /// made for arbitrary definitions. Eligibility is the policy /// ([`eligibility::InlineRefusal`] via /// [`TransformError::InlineIneligible`]): sole plain FeatureTyping, /// provenance-classified incoming references, no member-name @@ -2020,11 +3312,28 @@ impl EditBuilder<'_> { } fn run(self, dry_run: bool) -> Result { - let EditBuilder { session, ops } = self; + let EditBuilder { + session, + ops, + skip_colliding_renames, + } = self; let mut planner = Planner::new(session); - for op in &ops { + let skipped = planner.rename_collisions(&ops, skip_colliding_renames)?; + if !ops.is_empty() && skipped.len() == ops.len() { + // Every op was dropped: nothing to splice, the session is + // untouched, and the report says why. + return Ok(CommitReport { + findings: skipped.into_values().collect(), + ..CommitReport::default() + }); + } + for (i, op) in ops.iter().enumerate() { + if skipped.contains_key(&i) { + continue; + } planner.plan(op)?; } + planner.findings.extend(skipped.into_values()); planner.commit(dry_run) } } @@ -2067,6 +3376,9 @@ struct Planner<'s> { /// Units this batch creates (empty, appended at commit before the /// rebuild). Not splices — splices key existing unit indices. new_units: Vec, + /// Findings recorded while planning (dropped colliding renames); + /// they lead the committed report's findings. + findings: Vec, } /// One `move_member`'s carried reference sites: the destination @@ -2093,14 +3405,61 @@ impl<'s> Planner<'s> { projection_subjects: Vec::new(), report_unused_imports: false, new_units: Vec::new(), + findings: Vec::new(), + } + } + + /// Text of a user unit, or the empty text of a unit this batch + /// adds. `None` for a library unit: no edit reads one. + fn src(&self, unit: usize) -> Option<&str> { + self.session + .source(unit) + .or_else(|| self.is_born(unit).then_some("")) + } + + /// [`Self::src`] for the unit `subject` lives in — a library unit + /// refuses with [`TransformError::NotDeclared`]. + fn user_src(&self, unit: usize, subject: ElementRef) -> Result<&str, TransformError> { + self.src(unit).ok_or(TransformError::NotDeclared(subject)) + } + + /// Whether `unit` is a unit this batch adds — it joins the session + /// empty at commit, after every existing unit. + fn is_born(&self, unit: usize) -> bool { + let first = self.session.unit_offset + self.session.sources.len(); + (first..first + self.new_units.len()).contains(&unit) + } + + /// Name of an existing or born unit by model unit index. + fn unit_name(&self, unit: usize) -> String { + let local = unit - self.session.unit_offset; + match self.session.sources.get(local) { + Some((name, _)) => name.clone(), + None => self.new_units[local - self.session.sources.len()].clone(), } } - fn src(&self, unit: usize) -> &str { - self.session.source(unit).expect("user unit") + /// Model unit index of an existing or born unit by name. + fn unit_by_name(&self, name: &str) -> Option { + if let Some((u, _, _)) = self.session.units().find(|(_, n, _)| *n == name) { + return Some(u); + } + let first = self.session.unit_offset + self.session.sources.len(); + self.new_units + .iter() + .position(|n| n == name) + .map(|k| first + k) } fn plan(&mut self, op: &Op) -> Result<(), TransformError> { + // Library elements are resolution targets only. An edit whose + // subject lives in a library unit is refused here, before any + // op reads the subject's text or plans a splice into its unit. + if let Some(subject) = op.subject() { + if self.session.resolved.is_library_element(subject) { + return Err(TransformError::NotDeclared(subject)); + } + } match op { Op::Rename { e, new_name } => self.plan_rename(*e, new_name), Op::SetFeatureValue { e, expr } => self.plan_set_value(*e, expr), @@ -2117,10 +3476,134 @@ impl<'s> Planner<'s> { index, } => self.plan_move(*e, *new_owner, *index), Op::ExtractDefinition { usage, name } => self.plan_extract(*usage, name.as_deref()), + Op::HoistToUnit { + e, + unit_name, + new_name, + } => self.plan_hoist(*e, unit_name, new_name.as_deref()), Op::InlineDefinition { definition } => self.plan_inline(*definition), } } + /// The renames in `ops` whose new name collides with a sibling's: + /// a name another member of the same owner still carries after the + /// batch (its declared name unless the batch renames it away, its + /// short name regardless, the effective name of an unnamed + /// feature), or a name an earlier rename in the batch already gives + /// a sibling. Two members of one namespace sharing a name make every + /// qualified reference to either ambiguous — the commit's + /// verification would refuse the batch at each such site, without + /// saying which rename caused it. Returns op index → finding text; + /// without `skip`, the first collision is a + /// [`TransformError::NameTaken`] refusal instead. + fn rename_collisions( + &mut self, + ops: &[Op], + skip: bool, + ) -> Result, TransformError> { + let renamed: HashSet = ops + .iter() + .filter_map(|op| match op { + Op::Rename { e, .. } => Some(*e), + _ => None, + }) + .collect(); + let mut out = BTreeMap::new(); + if renamed.is_empty() { + return Ok(out); + } + let r = self.session.resolved(); + // Per owner (`None` = the root namespace): the names its members + // keep, and the names the batch's renames claim, each to the + // element carrying it. + let mut taken: HashMap, HashMap> = HashMap::new(); + let mut claimed: HashMap, HashMap> = HashMap::new(); + let mut roots: Option> = None; + for (i, op) in ops.iter().enumerate() { + let Op::Rename { e, new_name } = op else { + continue; + }; + let owner = r.owner(*e); + let names = taken.entry(owner).or_insert_with(|| { + let siblings: Vec = match owner { + Some(o) => r.owned_members(o), + None => roots + .get_or_insert_with(|| { + // Owner lookups memoize, so the candidates + // are read out before they are filtered. + let mut all: Vec = r.user_elements().collect(); + all.retain(|x| r.owner(*x).is_none()); + all + }) + .clone(), + }; + let mut names: HashMap = HashMap::new(); + for sib in siblings { + if !renamed.contains(&sib) { + // What lookup finds the sibling by, not the + // specification's effective name. + if let Some(n) = r.element_lookup_name(sib) { + names.entry(n).or_insert(sib); + } + } + if let Some(sn) = r.element_declared_short_name(sib) { + names.entry(sn.to_string()).or_insert(sib); + } + } + names + }); + let existing = names + .get(new_name.as_str()) + .copied() + .filter(|x| x != e) + .map(|x| (x, false)) + .or_else(|| { + claimed + .get(&owner) + .and_then(|c| c.get(new_name.as_str())) + .copied() + .map(|x| (x, true)) + }); + let Some((other, by_batch)) = existing else { + claimed + .entry(owner) + .or_default() + .entry(new_name.clone()) + .or_insert(*e); + continue; + }; + let other_qn = r + .element_qualified_name(other) + .unwrap_or_else(|| format!("{other:?}")); + if !skip { + return Err(TransformError::NameTaken { + name: new_name.clone(), + existing: if by_batch { + format!("{other_qn} (renamed to `{new_name}` in the same batch)") + } else { + other_qn + }, + }); + } + let old_qn = r + .element_qualified_name(*e) + .unwrap_or_else(|| format!("{e:?}")); + out.insert( + i, + if by_batch { + format!( + "rename of `{old_qn}` to `{new_name}` skipped: the batch already renames its sibling `{other_qn}` to `{new_name}`" + ) + } else { + format!( + "rename of `{old_qn}` to `{new_name}` skipped: its sibling `{other_qn}` is already named `{new_name}`" + ) + }, + ); + } + Ok(out) + } + fn plan_rename(&mut self, e: ElementRef, new_name: &str) -> Result<(), TransformError> { if new_name.is_empty() { return Err(TransformError::InvalidName(new_name.to_string())); @@ -2132,7 +3615,7 @@ impl<'s> Planner<'s> { let old_qn = r .element_qualified_name(e) .ok_or(TransformError::NotDeclared(e))?; - let old_raw = decode_name(slice(self.src(decl_unit), decl_span)); + let old_raw = decode_name(slice(self.user_src(decl_unit, e)?, decl_span)); let spelled = spell_name(new_name); // Qualified-name strings follow `element_qualified_name`'s // convention (escape_name, reserved words unquoted) — the @@ -2154,8 +3637,12 @@ impl<'s> Planner<'s> { }); for site in self.session.resolved().references_to(e) { // Only sites written with the element's own name are - // respelled; alias/effective-name spellings stay. - if decode_name(slice(self.src(site.unit), site.name_span)) == old_raw { + // respelled; alias/effective-name spellings stay. (Sites + // are recorded in user units only.) + let Some(site_src) = self.src(site.unit) else { + continue; + }; + if decode_name(slice(site_src, site.name_span)) == old_raw { self.splices.push(Splice { unit: site.unit, start: site.name_span.start, @@ -2205,7 +3692,7 @@ impl<'s> Planner<'s> { let (unit, extent) = r .member_extent(e) .ok_or(TransformError::NoEditableValue(e))?; - let src = self.src(unit); + let src = self.user_src(unit, e)?; if !slice(src, extent).ends_with(';') { return Err(TransformError::NoEditableValue(e)); } @@ -2290,7 +3777,7 @@ impl<'s> Planner<'s> { .resolved() .member_extent(owner) .ok_or(TransformError::NoExtent(owner))?; - let src = self.src(unit); + let src = self.user_src(unit, owner)?; let indent = line_indent(src, extent.start); let child = child_indent(&indent, src); // The member arrives in top-level form; every line is @@ -2346,13 +3833,13 @@ impl<'s> Planner<'s> { fn plan_insert_top(&mut self, unit_name: &str, text: &str) -> Result<(), TransformError> { Self::validate_member_text(text)?; - let (unit, src_len) = self - .session - .units() - .find(|(_, n, _)| *n == unit_name) - .map(|(u, _, s)| (u, s.len() as u32)) + let unit = self + .unit_by_name(unit_name) .ok_or_else(|| TransformError::UnknownUnit(unit_name.to_string()))?; - let src = self.src(unit); + let src = self + .src(unit) + .ok_or_else(|| TransformError::UnknownUnit(unit_name.to_string()))?; + let src_len = src.len() as u32; let needs_newline = !src.is_empty() && !src.ends_with('\n'); // Top level: no base indent, but internal levels still convert // to the unit's own indent style. @@ -2372,7 +3859,8 @@ impl<'s> Planner<'s> { } fn plan_add_unit(&mut self, name: &str) -> Result<(), TransformError> { - if name.is_empty() { + // A blank name would open a unit the session could not emit. + if name.trim().is_empty() { return Err(TransformError::InvalidName(name.to_string())); } if self.session.units().any(|(_, n, _)| n == name) @@ -2386,7 +3874,27 @@ impl<'s> Planner<'s> { fn plan_remove(&mut self, e: ElementRef) -> Result<(), TransformError> { let r = self.session.resolved(); - let (unit, extent) = r.member_extent(e).ok_or(TransformError::NoExtent(e))?; + let (unit, mut extent) = r.member_extent(e).ok_or(TransformError::NoExtent(e))?; + if r.element_type(e) == "SuccessionAsUsage" { + // A leading `then` and its following declaration share an outer + // source extent. Removing the relationship must retain the action. + let source = slice(self.user_src(unit, e)?, extent); + let parsed = parse_source(source); + if let Some(member) = parsed.unit.members.first().filter(|m| m.leading_then) { + let (tokens, _) = sysmlv2_syntax::lexer::tokenize(source); + if let Some(token) = tokens.iter().find(|t| { + t.kind == TokenKind::Ident + && &source[t.span.start as usize..t.span.end as usize] == "then" + }) { + let end = member + .leading_then_multiplicity + .as_ref() + .map_or(token.span.end, |m| m.span.end); + extent = Span::new(extent.start + token.span.start, extent.start + end); + } + } + } + let r = self.session.resolved(); let element = r .element_qualified_name(e) .unwrap_or_else(|| format!("{:?}", e)); @@ -2424,27 +3932,9 @@ impl<'s> Planner<'s> { } // Consume surrounding whitespace: the line's leading indentation // and the trailing newline, when nothing else shares the line. - let src = self.src(unit); - let bytes = src.as_bytes(); - let mut start = extent.start; - while start > 0 && matches!(bytes[start as usize - 1], b' ' | b'\t') { - start -= 1; - } - let own_line = start == 0 || bytes[start as usize - 1] == b'\n'; - let mut end = extent.end; - if own_line { - while (end as usize) < bytes.len() && matches!(bytes[end as usize], b' ' | b'\t') { - end += 1; - } - if (end as usize) < bytes.len() && bytes[end as usize] == b'\n' { - end += 1; - } else { - start = extent.start; // keep the indentation if no newline followed - } - } else { - start = extent.start; - } - self.consumed.push((unit, Span::new(start, end))); + let cut = cut_whole_lines(self.user_src(unit, e)?, extent); + let (start, end) = (cut.start, cut.end); + self.consumed.push((unit, cut)); self.splices.push(Splice { unit, start, @@ -2498,13 +3988,14 @@ impl<'s> Planner<'s> { let old_qn = r.element_qualified_name(e); let old_raw = r .declaration_site(e) - .map(|(u, sp)| decode_name(slice(self.src(u), sp))); + .and_then(|(u, sp)| Some(decode_name(slice(self.src(u)?, sp)))); // The replacement arrives in top-level form; continuation lines // are re-spelled at the member's own depth (the splice starts // past the first line's indentation, which survives as-is). - let base = line_indent(self.src(unit), extent.start); - let text = reindent_member_text(text, &base, indent_unit(&base, self.src(unit))); + let src = self.user_src(unit, e)?; + let base = line_indent(src, extent.start); + let text = reindent_member_text(text, &base, indent_unit(&base, src)); // The whole extent is consumed: references inside it vanish with // the old text, and untouched-site verification skips them. @@ -2553,7 +4044,10 @@ impl<'s> Planner<'s> { if inside || already_consumed { continue; } - if decode_name(slice(self.src(site.unit), site.name_span)) == old_raw { + let Some(site_src) = self.src(site.unit) else { + continue; + }; + if decode_name(slice(site_src, site.name_span)) == old_raw { self.splices.push(Splice { unit: site.unit, start: site.name_span.start, @@ -2574,10 +4068,15 @@ impl<'s> Planner<'s> { } fn plan_retarget(&mut self, site: &RefSite, to: ElementRef) -> Result<(), TransformError> { + // The rewrite lands in the site's own unit, so that unit must be + // one the session owns: a site handed in against a library unit + // is refused rather than spliced into text that is read-only. + self.user_src(site.unit, site.owner)?; + // Spliced as reference text, so the re-resolvable spelling. let qn = self .session .resolved() - .element_qualified_name(to) + .element_reference_spelling(to) .ok_or(TransformError::AnonymousTarget(to))?; let last_len = qn.rsplit("::").next().unwrap_or(&qn).len() as u32; self.consumed.push((site.unit, site.span)); @@ -2667,51 +4166,27 @@ impl<'s> Planner<'s> { // Excise, with remove's whitespace discipline (no stranding // check — the text comes back; verification decides what broke). - let src = self.src(unit); + let src = self.user_src(unit, e)?; let member_text = slice(src, extent).to_string(); - let bytes = src.as_bytes(); - let mut cut_start = extent.start; - while cut_start > 0 && matches!(bytes[cut_start as usize - 1], b' ' | b'\t') { - cut_start -= 1; - } - let own_line = cut_start == 0 || bytes[cut_start as usize - 1] == b'\n'; - let mut cut_end = extent.end; - if own_line { - while (cut_end as usize) < bytes.len() - && matches!(bytes[cut_end as usize], b' ' | b'\t') - { - cut_end += 1; - } - if (cut_end as usize) < bytes.len() && bytes[cut_end as usize] == b'\n' { - cut_end += 1; - } else { - cut_start = extent.start; - } - } else { - cut_start = extent.start; - } - self.consumed.push((unit, Span::new(cut_start, cut_end))); + let cut = cut_whole_lines(src, extent); + self.consumed.push((unit, cut)); self.splices.push(Splice { unit, - start: cut_start, - end: cut_end, + start: cut.start, + end: cut.end, text: String::new(), expects: Vec::new(), }); // Insert at the destination slot (plan_insert's composition for // the append shapes; before-a-sibling lands at its line start). - let dsrc = self.src(dunit); + let dsrc = self.user_src(dunit, new_owner)?; let indent = line_indent(dsrc, dextent.start); let child = child_indent(&indent, dsrc); let slot = index.unwrap_or(usize::MAX); let (ins_start, ins_end, ins_text) = if slot < sibs.len() { let sib = sibs[slot]; - let dbytes = dsrc.as_bytes(); - let mut at = sib.start; - while at > 0 && matches!(dbytes[at as usize - 1], b' ' | b'\t') { - at -= 1; - } + let at = indent_start(dsrc.as_bytes(), sib.start); (at, at, format!("{child}{member_text}\n")) } else { let last = dextent.end - 1; @@ -2770,6 +4245,262 @@ impl<'s> Planner<'s> { /// bookkeeping (correspondence per moved member, expectation per /// generated target, carried-site re-verification, strict /// unresolved net, projection subject). + fn plan_hoist( + &mut self, + e: ElementRef, + unit_name: &str, + new_name: Option<&str>, + ) -> Result<(), TransformError> { + let unit_offset = self.session.unit_offset; + let dunit = self + .unit_by_name(unit_name) + .ok_or_else(|| TransformError::UnknownUnit(unit_name.to_string()))?; + if let Some(new) = new_name { + if new.is_empty() { + return Err(TransformError::InvalidName(new.to_string())); + } + } + let (unit, extent) = self + .session + .resolved() + .member_extent(e) + .ok_or(TransformError::NoExtent(e))?; + if unit < unit_offset { + return Err(TransformError::NotDeclared(e)); + } + let source: String = self.user_src(unit, e)?.to_string(); + let r = self.session.resolved(); + let old_qn = r + .element_qualified_name(e) + .ok_or(TransformError::NotDeclared(e))?; + let name = r + .element_name(e) + .ok_or(TransformError::NotDeclared(e))? + .to_string(); + let top = new_name.map_or(name, str::to_string); + self.correspondence.push((old_qn, escape_name(&top))); + let decl = r.declaration_site(e).map(|(_, sp)| sp); + // Every reference written inside the moved text. Those whose + // target lies outside the moved subtree and that were written as + // a name resolved from here (a plain lexical reference or an + // import target) are respelled by the target's reference + // spelling, so the text no longer depends on its old surroundings. + // Every site is verified at its destination. + struct Rewrite { + start: u32, + end: u32, + text: String, + } + let mut rewrites: Vec = Vec::new(); + let mut sites: Vec<(u32, u32, Option, Option)> = Vec::new(); + let all: Vec = r + .reference_sites() + .iter() + .filter(|s| s.unit == unit && s.span.start >= extent.start && s.span.end <= extent.end) + .cloned() + .collect(); + for site in &all { + let mut inside = false; + let mut cur = Some(site.target); + while let Some(c) = cur { + if c == e { + inside = true; + break; + } + cur = r.owner(c); + } + let qn = r.element_qualified_name(site.target); + // A site that resolved only through imports the moved text + // owns keeps resolving through them: leave it as written. + let through_own_imports = !site.via_imports.is_empty() + && site.via_imports.iter().all(|(imp, _)| { + r.import_extent(*imp).is_some_and(|(u, sp)| { + u == unit && sp.start >= extent.start && sp.end <= extent.end + }) + }); + let respell = !inside + && !through_own_imports + && site.chain_root.is_none() + && (site.plain || site.kind.starts_with("imported")); + let mut rewritten = None; + // The package names itself as the first segment (`Lib::K` + // inside `Lib`): under the new name the old one would denote + // the colliding root element. Qualified through the owner + // (`R::Lib::K`) it keeps resolving through the root's alias. + let names_itself = site.target == e && site.span.start == site.name_span.start; + if let (Some(new), true) = (new_name, names_itself) { + rewritten = Some(rewrites.len()); + rewrites.push(Rewrite { + start: site.name_span.start, + end: site.name_span.end, + text: spell_name(new), + }); + } else if respell { + if let Some(mut spelling) = r.element_reference_spelling(site.target) { + let written = &source[site.span.start as usize..site.span.end as usize]; + // A reference written from the global root stays + // global: the prefix escapes a nearer member of the + // same name, and the moved text keeps those scopes. + // The same prefix is added when the spelling's first + // segment would not denote the target's root ancestor + // from where the text sits: a member of the moved text + // (or of the vanishing owner) shadows it. + let shadowed = !written.starts_with("$::") && { + let first = sysmlv2_syntax::name::split_canonical(&spelling) + .into_iter() + .next() + .unwrap_or_default(); + let probe = sysmlv2_syntax::ast::QualifiedName { + is_global: false, + segments: vec![sysmlv2_syntax::ast::Name { + value: first.clone(), + span: Span::default(), + }], + span: Span::default(), + }; + // The root-level element the spelling starts from. + let top = r.resolve_qualified(&spell_name(&first)); + top.is_none() + || r.resolve_in_excluding(site.scope, &probe, site.exclude) != top + }; + if written.starts_with("$::") || shadowed { + spelling = format!("$::{spelling}"); + } + if spelling != written { + rewritten = Some(rewrites.len()); + rewrites.push(Rewrite { + start: site.span.start, + end: site.span.end, + text: spelling, + }); + } + } + } + sites.push((site.name_span.start, site.name_span.end, qn, rewritten)); + } + if let (Some(new), Some(decl)) = (new_name, decl) { + rewrites.push(Rewrite { + start: decl.start, + end: decl.end, + text: spell_name(new), + }); + } + self.report_unused_imports = true; + // Sites index `rewrites` by push order; the text is assembled in + // source order through this permutation. + let mut order: Vec = (0..rewrites.len()).collect(); + order.sort_by_key(|&i| (rewrites[i].start, rewrites[i].end)); + for pair in order.windows(2) { + let (a, b) = (&rewrites[pair[0]], &rewrites[pair[1]]); + if b.start < a.end { + return Err(TransformError::OverlappingEdits { + unit, + at: Span::new(b.start, b.end), + }); + } + } + // A site inside a respelled reference (its qualifier segments) is + // re-derived from the new spelling; the respelled site's own + // expectation covers it. + let sites = sites.into_iter().filter(|(ns, ne, _, rw)| { + rw.is_some() || !rewrites.iter().any(|w| *ns < w.end && w.start < *ne) + }); + // The moved text: the member's extent with the rewrites applied + // and the member's own indentation removed from every line. + let src = self.user_src(unit, e)?; + let indent = line_indent(src, extent.start); + let raw = &src[extent.start as usize..extent.end as usize]; + // Position map from raw offsets (relative to the extent) to the + // rewritten text, then through the dedent. + let mut rewritten = String::with_capacity(raw.len()); + let mut cursor = 0u32; + let mut deltas: Vec<(u32, i64)> = Vec::new(); // (raw offset after which delta applies, cumulative delta) + let mut delta = 0i64; + for w in order.iter().map(|&i| &rewrites[i]) { + let (ws, we) = (w.start - extent.start, w.end - extent.start); + rewritten.push_str(&raw[cursor as usize..ws as usize]); + rewritten.push_str(&w.text); + delta += w.text.len() as i64 - (we - ws) as i64; + deltas.push((we, delta)); + cursor = we; + } + rewritten.push_str(&raw[cursor as usize..]); + let map_rewrite = |pos: u32| -> u32 { + let d = deltas + .iter() + .rev() + .find(|(after, _)| *after <= pos) + .map_or(0, |(_, d)| *d); + (pos as i64 + d) as u32 + }; + let (dedented, lines) = dedent_lines(&rewritten, &indent); + let map_dedent = |pos: u32| -> u32 { + let (old_start, new_start) = lines + .iter() + .rev() + .find(|(old_start, _)| *old_start <= pos) + .copied() + .unwrap_or((0, 0)); + new_start + (pos - old_start) + }; + let expects = sites.map(|(ns, ne, qn, rw)| match rw { + Some(i) => { + let w = &rewrites[i]; + // The spelled last segment (a quoted one may hold `::`). + let last_len = sysmlv2_syntax::name::split_canonical(&w.text) + .pop() + .map_or(w.text.len(), |seg| { + sysmlv2_syntax::name::spell_name_in(None, &seg).len() + }) as u32; + let start = map_rewrite(w.start - extent.start) + w.text.len() as u32 - last_len; + (map_dedent(start), last_len, qn) + } + None => { + let start = map_rewrite(ns - extent.start); + (map_dedent(start), ne - ns, qn) + } + }); + // Cut the member from its unit, whole lines when it stands alone. + let cut = cut_whole_lines(src, extent); + self.consumed.push((unit, cut)); + self.splices.push(Splice { + unit, + start: cut.start, + end: cut.end, + text: String::new(), + expects: Vec::new(), + }); + // Append at the destination's top level. + let dsrc = self + .src(dunit) + .ok_or_else(|| TransformError::UnknownUnit(unit_name.to_string()))?; + let at = dsrc.len() as u32; + let ins_text = if dsrc.is_empty() || dsrc.ends_with('\n') { + format!("{dedented}\n") + } else { + format!("\n{dedented}\n") + }; + let prefix = ins_text + .find(&dedented) + .expect("insert text is composed around the member text") as u32; + self.moved_expects.push(MovedExpects { + unit: dunit, + at, + text: ins_text.clone(), + sites: expects + .map(|(off, len, qn)| (off + prefix, len, qn)) + .collect(), + }); + self.splices.push(Splice { + unit: dunit, + start: at, + end: at, + text: ins_text, + expects: Vec::new(), + }); + Ok(()) + } + fn plan_extract( &mut self, usage: ElementRef, @@ -2793,7 +4524,7 @@ impl<'s> Planner<'s> { }; let owner = r.owner(usage).ok_or(TransformError::NotDeclared(usage))?; for sib in r.owned_members(owner) { - if r.element_effective_name(sib).as_deref() == Some(def_name.as_str()) { + if r.element_lookup_name(sib).as_deref() == Some(def_name.as_str()) { return Err(TransformError::NameTaken { existing: r .element_qualified_name(sib) @@ -2851,7 +4582,7 @@ impl<'s> Planner<'s> { .into_iter() .filter_map(|m| { let qn = r.element_qualified_name(m)?; - let name = r.element_effective_name(m)?; + let name = r.element_lookup_name(m)?; Some((qn, escape_name(&name))) }) .collect(); @@ -2878,7 +4609,7 @@ impl<'s> Planner<'s> { let spelled = spell_name(&def_name); let (cut, ins_at, interior_text, indent) = { - let src = self.src(unit); + let src = self.user_src(unit, usage)?; let bytes = src.as_bytes(); // Body removal starts at the whitespace before the opening // brace (the brace is the byte before the interior). @@ -2889,10 +4620,7 @@ impl<'s> Planner<'s> { cut -= 1; } // The definition inserts at the usage's line start. - let mut ins_at = extent.start; - while ins_at > 0 && matches!(bytes[ins_at as usize - 1], b' ' | b'\t') { - ins_at -= 1; - } + let ins_at = indent_start(bytes, extent.start); ( (cut, slice(src, Span::new(cut, brace)).to_string()), ins_at, @@ -3037,7 +4765,7 @@ impl<'s> Planner<'s> { .into_iter() .filter_map(|m| { let qn = r.element_qualified_name(m)?; - let name = r.element_effective_name(m)?; + let name = r.element_lookup_name(m)?; Some((qn, escape_name(&name))) }) .collect(); @@ -3066,16 +4794,15 @@ impl<'s> Planner<'s> { }; // ---- text geometry ---- - let def_interior_text = elig - .body_interior - .map(|sp| slice(self.src(def_unit), sp).to_string()); + let def_src = self.user_src(def_unit, definition)?; + let def_interior_text = elig.body_interior.map(|sp| slice(def_src, sp).to_string()); // The whitespace the definition wrote between its header and // opening brace — reused when the usage grows a body, so // `inline(extract(usage))` restores the original spelling // byte-exactly whatever its brace style was. let def_pre_brace_ws: String = match elig.body_interior { Some(interior) => { - let src = self.src(def_unit); + let src = self.user_src(def_unit, definition)?; let bytes = src.as_bytes(); let brace = interior.start - 1; let mut ws = brace; @@ -3087,31 +4814,9 @@ impl<'s> Planner<'s> { None => String::new(), }; // Definition removal, with remove's whitespace discipline. - let (def_cut_start, def_cut_end) = { - let src = self.src(def_unit); - let bytes = src.as_bytes(); - let extent = elig.def_extent; - let mut start = extent.start; - while start > 0 && matches!(bytes[start as usize - 1], b' ' | b'\t') { - start -= 1; - } - let own_line = start == 0 || bytes[start as usize - 1] == b'\n'; - let mut end = extent.end; - if own_line { - while (end as usize) < bytes.len() && matches!(bytes[end as usize], b' ' | b'\t') { - end += 1; - } - if (end as usize) < bytes.len() && bytes[end as usize] == b'\n' { - end += 1; - } else { - start = extent.start; - } - } else { - start = extent.start; - } - (start, end) - }; - let usage_text = slice(self.src(u_unit), u_extent).to_string(); + let def_cut = cut_whole_lines(self.user_src(def_unit, definition)?, elig.def_extent); + let (def_cut_start, def_cut_end) = (def_cut.start, def_cut.end); + let usage_text = slice(self.user_src(u_unit, usage)?, u_extent).to_string(); let usage_interior_rel = eligibility::body_interior(&usage_text); // 1. The usage's typing entry: retargeted to the definition's @@ -3177,7 +4882,7 @@ impl<'s> Planner<'s> { unit: u_unit, at, text: ins.clone(), - sites: inner_sites.clone(), + sites: inner_sites, }); } self.splices.push(Splice { @@ -3319,6 +5024,12 @@ impl<'s> Planner<'s> { // Apply the splices to copies of the sources, tracking the new // position of every splice. let mut new_sources = self.session.sources.clone(); + // Born units join empty, after the existing ones — indices of + // existing units (and every splice) are untouched, and a splice + // may already write into a born unit. + for name in &self.new_units { + new_sources.push((name.clone(), String::new())); + } let mut new_positions: Vec = Vec::with_capacity(self.splices.len()); { let mut per_unit: HashMap> = HashMap::new(); @@ -3328,7 +5039,11 @@ impl<'s> Planner<'s> { new_positions.resize(self.splices.len(), 0); for (unit, idxs) in per_unit { let local = unit - self.session.unit_offset; - let src = &self.session.sources[local].1; + let src: &str = self + .session + .sources + .get(local) + .map_or("", |(_, s)| s.as_str()); let mut out = String::with_capacity(src.len()); let mut cursor = 0usize; for &i in &idxs { @@ -3342,12 +5057,6 @@ impl<'s> Planner<'s> { new_sources[local].1 = out; } } - // Born units join empty, after the existing ones — indices of - // existing units (and every splice) are untouched. - for name in &self.new_units { - new_sources.push((name.clone(), String::new())); - } - // Reparse + rebuild (rollback = return before swapping state). let (new_model, mut new_resolved, unit_offset) = rebuild(&new_sources, self.session.lib.as_ref()).map_err(|e| match e { @@ -3409,7 +5118,13 @@ impl<'s> Planner<'s> { let (line, col) = line_col(text, pos as usize); format!("{name}:{line}:{col}") } - None => format!("library unit {unit}"), + None => match unit + .checked_sub(pre_offset + pre_sources.len()) + .and_then(|k| self.new_units.get(k)) + { + Some(name) => format!("{name} (new)"), + None => format!("library unit {unit}"), + }, } }; let spelled_at = |unit: usize, span: Span| -> &str { @@ -3453,7 +5168,9 @@ impl<'s> Planner<'s> { s.name_span.end ); if let Some(q) = expected.as_deref() { - msg.push_str(&format!(" (expected target: `{q}`)")); + msg.push_str(" (expected target: `"); + msg.push_str(q); + msg.push_str("`)"); } broken.push(msg); } @@ -3551,7 +5268,9 @@ impl<'s> Planner<'s> { place(unit, me.at) ); if let Some(qn) = qn { - msg.push_str(&format!(" (expected target: `{}`)", map_qn(qn))); + msg.push_str(" (expected target: `"); + msg.push_str(&map_qn(qn)); + msg.push_str("`)"); } broken.push(msg); } @@ -3619,7 +5338,10 @@ impl<'s> Planner<'s> { let mut fresh: Vec = Vec::new(); for unit in touched { let local = unit - self.session.unit_offset; - let (unit_name, pre_text) = &self.session.sources[local]; + // A born unit had no text before the batch. + let Some((unit_name, pre_text)) = self.session.sources.get(local) else { + continue; + }; let pre_diagnostics = syntax_validation(unit_name, pre_text); let mut pre_counts: HashMap = HashMap::new(); for diagnostic in &pre_diagnostics { @@ -3655,7 +5377,7 @@ impl<'s> Planner<'s> { } } // Relocated subjects keep their effective-member projection - // (M29a0's authoritative structural gate): pre-commit rows under + // (the authoritative structural gate): pre-commit rows under // the correspondence map must equal prospective rows exactly. for qn in self.projection_subjects.clone() { let Some(pre_e) = self.session.resolved.resolve_qualified(&qn) else { @@ -3716,7 +5438,10 @@ impl<'s> Planner<'s> { } } } - let mut report = CommitReport::default(); + let mut report = CommitReport { + findings: std::mem::take(&mut self.findings), + ..CommitReport::default() + }; for (qn, old_id) in old_qn_ids { if let Some(&new_id) = new_ids.get(&map_qn(&qn)) { if new_id != old_id { @@ -3781,9 +5506,7 @@ impl<'s> Planner<'s> { .splices .iter() .map(|s| AppliedSplice { - unit: self.session.sources[s.unit - self.session.unit_offset] - .0 - .clone(), + unit: self.unit_name(s.unit), start: s.start, end: s.end, text: s.text.clone(), @@ -3805,8 +5528,16 @@ impl<'s> Planner<'s> { // Success — swap the session to the new state. if !dry_run { self.session.sources = new_sources; + apply_explicit_ids( + &mut new_resolved, + &mut self.session.explicit_ids, + self.session.binds_ids, + &mut self.session.warnings, + ); self.session.model = new_model; + let policy = self.session.resolved.closure_policy(); self.session.resolved = new_resolved; + self.session.resolved.set_closure_policy(policy); } Ok(report) } @@ -3883,7 +5614,10 @@ fn doc_unit_name(root_name: Option<&str>, index: usize) -> String { && base .chars() .all(|c| c != ':' && c != '*' && c != '?' && c != '"'); - if safe && (base.ends_with(".sysml") || base.ends_with(".kerml")) { + let model_file = Path::new(&base) + .extension() + .is_some_and(|e| e.eq_ignore_ascii_case("sysml") || e.eq_ignore_ascii_case("kerml")); + if safe && model_file { return base; } } @@ -3916,7 +5650,7 @@ fn child_indent(indent: &str, src: &str) -> String { } // --------------------------------------------------------------------------- -// M29a0 planner-internal gates: multi-expectation splices, relocation +// Planner-internal gates: multi-expectation splices, relocation // discipline (new unresolved references are fatal), rollback. // --------------------------------------------------------------------------- @@ -4191,3 +5925,45 @@ mod relocation_tests { assert!(s.source(s.unit_offset).unwrap().contains("part def Alpha;")); } } + +#[cfg(test)] +mod minimize_tests { + use super::overlapping_candidates; + + #[test] + fn disjoint_ranges_all_survive() { + let ranges = [(1, 0, 5), (1, 5, 9), (1, 20, 24), (2, 0, 4)]; + assert!(overlapping_candidates(&ranges).is_empty()); + } + + #[test] + fn a_nested_range_is_reported() { + // The second range sits inside the first: applying both in one + // forward sweep would slice backwards. + let ranges = [(1, 0, 12), (1, 4, 8), (1, 14, 18)]; + assert_eq!(overlapping_candidates(&ranges), vec![1]); + } + + #[test] + fn a_straddling_range_is_reported() { + let ranges = [(1, 0, 12), (1, 8, 20)]; + assert_eq!(overlapping_candidates(&ranges), vec![1]); + } + + #[test] + fn a_whole_overlapping_run_is_reported_against_the_first_kept_range() { + // The third range clears the second but still reaches into the + // first, which is the one that will be applied. + let ranges = [(1, 0, 30), (1, 4, 8), (1, 10, 40), (1, 40, 44)]; + assert_eq!(overlapping_candidates(&ranges), vec![1, 2]); + } + + #[test] + fn ranges_in_different_units_never_overlap() { + let ranges = [(1, 0, 30), (2, 4, 8), (3, 4, 8)]; + assert!(overlapping_candidates(&ranges).is_empty()); + } +} + +#[cfg(test)] +mod unused_imports_tests; diff --git a/crates/sysmlv2-transform/src/projection.rs b/crates/sysmlv2-transform/src/projection.rs index e11cbbf..c63d1ee 100644 --- a/crates/sysmlv2-transform/src/projection.rs +++ b/crates/sysmlv2-transform/src/projection.rs @@ -14,10 +14,11 @@ //! equal `unbound`/`undecided` results prove nothing; this projection //! is the comparison made authoritative. //! -//! The engine lives on [`Projector`], which borrows any resolved model -//! plus its sources — the commit pipeline projects the *prospective* -//! state (rebuilt but not yet swapped in) exactly like the session's -//! own; [`Session::effective_member_projection`] is the public wrapper. +//! The engine lives on the crate-internal projector, which borrows any +//! resolved model plus its sources — the commit pipeline projects the +//! *prospective* state (rebuilt but not yet swapped in) exactly like +//! the session's own; [`Session::effective_member_projection`] is the +//! public wrapper. use std::collections::{HashMap, HashSet}; @@ -118,7 +119,7 @@ impl Projector<'_> { for base in layers { for m in self.resolved.owned_members(base) { let metaclass = self.resolved.element_type(m); - let name = self.resolved.element_effective_name(m); + let name = self.resolved.element_lookup_name(m); if name .as_ref() .is_some_and(|n| !seen.insert((n.clone(), metaclass))) diff --git a/crates/sysmlv2-transform/src/unused_imports_tests.rs b/crates/sysmlv2-transform/src/unused_imports_tests.rs new file mode 100644 index 0000000..761d95a --- /dev/null +++ b/crates/sysmlv2-transform/src/unused_imports_tests.rs @@ -0,0 +1,227 @@ +//! Text-stage differential tests; graph parity is tested in the model crate. +use super::*; +fn legacy(resolved: &mut ResolvedModel, texts: &[(usize, String)]) -> Vec<(usize, Span)> { + let candidates = resolved.unused_private_imports(); + let mut out = Vec::new(); + for (_, target, unit, span) in candidates { + let Some((_, text)) = texts.iter().find(|(i, _)| *i == unit) else { + continue; // library unit — never reported + }; + let names = resolved.namespace_member_names(target); + let mentioned = names + .iter() + .any(|name| !name.is_empty() && mentions_outside(text, name, span)); + if !mentioned { + out.push((unit, span)); + } + } + out +} + +fn mentions_outside(text: &str, name: &str, skip: Span) -> bool { + let bytes = text.as_bytes(); + let is_word = |b: u8| b.is_ascii_alphanumeric() || b == b'_'; + let mut from = 0; + while let Some(i) = text[from..].find(name) { + let start = from + i; + let end = start + name.len(); + from = start + name.chars().next().unwrap().len_utf8(); + if start >= skip.start as usize && end <= skip.end as usize { + continue; + } + let left_ok = start == 0 || !is_word(bytes[start - 1]); + let right_ok = end >= bytes.len() || !is_word(bytes[end]); + if left_ok && right_ok { + return true; + } + } + false +} + +fn compare(sources: &[(&str, &str)]) { + let mut model = Model::new(); + let texts: Vec<_> = sources + .iter() + .enumerate() + .map(|(i, (name, text))| { + let unit = model.add_source(*name, text); + assert!( + unit.diagnostics.is_empty(), + "{name}: {:?}", + unit.diagnostics + ); + (i, text.to_string()) + }) + .collect(); + let mut resolved = ResolvedModel::build(&model); + let expected = legacy(&mut resolved, &texts); + assert_eq!(unused_private_imports_with(&mut resolved, &texts), expected); + assert_eq!( + unused_private_imports_with(&mut resolved, &texts), + expected, + "repeated call" + ); + assert!(unused_private_imports_with(&mut resolved, &[]).is_empty()); +} + +#[test] +fn text_index_preserves_conservative_import_contract() { + for body in [ + "part def Other;", + "part x : Leaf;", + "part x : Defs::Leaf;", + "// Leaf in a comment", + "/* Leaf */", + "part 'Leaf';", + "part LeafSuffix;", + "part _Leaf;", + "part PrefixLeaf;", + "alias Alias for Defs::Leaf; part x : Alias;", + "package Nested { private import Defs::Leaf; part x : Leaf; }", + "private import Defs::*;", + "public import Defs::*;", + "protected import Defs::*;", + "private import Missing::*;", + "part 'é';", + "/* é */", + "/* 😀 */", + ] { + for import in [ + "private import Defs::*;", + "private import Defs::Leaf;", + "private import Defs::**;", + ] { + let source = format!("package User {{ {import} {body}\n }}"); + compare(&[ + ( + "defs.sysml", + "package Defs { part def Leaf; part def 'é'; part def '😀'; }", + ), + ("user.sysml", &source), + ]); + } + } + compare(&[ + ("defs.kerml", "package Defs { class Leaf; }"), + ("user.kerml", "package User { import Defs::*; }"), + ]); + compare(&[ + ( + "defs.sysml", + "package Defs { metadata def M; #M part def Leaf; part def Other; }", + ), + ( + "user.sysml", + "package User { private import Defs::*[@Defs::M]; part x : Leaf; }", + ), + ]); +} + +#[test] +fn text_extent_handles_overlap_boundaries_and_unicode() { + assert_eq!(mention_extent("é", "é"), Some((0, 2))); + assert_eq!(mention_extent("😀 😀", "😀"), Some((0, 9))); + assert_eq!(mention_extent("ééé", "éé"), Some((0, 6))); + assert_eq!(mention_extent("xName Name_ Name", "Name"), Some((12, 16))); + assert_eq!(mention_extent("anything", ""), None); +} + +#[test] +fn imports_are_recomputed_after_edits() { + let mut session = Session::from_sources(vec![ + ( + "defs.sysml".into(), + "package Defs { part def Leaf; }".into(), + ), + ( + "user.sysml".into(), + "package User { private import Defs::*; part p; }".into(), + ), + ]) + .unwrap(); + let before = session.unused_private_imports(); + assert_eq!(before.len(), 1); + let p = session.resolved().resolve_qualified("User::p").unwrap(); + let mut edit = session.edit(); + edit.replace_member(p, "part p : Leaf;"); + edit.commit().unwrap(); + assert!(session.unused_private_imports().is_empty()); + let p = session.resolved().resolve_qualified("User::p").unwrap(); + let mut edit = session.edit(); + edit.replace_member(p, "part p;"); + edit.commit().unwrap(); + assert_eq!(session.unused_private_imports(), before); +} + +#[test] +fn corpus_text_results_match_legacy_with_cold_and_replayed_libraries() { + let root = sysmlv2_testkit::workspace_root(); + let library = sysmlv2_testkit::library_dir(); + if !library.is_dir() { + return; + } + let mut base = Model::new(); + base.load_library_dir(&library).unwrap(); + sysmlv2_model::ambient::add_to(&mut base); + base.record_library_cache(); + ResolvedModel::build(&base); + let cache = base.take_recorded_library_cache().unwrap(); + let prepared = base.prepare_library().unwrap(); + let mut corpora = vec![ + "spec-refs/SysML-v2-Release/sysml/src".to_string(), + "spec-refs/apollo-11-sysml-v2".to_string(), + ]; + if let Ok(path) = std::env::var("SYSMLV2_IMPORT_CORPUS") { + corpora.push(path); + } + for corpus in corpora { + let path = root.join(&corpus); + if !path.is_dir() { + continue; + } + let mut paths = Vec::new(); + sysmlv2_testkit::collect_files(&path, &mut paths); + paths.sort(); + let mut prior = None; + for replay in 0..3 { + let mut model = Model::new(); + if replay == 2 { + prepared.clone().install(&mut model).unwrap(); + } else { + model.load_library_dir(&library).unwrap(); + sysmlv2_model::ambient::add_to(&mut model); + } + if replay == 1 { + model.set_library_cache(cache.clone()); + } + let offset = model.units().len(); + let texts: Vec<_> = paths + .iter() + .enumerate() + .map(|(i, p)| { + let source = std::fs::read_to_string(p).unwrap(); + model.add_source(p.display().to_string(), &source); + (offset + i, source) + }) + .collect(); + let mut resolved = ResolvedModel::build(&model); + let expected = legacy(&mut resolved, &texts); + let actual = unused_private_imports_with(&mut resolved, &texts); + assert_eq!(actual, expected, "{corpus}, replay={replay}"); + if corpus.contains("apollo") { + assert_eq!(actual.len(), 39); + } + sysmlv2_model::check::validate_model_with(&mut resolved, &model); + sysmlv2_model::check::validate_semantics_with(&mut resolved, &model); + assert_eq!( + unused_private_imports_with(&mut resolved, &texts), + actual, + "validation must preserve import provenance: {corpus}, replay={replay}" + ); + if let Some(prior) = prior { + assert_eq!(actual, prior, "cold/replay parity"); + } + prior = Some(actual); + } + } +} diff --git a/crates/sysmlv2-transform/tests/cbor_session.rs b/crates/sysmlv2-transform/tests/cbor_session.rs index 7b1096b..3af402c 100644 --- a/crates/sysmlv2-transform/tests/cbor_session.rs +++ b/crates/sysmlv2-transform/tests/cbor_session.rs @@ -25,8 +25,8 @@ fn cbor_lift_restores_the_original_layout() { assert_eq!(names(&via_cbor), vec!["t.sysml"]); assert_eq!(via_cbor.to_compact_json(), s.to_compact_json()); assert_eq!(via_cbor.to_compact_cbor(), s.to_compact_cbor()); - // JSON carries no unit structure: that path still renames to - // document-N and re-derives ids accordingly. + // JSON carries no unit structure: that path names the unit + // document-N (the document's ids ride as explicit ids). let via_json = Session::from_interchange_json(&s.to_compact_json()).expect("lifts from JSON"); assert_eq!(names(&via_json), vec!["document-1.sysml"]); } @@ -38,4 +38,64 @@ fn invalid_payload_is_a_session_error() { }; assert!(matches!(err, SessionError::Cbor(_))); assert!(err.to_string().contains("CBOR"), "{err}"); + // The codec's own message is reachable as the cause, so a host that + // walks the error chain sees what the payload got wrong. + let cause = std::error::Error::source(&err).expect("the codec error is the cause"); + assert!(cause.to_string().contains("payload"), "{cause}"); +} + +#[test] +fn a_codec_error_converts_into_a_session_error() { + // The conversion is what lets the session's own payload paths use + // `?` over the codec's result. + let codec = sysmlv2_cbor::from_compact_cbor_units(&[0xFF, 0x00]).expect_err("garbage bytes"); + let message = codec.to_string(); + let err = SessionError::from(codec); + assert!(matches!(err, SessionError::Cbor(_))); + assert!(err.to_string().ends_with(&message), "{err}"); +} + +#[test] +fn a_read_failure_carries_its_cause() { + let Err(err) = Session::open(&[std::path::PathBuf::from("no/such/directory/model.sysml")]) + else { + panic!("a missing file must not open a session"); + }; + assert!(matches!(err, SessionError::Io(_))); + assert!(std::error::Error::source(&err).is_some(), "{err}"); +} + +#[test] +fn blank_unit_names_are_refused_when_the_session_is_built() { + // The binary payloads key every unit by its name, so a blank one + // is refused up front instead of failing inside the emitter. + for name in ["", " ", "\t\n"] { + let Err(err) = Session::from_sources(vec![(name.into(), "package P;".into())]) else { + panic!("a unit named {name:?} must not open a session"); + }; + assert!( + matches!(err, SessionError::InvalidUnitName(ref n) if n == name), + "{err:?}" + ); + assert!(err.to_string().contains("blank"), "{err}"); + } + let s = Session::from_sources(vec![("named.sysml".into(), "package P;".into())]) + .expect("a named unit opens"); + assert!(!s.to_compact_cbor().is_empty()); +} + +#[test] +fn blank_unit_names_are_refused_by_add_unit() { + let mut s = + Session::from_sources(vec![("t.sysml".into(), "package P;".into())]).expect("parses"); + for name in ["", " "] { + let mut edit = s.edit(); + edit.add_unit(name); + let err = edit.commit().expect_err("a blank unit name is refused"); + assert!( + matches!(err, sysmlv2_transform::TransformError::InvalidName(ref n) if n == name), + "{err:?}" + ); + } + assert_eq!(s.units().count(), 1); } diff --git a/crates/sysmlv2-transform/tests/eligibility.rs b/crates/sysmlv2-transform/tests/eligibility.rs index 60172d6..08e41b5 100644 --- a/crates/sysmlv2-transform/tests/eligibility.rs +++ b/crates/sysmlv2-transform/tests/eligibility.rs @@ -286,6 +286,24 @@ fn kerml_units_are_out_of_scope() { ); } +#[test] +fn a_unit_named_in_upper_case_is_the_same_dialect() { + // Unit names come from file systems that do not distinguish case, + // so the dialect a name spells is read without it: this text parses + // (it is KerML, which SysML would reject) and the gate refuses it + // for the same dialect the parse chose. + let mut s = Session::from_sources(vec![( + "m.KerML".into(), + "package K { feature f { feature g; } }".into(), + )]) + .expect("parses"); + let f = elem(&mut s, "K::f"); + assert_eq!( + s.extract_definition_eligibility(f).unwrap_err(), + ExtractRefusal::UnsupportedDialect + ); +} + #[test] fn a_definition_is_not_an_extractable_usage() { let src = "package P { part def A { attribute a; } }"; diff --git a/crates/sysmlv2-transform/tests/json_path.rs b/crates/sysmlv2-transform/tests/json_path.rs index 5ac3d3c..b1ebd16 100644 --- a/crates/sysmlv2-transform/tests/json_path.rs +++ b/crates/sysmlv2-transform/tests/json_path.rs @@ -100,21 +100,18 @@ fn edit_a_payload_and_reemit() { } #[test] -fn anonymous_root_gets_numbered_unit_and_ids_map() { +fn anonymous_root_gets_numbered_unit_and_keeps_its_ids() { // No Flexo naming: the lifted unit is document-1.sysml, so the - // ownership paths (and ids) differ from the original m.sysml - // emission — id_map_from names every element's move. + // ownership paths derive different ids from the original m.sysml + // emission — and the session keeps the document's ids as explicit + // ids, so nothing moves and id_map_from has nothing to report. let input = demo_json_unstamped(); let mut s = Session::from_interchange_json(&input).expect("lifts"); assert_eq!(s.units().next().unwrap().1, "document-1.sysml"); + assert!(s.has_explicit_ids()); let out = s.to_compact_json(); - assert_ne!(ids(&input), ids(&out)); - let map = s.id_map_from(&input); - // Every *named* element maps old -> new. - assert!(!map.is_empty()); - for (old, _) in &map { - assert!(ids(&input).contains(&old.to_string())); - } + assert_eq!(ids(&input), ids(&out)); + assert!(s.id_map_from(&input).is_empty()); } fn demo_json_unstamped() -> Value { diff --git a/crates/sysmlv2-transform/tests/library_subjects.rs b/crates/sysmlv2-transform/tests/library_subjects.rs new file mode 100644 index 0000000..f02b696 --- /dev/null +++ b/crates/sysmlv2-transform/tests/library_subjects.rs @@ -0,0 +1,258 @@ +//! Edits whose subject is a library element are refused with +//! `TransformError::NotDeclared` before any text is read: library units +//! are resolution targets only, never edited, and a host that hands the +//! engine any handle it holds (a rename with the cursor on a library +//! type, say) gets a refusal instead of a fault. Every operation kind +//! is driven through the public edit API, as a dry run and as a commit, +//! and the user text must survive both untouched. + +use sysmlv2_transform::eligibility::{ExtractRefusal, InlineRefusal}; +use sysmlv2_transform::{EditBuilder, ElementRef, Library, Session, TransformError}; + +const LIB: &str = "package Lib { + part def LibDef { + attribute mass = 1; + } + part libPart : LibDef; +} +"; + +const USER: &str = "package P { + part def A :> Lib::LibDef; + part p : Lib::LibDef; +} +"; + +fn session() -> Session { + Session::from_sources_with_library( + vec![("user.sysml".into(), USER.into())], + Some(Library::sources(vec![("lib.sysml".into(), LIB.into())])), + ) + .expect("parses") +} + +fn elem(s: &mut Session, qn: &str) -> ElementRef { + s.resolved() + .resolve_qualified(qn) + .unwrap_or_else(|| panic!("`{qn}` resolves")) +} + +fn user_text(s: &Session) -> String { + s.units().next().expect("one user unit").2.to_string() +} + +/// Plans the batch twice — as a dry run and as a commit — and requires +/// the same refusal from both, with the user text untouched. +fn refused(s: &mut Session, plan: impl Fn(&mut EditBuilder<'_>)) -> TransformError { + let before = user_text(s); + let mut dry = s.edit(); + plan(&mut dry); + let dry_err = dry.check().expect_err("the dry run refuses"); + let mut edit = s.edit(); + plan(&mut edit); + let err = edit.commit().expect_err("the commit refuses"); + assert_eq!(dry_err.to_string(), err.to_string()); + assert_eq!(user_text(s), before, "the session is untouched"); + err +} + +fn assert_not_declared(err: &TransformError, subject: ElementRef) { + assert!( + matches!(err, TransformError::NotDeclared(e) if *e == subject), + "expected NotDeclared({subject:?}), got {err:?}" + ); +} + +#[test] +fn rename_of_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + assert!(s.resolved().is_library_element(def)); + let err = refused(&mut s, |e| { + e.rename(def, "Renamed"); + }); + assert_not_declared(&err, def); +} + +#[test] +fn set_feature_value_on_a_library_element_is_refused() { + let mut s = session(); + let mass = elem(&mut s, "Lib::LibDef::mass"); + let err = refused(&mut s, |e| { + e.set_feature_value(mass, "2"); + }); + assert_not_declared(&err, mass); +} + +#[test] +fn set_feature_type_on_a_library_element_is_refused() { + let mut s = session(); + let mass = elem(&mut s, "Lib::LibDef::mass"); + let err = refused(&mut s, |e| { + e.set_feature_type(mass, "P::A"); + }); + assert_not_declared(&err, mass); +} + +#[test] +fn insert_member_into_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let err = refused(&mut s, |e| { + e.insert_member(def, "attribute added;"); + }); + assert_not_declared(&err, def); +} + +#[test] +fn remove_of_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let err = refused(&mut s, |e| { + e.remove(def); + }); + assert_not_declared(&err, def); +} + +#[test] +fn replace_member_of_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let err = refused(&mut s, |e| { + e.replace_member(def, "part def LibDef;"); + }); + assert_not_declared(&err, def); +} + +#[test] +fn retarget_of_a_site_owned_by_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let a = elem(&mut s, "P::A"); + // Sites are recorded in user units only, so a library site is one a + // host re-homed: the user site's record placed on the library + // element, in the library unit. + let mut site = s + .resolved() + .references_to(def) + .into_iter() + .next() + .expect("`Lib::LibDef` is referenced"); + site.owner = def; + site.unit = 0; + assert!(s.source(site.unit).is_none(), "unit 0 is the library unit"); + let err = refused(&mut s, |e| { + e.retarget(site.clone(), a); + }); + assert_not_declared(&err, def); +} + +#[test] +fn retarget_of_a_site_in_a_library_unit_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let a = elem(&mut s, "P::A"); + // The owner is a user element, so only the site's unit says the + // rewrite would land in library text — the refusal must still come + // before the splice is planned. + let mut site = s + .resolved() + .references_to(def) + .into_iter() + .next() + .expect("`Lib::LibDef` is referenced"); + let owner = site.owner; + assert!(!s.resolved().is_library_element(owner)); + site.unit = 0; + assert!(s.source(site.unit).is_none(), "unit 0 is the library unit"); + let err = refused(&mut s, |e| { + e.retarget(site.clone(), a); + }); + assert_not_declared(&err, owner); +} + +#[test] +fn move_of_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let p = elem(&mut s, "P"); + let err = refused(&mut s, |e| { + e.move_member(def, p, None); + }); + assert_not_declared(&err, def); +} + +#[test] +fn move_into_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let a = elem(&mut s, "P::A"); + let err = refused(&mut s, |e| { + e.move_member(a, def, None); + }); + assert_not_declared(&err, def); +} + +#[test] +fn hoist_of_a_library_element_is_refused() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let err = refused(&mut s, |e| { + e.add_unit("side.sysml"); + e.hoist_to_unit(def, "side.sysml", None); + }); + assert_not_declared(&err, def); +} + +#[test] +fn extract_of_a_library_usage_is_refused_by_eligibility() { + let mut s = session(); + let usage = elem(&mut s, "Lib::libPart"); + let err = refused(&mut s, |e| { + e.extract_definition(usage, None); + }); + assert!( + matches!( + err, + TransformError::ExtractIneligible { + reason: ExtractRefusal::NotAUserElement + } + ), + "{err:?}" + ); +} + +#[test] +fn inline_of_a_library_definition_is_refused_by_eligibility() { + let mut s = session(); + let def = elem(&mut s, "Lib::LibDef"); + let err = refused(&mut s, |e| { + e.inline_definition(def); + }); + assert!( + matches!( + err, + TransformError::InlineIneligible { + reason: InlineRefusal::NotAUserElement + } + ), + "{err:?}" + ); +} + +#[test] +fn user_edits_beside_the_library_still_commit() { + let mut s = session(); + let a = elem(&mut s, "P::A"); + let mut edit = s.edit(); + edit.rename(a, "B"); + edit.commit().expect("a user element renames"); + assert_eq!( + user_text(&s), + "package P { + part def B :> Lib::LibDef; + part p : Lib::LibDef; +} +" + ); +} diff --git a/crates/sysmlv2-transform/tests/line_endings.rs b/crates/sysmlv2-transform/tests/line_endings.rs new file mode 100644 index 0000000..09439d4 --- /dev/null +++ b/crates/sysmlv2-transform/tests/line_endings.rs @@ -0,0 +1,91 @@ +//! Edits that take a member's whole line take it over either line +//! ending: text written with CRLF must not keep the blank line the +//! removed member stood on. + +use sysmlv2_transform::Session; + +fn session(src: &str) -> Session { + Session::from_sources(vec![("t.sysml".into(), src.into())]).expect("parses") +} + +fn text(s: &Session) -> String { + s.units().next().expect("one unit").2.to_string() +} + +#[test] +fn removing_a_member_from_crlf_text_leaves_no_blank_line() { + let mut s = session("package P {\r\n part def A;\r\n part def B;\r\n}\r\n"); + let a = s + .resolved() + .resolve_qualified("P::A") + .expect("`P::A` resolves"); + let mut edit = s.edit(); + edit.remove(a); + edit.commit().expect("removes"); + assert_eq!(text(&s), "package P {\r\n part def B;\r\n}\r\n"); +} + +#[test] +fn removing_a_member_from_lf_text_leaves_no_blank_line() { + let mut s = session("package P {\n part def A;\n part def B;\n}\n"); + let a = s + .resolved() + .resolve_qualified("P::A") + .expect("`P::A` resolves"); + let mut edit = s.edit(); + edit.remove(a); + edit.commit().expect("removes"); + assert_eq!(text(&s), "package P {\n part def B;\n}\n"); +} + +#[test] +fn moving_a_member_out_of_crlf_text_leaves_no_blank_line() { + let mut s = + session("package P {\r\n part def A;\r\n}\r\npackage Q {\r\n part def B;\r\n}\r\n"); + let a = s + .resolved() + .resolve_qualified("P::A") + .expect("`P::A` resolves"); + let q = s.resolved().resolve_qualified("Q").expect("`Q` resolves"); + let mut edit = s.edit(); + edit.move_member(a, q, None); + edit.commit().expect("moves"); + let out = text(&s); + assert!( + !out.contains("{\r\n\r\n") && !out.contains("{\n\n"), + "the vacated line is gone: {out:?}" + ); + assert!(out.contains("part def A;"), "{out:?}"); +} + +#[test] +fn a_member_sharing_its_line_keeps_the_line() { + // Nothing widens here: the line belongs to the sibling too, so only + // the member's own text goes — on either line ending. + for src in [ + "package P {\r\n part def A; part def B;\r\n}\r\n", + "package P {\n part def A; part def B;\n}\n", + ] { + let mut s = session(src); + let b = s + .resolved() + .resolve_qualified("P::B") + .expect("`P::B` resolves"); + let mut edit = s.edit(); + edit.remove(b); + edit.commit().expect("removes"); + assert_eq!(text(&s), src.replace("part def B;", "")); + } +} + +#[test] +fn a_member_with_no_line_break_after_it_keeps_its_indentation() { + // The last line has no break to take along, so only the member and + // the blanks after it go. + let mut s = session("package P {\n part def A;\n}\npart def B; "); + let b = s.resolved().resolve_qualified("B").expect("`B` resolves"); + let mut edit = s.edit(); + edit.remove(b); + edit.commit().expect("removes"); + assert_eq!(text(&s), "package P {\n part def A;\n}\n"); +} diff --git a/crates/sysmlv2-transform/tests/minimize.rs b/crates/sysmlv2-transform/tests/minimize.rs index 881e42f..9db36f7 100644 --- a/crates/sysmlv2-transform/tests/minimize.rs +++ b/crates/sysmlv2-transform/tests/minimize.rs @@ -150,6 +150,19 @@ fn minimize_is_idempotent_and_ids_stable() { /// spellings the lift prints are (ratcheted) eliminated. #[test] fn corpus_lift_minimize_gate() { + // Unoptimized lifter frames run to 128 KB per nesting level, and the + // deepest corpus model sits within bytes of the default test-thread + // stack. Give the gate its own generous stack so unrelated struct + // growth cannot trip it. + std::thread::Builder::new() + .stack_size(64 * 1024 * 1024) + .spawn(corpus_lift_minimize_gate_body) + .unwrap() + .join() + .unwrap(); +} + +fn corpus_lift_minimize_gate_body() { let files = sysmlv2_testkit::user_files(); assert!(files.len() > 100, "expected the corpus checkout"); let (mut minimized, mut respelled, mut reverted) = (0usize, 0usize, 0usize); diff --git a/crates/sysmlv2-transform/tests/parsed_sources.rs b/crates/sysmlv2-transform/tests/parsed_sources.rs new file mode 100644 index 0000000..658adb6 --- /dev/null +++ b/crates/sysmlv2-transform/tests/parsed_sources.rs @@ -0,0 +1,148 @@ +use sysmlv2_model::{ + full, json, + model::{Model, ParsedSource}, +}; +use sysmlv2_transform::{CheckFinding, CheckStage, Library, Session}; + +fn signature(findings: Vec) -> Vec { + findings + .into_iter() + .map(|finding| format!("{finding:?}")) + .collect() +} + +#[test] +fn transferred_syntax_preserves_graphs_positions_and_prepared_unit_offsets() { + let mut library = Model::new(); + library.add_library_source("library.KerML", "package L { class Base; }"); + let prepared = library.prepare_library().unwrap(); + let mut transferred = Model::new(); + let mut direct = Model::new(); + prepared.clone().install(&mut transferred).unwrap(); + prepared.install(&mut direct).unwrap(); + for (name, text) in [ + ("empty.sysml", ""), + ("types.KerML", "package K { class C :> L::Base; }"), + ( + "user.sysml", + "// café\r\npackage U { part p : K::C; part missing : Unknown; }\n", + ), + ] { + // Populate the combined unit view before insertion; it must invalidate. + let before = transferred.units().len(); + let parsed = ParsedSource::new(name, text); + assert_eq!(parsed.name(), name); + assert!(parsed.diagnostics().is_empty()); + assert_eq!( + parsed.unit().dialect, + direct.add_source(name, text).unit.dialect + ); + transferred.add_parsed_source(parsed); + assert_eq!(transferred.units().len(), before + 1); + assert!(!transferred.unit(before).is_library); + } + assert_eq!( + json::model_to_compact_json(&transferred), + json::model_to_compact_json(&direct) + ); + assert_eq!( + full::model_to_full_json_with(&transferred, true), + full::model_to_full_json_with(&direct, true) + ); + let check = |model: &Model| { + let mut resolved = json::ResolvedModel::build(model); + format!( + "{:?}", + sysmlv2_model::check::validate_model_with(&mut resolved, model) + ) + }; + assert_eq!(check(&transferred), check(&direct)); + assert!(!transferred.has_errors()); +} + +#[test] +fn transferred_broken_syntax_retains_diagnostics_and_line_index() { + let text = "// café\r\npackage Broken {\n part p : ;\n}\n"; + let parsed = ParsedSource::new("broken.sysml", text); + assert!(!parsed.diagnostics().is_empty()); + let positions: Vec<_> = parsed + .diagnostics() + .iter() + .map(|d| { + let pos = parsed.lines().line_col(d.span.start); + (pos.line, pos.col) + }) + .collect(); + let mut direct = Model::new(); + let mut transferred = Model::new(); + let expected = direct.add_source("broken.sysml", text); + let actual = transferred.add_parsed_source(parsed); + assert_eq!( + format!("{:?}", actual.diagnostics), + format!("{:?}", expected.diagnostics) + ); + assert_eq!(format!("{:?}", actual.unit), format!("{:?}", expected.unit)); + for (diagnostic, expected) in actual.diagnostics.iter().zip(positions) { + let pos = actual.lines.line_col(diagnostic.span.start); + assert_eq!((pos.line, pos.col), expected); + } + assert!(transferred.has_errors()); +} + +#[test] +fn checking_reused_parses_matches_syntax_plus_independent_session() { + let sources = vec![ + ("broken.sysml".into(), "package Broken { part p : ; }".into()), + ("types.KerML".into(), "package K { class C; }".into()), + ("user.sysml".into(), "// café\r\npackage U { import K::*; part p : C; part missing : Unknown; attribute def V; individual def I :> V; }".into()), + ("empty.sysml".into(), "".into()), + ]; + let units = vec![( + "lib.sysml".into(), + "package Library { part def Base; }".into(), + )]; + let syntax = sysmlv2_transform::check_sources_syntax(&sources); + assert!(syntax.iter().any(|f| f.stage == CheckStage::Parse)); + assert!(syntax.iter().any(|f| f.stage == CheckStage::Context)); + assert_eq!( + signature(sysmlv2_transform::check_sources(&sources, None).unwrap()), + signature(syntax.clone()) + ); + for library in [ + Library::sources(units.clone()), + Library::prepared_sources(units, None).unwrap(), + ] { + let mut session = + Session::from_sources_with_library(sources[1..].to_vec(), Some(library.clone())) + .unwrap(); + let mut expected = syntax.clone(); + expected.extend( + session + .check_findings() + .into_iter() + .filter(|f| f.stage != CheckStage::Context), + ); + assert!(expected.iter().any(|f| f.stage == CheckStage::Referential)); + assert!(expected.iter().any(|f| f.stage == CheckStage::Semantic)); + let actual = + sysmlv2_transform::check_sources_with_library(&sources, Some(&library)).unwrap(); + assert_eq!(signature(actual), signature(expected)); + assert!( + sysmlv2_transform::check_sources_with_library(&[], Some(&library)) + .unwrap() + .is_empty() + ); + assert_eq!( + signature( + sysmlv2_transform::check_sources_with_library(&sources[..1], Some(&library)) + .unwrap() + ), + signature(sysmlv2_transform::check_sources_syntax(&sources[..1])) + ); + } + let absent = std::env::temp_dir().join(format!("absent-parsed-library-{}", std::process::id())); + assert!(!absent.exists()); + let missing = Library::dir(&absent); + assert!(sysmlv2_transform::check_sources_with_library(&[], Some(&missing)).is_err()); + assert!(sysmlv2_transform::check_sources_with_library(&sources[..1], Some(&missing)).is_err()); +} diff --git a/crates/sysmlv2-transform/tests/payload_loader.rs b/crates/sysmlv2-transform/tests/payload_loader.rs new file mode 100644 index 0000000..40eccb5 --- /dev/null +++ b/crates/sysmlv2-transform/tests/payload_loader.rs @@ -0,0 +1,599 @@ +//! The id-preserving payload loader (plan §33c): a document loaded into +//! a session keeps the ids it carried — this toolkit's own, a foreign +//! producer's, or ids of elements the textual notation cannot name. + +use serde_json::Value; +use std::collections::HashMap; +use std::fs; +use sysmlv2_model::model::Model; +use sysmlv2_transform::{Library, Session, SessionError}; +use uuid::Uuid; + +fn canon(v: &Value) -> String { + serde_json::to_string(v).unwrap() +} + +fn by_id(v: &Value) -> HashMap { + v.as_array() + .unwrap() + .iter() + .map(|e| (e["@id"].as_str().unwrap().to_string(), e)) + .collect() +} + +/// Every id in the payload replaced by a fresh one, consistently across +/// references — a document from another producer. +fn foreignize(v: &Value) -> (Value, HashMap) { + let mut map: HashMap = HashMap::new(); + for e in v.as_array().unwrap() { + let id = e["@id"].as_str().unwrap().to_string(); + let fresh = Uuid::new_v5(&Uuid::NAMESPACE_OID, format!("foreign:{id}").as_bytes()); + map.insert(id, fresh.to_string()); + } + fn rewrite(v: &Value, map: &HashMap) -> Value { + match v { + Value::Object(o) => Value::Object( + o.iter() + .map(|(k, x)| { + let x = if (k == "@id" || k == "elementId") && x.is_string() { + map.get(x.as_str().unwrap()) + .map(|s| Value::String(s.clone())) + .unwrap_or_else(|| x.clone()) + } else { + rewrite(x, map) + }; + (k.clone(), x) + }) + .collect(), + ), + Value::Array(a) => Value::Array(a.iter().map(|x| rewrite(x, map)).collect()), + other => other.clone(), + } + } + (rewrite(v, &map), map) +} + +#[test] +fn toolkit_payload_reloads_with_identical_ids_and_no_explicit_ids() { + let src = "package P { + part def V { attribute mass; part w[2]; } + part v : V { attribute :>> mass = 3; } + alias M for V; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let compact = s.to_compact_json(); + // Same unit name, so the derivation reproduces every id and no + // explicit id is needed; without the name the root id (salted by the + // unit name) would differ and the whole document would ride explicit. + let loaded = + Session::from_interchange_json_named(&compact, None, &["p.sysml".to_string()]).unwrap(); + assert!(!loaded.has_explicit_ids(), "our own ids derive exactly"); + let unnamed = Session::from_interchange_json(&compact).unwrap(); + assert!(unnamed.has_explicit_ids()); + assert_eq!(canon(&unnamed.to_compact_json()), canon(&compact)); + assert_eq!(canon(&loaded.to_compact_json()), canon(&compact)); + assert_eq!( + canon(&loaded.to_full_json_with(false)), + canon(&s.to_full_json_with(false)) + ); +} + +#[test] +fn foreign_ids_are_preserved_and_flagged() { + let src = "package P { + part def V { attribute mass; } + part v : V; + connection c connect v to v; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let (foreign, map) = foreignize(&s.to_compact_json()); + let loaded = Session::from_interchange_json(&foreign).unwrap(); + assert!(loaded.has_explicit_ids()); + assert!( + loaded.warnings().is_empty(), + "no unmatched elements: {:?}", + loaded.warnings() + ); + // Every element comes back under the id it was given, references + // included. + assert_eq!(canon(&loaded.to_compact_json()), canon(&foreign)); + // The full form spells the same ids. + let full = loaded.to_full_json_with(false); + let ids = by_id(&full); + for given in map.values() { + assert!( + ids.contains_key(given), + "{given} missing from the full form" + ); + } + // The read API sees them too. + let mut loaded = loaded; + let v_id = foreign + .as_array() + .unwrap() + .iter() + .find(|e| e["declaredName"] == "v") + .map(|e| e["@id"].as_str().unwrap().to_string()) + .expect("v"); + let v = loaded + .resolved() + .element_by_id(&v_id) + .expect("v is addressable by its given id"); + assert_eq!(loaded.resolved().element_name(v), Some("v")); + // Binary: the compact payload is flagged; elision is refused. + let bytes = loaded.to_compact_cbor(); + let desc = sysmlv2_cbor::describe(&bytes).unwrap(); + assert_eq!(desc["explicitIds"], true); + assert!(matches!( + loaded.to_compact_cbor_elided(), + Err(SessionError::ExplicitIds) + )); + // The flagged payload decodes to the same ids. + let back = Session::from_compact_cbor(&bytes).unwrap(); + assert_eq!(canon(&back.to_compact_json()), canon(&foreign)); +} + +#[test] +fn explicit_ids_survive_an_edit_elsewhere() { + let src = "package P { + part def V { attribute mass; } + part v : V; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let (foreign, _) = foreignize(&s.to_compact_json()); + let mut loaded = Session::from_interchange_json(&foreign).unwrap(); + let before = loaded.to_compact_json(); + // Append a new member: existing ids stay given, the new one derives. + let p = loaded.resolved().resolve_qualified("P").unwrap(); + let mut edit = loaded.edit(); + edit.insert_member(p, "part w;"); + edit.commit().unwrap(); + let after = loaded.to_compact_json(); + let before_ids = by_id(&before); + let after_ids = by_id(&after); + for (id, el) in &before_ids { + let kept = after_ids + .get(id) + .expect("given id survives an unrelated edit"); + assert_eq!(kept["@type"], el["@type"]); + } + assert!(loaded.has_explicit_ids()); + assert!( + after_ids.values().any(|e| e["declaredName"] == "w"), + "the new member is present" + ); +} + +#[test] +fn a_deleted_element_does_not_bequeath_its_given_id() { + let src = "package P { + part def V { attribute mass; } + part v : V; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let (foreign, _) = foreignize(&s.to_compact_json()); + let mut loaded = Session::from_interchange_json(&foreign).unwrap(); + let v_given = foreign + .as_array() + .unwrap() + .iter() + .find(|e| e["declaredName"] == "v") + .map(|e| e["@id"].as_str().unwrap().to_string()) + .unwrap(); + // Delete v: its entry retires with it. + let v = loaded.resolved().resolve_qualified("P::v").unwrap(); + let mut edit = loaded.edit(); + edit.remove(v); + edit.commit().unwrap(); + assert!(!by_id(&loaded.to_compact_json()).contains_key(&v_given)); + // Recreate a `part v` in the same place: it derives the same key as + // the deleted one, and must not inherit the deleted element's id. + let p = loaded.resolved().resolve_qualified("P").unwrap(); + let mut edit = loaded.edit(); + edit.insert_member(p, "part v : V;"); + edit.commit().unwrap(); + let after = loaded.to_compact_json(); + let new_v = after + .as_array() + .unwrap() + .iter() + .find(|e| e["declaredName"] == "v") + .map(|e| e["@id"].as_str().unwrap().to_string()) + .unwrap(); + assert_ne!(new_v, v_given, "a fresh element is not the deleted one"); + // The remaining entries (P, V, mass, their memberships, the root) are + // still explicit. + assert!(loaded.has_explicit_ids()); +} + +#[test] +fn reordered_relationships_never_swap_ids_across_metaclasses() { + // A producer may list a feature's value before its typing; the lift + // prints a fixed order, so positional pairing alone would cross the + // two ids. Pairing is only trusted within a metaclass. + let src = "package P { + part def V; + part v : V = null; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let (mut foreign, _) = foreignize(&s.to_compact_json()); + let v_index = foreign + .as_array() + .unwrap() + .iter() + .position(|e| e["declaredName"] == "v") + .unwrap(); + let rels = foreign[v_index]["ownedRelationship"] + .as_array() + .unwrap() + .clone(); + assert_eq!(rels.len(), 2, "typing and value"); + foreign[v_index]["ownedRelationship"] = Value::Array(rels.iter().rev().cloned().collect()); + let loaded = Session::from_interchange_json(&foreign).unwrap(); + let ids = by_id(&foreign); + let emitted = loaded.to_compact_json(); + let out = by_id(&emitted); + for (id, el) in &ids { + if let Some(x) = out.get(id) { + assert_eq!(x["@type"], el["@type"], "id {id} changed metaclass"); + } + } + assert!( + loaded + .warnings() + .iter() + .any(|w| w.contains("no structural counterpart")), + "the two reordered relationships are reported, not swapped: {:?}", + loaded.warnings() + ); +} + +#[test] +fn a_document_in_another_element_order_still_preserves_its_ids() { + let src = "package P { + part def V { attribute mass; } + part v : V; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let (foreign, _) = foreignize(&s.to_compact_json()); + let reversed = Value::Array(foreign.as_array().unwrap().iter().rev().cloned().collect()); + let loaded = Session::from_interchange_json(&reversed).unwrap(); + assert!(loaded.has_explicit_ids()); + assert!(loaded.warnings().is_empty(), "{:?}", loaded.warnings()); + let emitted = loaded.to_compact_json(); + let out = by_id(&emitted); + for (id, el) in by_id(&foreign) { + assert_eq!(out.get(&id).map(|x| canon(x)), Some(canon(el)), "{id}"); + } +} + +#[test] +fn library_references_stay_ids_without_a_library() { + // A library-typed payload converted without a library: the lift can + // only spell the library id, and the emitted forms keep it as the id + // (no dangling substitute, no recovery annotation). + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return; + } + let s = Session::from_sources(vec![( + "p.sysml".into(), + "package P { part def V { attribute mass : ScalarValues::Real; } }".into(), + )]) + .unwrap() + .with_library(&root.join("sysml.library")) + .unwrap(); + let compact = s.to_compact_json(); + let lib_type = compact + .as_array() + .unwrap() + .iter() + .find(|e| e["@type"] == "FeatureTyping") + .map(|e| e["type"]["@id"].as_str().unwrap().to_string()) + .expect("the typing references a library id"); + let loaded = Session::from_interchange_json(&compact).unwrap(); + let typing_of = |v: &Value| -> Value { + v.as_array() + .unwrap() + .iter() + .find(|e| e["@type"] == "FeatureTyping") + .map(|e| e["type"].clone()) + .unwrap() + }; + assert_eq!(typing_of(&loaded.to_compact_json())["@id"], lib_type); + let full = loaded.to_full_json_with(true); + assert_eq!(typing_of(&full)["@id"], lib_type); + assert!( + !full + .as_array() + .unwrap() + .iter() + .any(|e| e["@type"] == "TextualRepresentation"), + "no recovery annotation for an id-spelled reference" + ); +} + +#[test] +fn references_to_unnamed_elements_are_bound_by_id() { + // API-GAPS issue 13: a legal payload may reference an element with + // no name; the text cannot spell it, but the loaded model must keep + // the link. + let src = "package P { + part a; part b; + connection c connect a to b; + }"; + let s = Session::from_sources(vec![("p.sysml".into(), src.into())]).unwrap(); + let mut compact = s.to_compact_json(); + let mut stripped = 0; + for e in compact.as_array_mut().unwrap() { + let name = e["declaredName"].as_str().map(str::to_string); + if matches!(name.as_deref(), Some("a") | Some("b")) { + e.as_object_mut().unwrap().remove("declaredName"); + stripped += 1; + } + } + assert_eq!(stripped, 2); + let loaded = Session::from_interchange_json(&compact).unwrap(); + let out = loaded.to_compact_json(); + let text = canon(&out); + assert!( + !text.contains("@ref"), + "no reference degrades to a spelling: {text}" + ); + // The connector's ends still target the two unnamed parts. + let ids = by_id(&compact); + let unnamed: Vec<&str> = ids + .iter() + .filter(|(_, e)| e["@type"] == "PartUsage" && e.get("declaredName").is_none()) + .map(|(id, _)| id.as_str()) + .collect(); + assert_eq!(unnamed.len(), 2); + let out_ids = by_id(&out); + for id in &unnamed { + assert!(out_ids.contains_key(*id), "unnamed part keeps its id"); + } + let referenced: Vec<&str> = out + .as_array() + .unwrap() + .iter() + .filter(|e| e["@type"] == "ReferenceSubsetting") + .filter_map(|e| e["referencedFeature"]["@id"].as_str()) + .collect(); + for id in &unnamed { + assert!( + referenced.contains(id), + "connector end references the unnamed part {id}: {referenced:?}" + ); + } + assert!( + loaded + .warnings() + .iter() + .all(|w| !w.contains("cannot name reference target")), + "{:?}", + loaded.warnings() + ); +} + +/// The whole standard corpus loaded from its compact payload reproduces +/// the text route's compact and full forms element by element. +/// +/// Excluded: files whose top-level package name is also declared by +/// another corpus file. The lift spells cross-scope references rooted at +/// the model root (`$::Name::…`), which is unambiguous within one +/// document but not in a model that holds two documents declaring the +/// same top-level name (API-GAPS issue 15); the text route resolves +/// those references lexically. +#[test] +fn corpus_payload_route_matches_the_text_route() { + // A whole-corpus session rebuild needs more stack than a test thread + // has, as the other corpus-scale session tests in this crate do. + std::thread::Builder::new() + .stack_size(64 * 1024 * 1024) + .spawn(corpus_payload_route_body) + .unwrap() + .join() + .unwrap(); +} + +fn corpus_payload_route_body() { + let root = sysmlv2_testkit::workspace_root().join("spec-refs/SysML-v2-Release"); + if !root.join("sysml.library").exists() { + eprintln!("skipping: corpus not present"); + return; + } + let files = sysmlv2_testkit::user_files(); + if files.is_empty() { + eprintln!("skipping: corpus model files not present"); + return; + } + // Top-level member names per file, read from the resolved model, to + // drop the files whose top-level names another file declares too. + let mut probe = Model::new(); + let mut probe_names = Vec::new(); + for path in &files { + let src = fs::read_to_string(path).unwrap(); + let name = path + .strip_prefix(&root) + .unwrap_or(path) + .to_string_lossy() + .into_owned(); + probe.add_source(name.clone(), &src); + probe_names.push(name); + } + let (probe_compact, probe_units) = + sysmlv2_model::json::model_to_compact_json_with_units(&probe); + let mut resolved = sysmlv2_model::json::ResolvedModel::build(&probe); + let mut per_file: Vec<(std::path::PathBuf, Vec)> = Vec::new(); + let mut declared: HashMap = HashMap::new(); + for (i, (root_index, unit)) in probe_units.iter().enumerate() { + let root_id = probe_compact[*root_index]["@id"].as_str().unwrap(); + let root_el = resolved.element_by_id(root_id).expect("unit root"); + let names: Vec = resolved + .owned_members(root_el) + .into_iter() + .filter_map(|m| resolved.element_name(m).map(str::to_string)) + .collect(); + for n in &names { + *declared.entry(n.clone()).or_default() += 1; + } + assert_eq!(&probe_names[i], unit); + per_file.push((files[i].clone(), names)); + } + let excluded: Vec<&std::path::PathBuf> = per_file + .iter() + .filter(|(_, names)| names.iter().any(|n| declared[n] > 1)) + .map(|(p, _)| p) + .collect(); + assert_eq!( + excluded.len(), + 8, + "four top-level names are each declared by two corpus files: {excluded:?}" + ); + let files: Vec = files + .iter() + .filter(|p| !excluded.contains(p)) + .cloned() + .collect(); + let lib = Library::dir(root.join("sysml.library")); + let mut model = Model::new(); + model + .load_library_dir(&root.join("sysml.library")) + .expect("library loads"); + let mut names = Vec::new(); + for path in &files { + let src = fs::read_to_string(path).unwrap(); + let name = path + .strip_prefix(&root) + .unwrap_or(path) + .to_string_lossy() + .into_owned(); + model.add_source(name.clone(), &src); + names.push(name); + } + let compact = sysmlv2_model::json::model_to_compact_json(&model); + let direct_full = sysmlv2_model::full::model_to_full_json_with(&model, false); + let loaded = Session::from_interchange_json_named(&compact, Some(&lib), &names).unwrap(); + assert!( + !loaded.has_explicit_ids(), + "a toolkit payload loaded under its unit names derives every id" + ); + assert!( + loaded.warnings().is_empty(), + "{} warnings, first: {:?}", + loaded.warnings().len(), + loaded.warnings().first() + ); + let reloaded = loaded.to_compact_json(); + let (a, b) = (by_id(&compact), by_id(&reloaded)); + assert_eq!(a.len(), b.len(), "element count"); + // API-GAPS issue 16: one reference to a library return parameter is + // spelled by the parameter's effective name and does not re-resolve. + const KNOWN_UNRESOLVED: &str = "$::Requirements::RequirementConstraintCheck::result"; + let mut known = 0usize; + let mut known_ids: Vec = Vec::new(); + let mut differing = 0usize; + let mut example = String::new(); + for (id, el) in &a { + match b.get(id) { + Some(x) if canon(x) == canon(el) => {} + Some(x) if x["memberElement"]["@ref"] == KNOWN_UNRESOLVED => { + known += 1; + known_ids.push(id.clone()); + } + other => { + differing += 1; + if example.is_empty() { + example = format!("{id}: {} vs {:?}", canon(el), other.map(|x| canon(x))); + } + } + } + } + assert_eq!(known, 1, "exactly one known unresolvable spelling"); + assert_eq!( + differing, 0, + "compact round trip through the loader; e.g. {example}" + ); + // And the full form emitted from the loaded session equals the + // text route's, element by element. + let loaded_full = loaded.to_full_json_with(false); + let (a, b) = (by_id(&direct_full), by_id(&loaded_full)); + assert_eq!(a.len(), b.len(), "full-form element count"); + // The known unresolvable reference becomes a deterministic dangling + // id in the full form; skip it and every element that carries that + // id in a derived property. + let dangling: Vec = known_ids + .iter() + .filter_map(|id| b.get(id.as_str())) + .filter_map(|x| x["memberElement"]["@id"].as_str().map(str::to_string)) + .collect(); + let mut differing = 0usize; + for (id, el) in &a { + if b.get(id).map(|x| canon(x)) != Some(canon(el)) { + let text = canon(b[id]); + if known_ids.contains(id) || dangling.iter().any(|d| text.contains(d)) { + continue; + } + differing += 1; + if differing == 1 { + eprintln!("first full-form difference at {id}: {}", canon(b[id])); + } + } + } + assert_eq!(differing, 0, "full form through the loader"); +} + +#[test] +fn long_expressions_keep_their_value_through_json_and_cbor_sessions() { + sysmlv2_syntax::parser::on_parsing_stack( + "session-expression-roundtrip", + |e| panic!("cannot reserve parsing stack: {e}"), + || { + let operators = sysmlv2_syntax::parser::MAX_EXPR_OPERATORS as usize; + let source = format!("attribute sum = {};", vec!["1"; operators + 1].join(" + ")); + let session = Session::from_sources(vec![("sum.sysml".into(), source)]).unwrap(); + let compact = session.to_compact_json(); + let full = session.to_full_json(); + let bytes = session.to_compact_cbor(); + let binary = Session::from_compact_cbor(&bytes).unwrap(); + assert_eq!(binary.to_compact_json(), compact); + for payload in [&compact, &full] { + let loaded = Session::from_interchange_json(payload).unwrap(); + assert!(loaded.warnings().is_empty(), "{:?}", loaded.warnings()); + assert_eq!(loaded.to_compact_json(), compact); + } + + // Add one operator below the deepest leaf: the valid input is + // now just beyond the expression budget. Neither JSON nor + // binary session loading may return the shorter sum. + let mut too_deep = compact; + let elements = too_deep.as_array_mut().unwrap(); + let leaf = elements + .iter_mut() + .find(|e| e["@type"] == "LiteralInteger") + .unwrap(); + let leaf_id = leaf["@id"].clone(); + leaf["@type"] = "OperatorExpression".into(); + leaf["operator"] = "+".into(); + leaf.as_object_mut().unwrap().remove("value"); + let id = |s: &str| Uuid::new_v5(&Uuid::NAMESPACE_OID, s.as_bytes()).to_string(); + let rels = [id("extra-left-rel"), id("extra-right-rel")]; + leaf["ownedRelationship"] = serde_json::json!([{"@id": rels[0]}, {"@id": rels[1]}]); + for (i, rel) in rels.iter().enumerate() { + let value = id(&format!("extra-value-{i}")); + elements.push(serde_json::json!({"@id": rel, "@type": "ParameterMembership", + "owningRelatedElement": {"@id": leaf_id}, "ownedRelatedElement": [{"@id": value}]})); + elements.push(serde_json::json!({"@id": value, "@type": "LiteralInteger", + "owningRelationship": {"@id": rel}, "value": 1})); + } + let error = match Session::from_interchange_json(&too_deep) { + Ok(_) => panic!("a truncated expression must not become a session"), + Err(e) => e.to_string(), + }; + assert!(error.contains("expression nesting deeper than"), "{error}"); + let bytes = sysmlv2_cbor::to_compact_cbor(&too_deep).unwrap(); + assert!(Session::from_compact_cbor(&bytes).is_err()); + }, + ); +} diff --git a/crates/sysmlv2-transform/tests/prepared_sources.rs b/crates/sysmlv2-transform/tests/prepared_sources.rs new file mode 100644 index 0000000..870466e --- /dev/null +++ b/crates/sysmlv2-transform/tests/prepared_sources.rs @@ -0,0 +1,35 @@ +use sysmlv2_transform::{Library, Session}; + +#[test] +fn prepared_library_keeps_source_order_and_navigation_text() { + let units = vec![ + ("lib.KerML".to_owned(), "package L { class A; }".to_owned()), + ( + "extra.sysml".to_owned(), + "package Extra { part def B; }".to_owned(), + ), + ]; + let library = Library::prepared_sources(units.clone(), None).unwrap(); + if let Library::Prepared(graph) = &library { + assert_eq!( + graph.sources().collect::>(), + units + .iter() + .map(|(n, t)| (n.as_str(), t.as_str())) + .collect::>() + ); + assert!(graph.source(2).is_none()); + } else { + panic!("prepared library expected"); + } + let s = Session::from_sources_with_library( + vec![("user.sysml".into(), "package U;".into())], + Some(library), + ) + .unwrap(); + for (i, (name, text)) in units.iter().enumerate() { + assert_eq!(s.library_unit(i), Some((name.as_str(), text.as_str()))); + assert!(s.library_unit_path(i).is_none()); + } + assert!(s.library_unit(2).is_none()); +} diff --git a/crates/sysmlv2-transform/tests/refusal_message.rs b/crates/sysmlv2-transform/tests/refusal_message.rs index 7e81e22..77405e1 100644 --- a/crates/sysmlv2-transform/tests/refusal_message.rs +++ b/crates/sysmlv2-transform/tests/refusal_message.rs @@ -2,7 +2,7 @@ //! human-readable terms: the spelled reference text, unit:line:col, the //! raw byte span, and the expected target's qualified name. -use sysmlv2_transform::{Session, TransformError}; +use sysmlv2_transform::{Session, SessionError, TransformError}; #[test] fn refusal_names_broken_sites() { @@ -37,3 +37,25 @@ package Rig { assert!(msg.contains("Other::Wheel"), "{msg}"); println!("{msg}"); } + +#[test] +fn a_parse_failure_with_no_diagnostics_still_prints() { + // The diagnostic lists are public fields, so a host can hand back an + // error it built itself (a relay across a process boundary, say). + // An empty list must read as a missing detail, not end in a fault. + let session = SessionError::Parse { + unit: "t.sysml".into(), + diagnostics: Vec::new(), + }; + let msg = session.to_string(); + assert!(msg.starts_with("t.sysml does not parse: "), "{msg}"); + assert!(msg.contains("no diagnostic"), "{msg}"); + + let reparse = TransformError::ReparseFailed { + unit: "t.sysml".into(), + diagnostics: Vec::new(), + }; + let msg = reparse.to_string(); + assert!(msg.starts_with("edited t.sysml does not parse: "), "{msg}"); + assert!(msg.contains("no diagnostic"), "{msg}"); +} diff --git a/crates/sysmlv2-transform/tests/transform.rs b/crates/sysmlv2-transform/tests/transform.rs index 7cc65cd..cb6e078 100644 --- a/crates/sysmlv2-transform/tests/transform.rs +++ b/crates/sysmlv2-transform/tests/transform.rs @@ -800,11 +800,50 @@ fn check_sources_reports_parse_errors_with_positions() { assert!(!findings.is_empty(), "expected parse findings"); let f = &findings[0]; assert_eq!(f.severity, sysmlv2_transform::Severity::Error); + assert_eq!(f.stage, sysmlv2_transform::CheckStage::Parse); assert_eq!(f.unit, "bad.sysml"); assert_eq!(f.line, 2, "position should point at the broken typing"); assert!(f.col > 0); } +#[test] +fn check_sources_stages_context_referential_and_semantic_findings() { + let lib = sysmlv2_testkit::library_dir(); + let findings = sysmlv2_transform::check_sources( + &[( + "staged.sysml".into(), + "package Staged {\n import ScalarValues::*;\n part p : Missing;\n attribute def V;\n individual def I :> V;\n}\n".into(), + )], + Some(&lib), + ) + .expect("check runs"); + let stage_of = |needle: &str| { + findings + .iter() + .find(|f| f.message.contains(needle)) + .unwrap_or_else(|| panic!("no finding containing {needle:?}: {findings:?}")) + .stage + }; + assert_eq!( + stage_of("explicit visibility"), + sysmlv2_transform::CheckStage::Context + ); + assert_eq!( + stage_of("unresolved reference"), + sysmlv2_transform::CheckStage::Referential + ); + assert_eq!( + stage_of("cannot specialize a data type"), + sysmlv2_transform::CheckStage::Semantic + ); + assert!( + findings + .iter() + .all(|f| f.stage != sysmlv2_transform::CheckStage::Parse), + "nothing failed to parse: {findings:?}" + ); +} + #[test] fn check_sources_is_quiet_on_clean_sources_without_library() { let findings = sysmlv2_transform::check_sources( @@ -1297,3 +1336,906 @@ fn replace_batch_tolerates_sibling_consumed_references() { assert!(t.contains("about Beta"), "{t}"); assert!(t.contains("body = \"new\""), "{t}"); } + +#[test] +fn removing_inline_succession_preserves_its_action_and_references() { + for prefix in [ + "then", + "then [1]", + "private then", + "then private", + "then // retained\n", + ] { + let src = + format!("part p {{ perform action a; {prefix} perform action b; first b then a; }}"); + let mut s = session(&src); + let owner = s.resolved().resolve_qualified("p").unwrap(); + let edge = s + .resolved() + .owned_members(owner) + .into_iter() + .find(|&m| s.resolved().element_type(m) == "SuccessionAsUsage") + .unwrap(); + let mut edit = s.edit(); + edit.remove(edge); + edit.commit() + .expect("only the implicit relationship is removed"); + let out = text(&s); + assert!( + out.contains("perform action a;") + && out.contains("perform action b;") + && out.contains("first b then a;"), + "{out}" + ); + assert_eq!(out.matches("then").count(), 1, "{out}"); + assert!(!out.contains("[1]"), "{out}"); + if prefix.contains("private") { + assert!(out.contains("private"), "{out}"); + } + if prefix.contains("retained") { + assert!(out.contains("// retained"), "{out}"); + } + let owner = s.resolved().resolve_qualified("p").unwrap(); + assert_eq!( + s.resolved() + .owned_members(owner) + .into_iter() + .filter(|&m| s.resolved().element_type(m) == "SuccessionAsUsage") + .count(), + 1 + ); + } +} + +#[test] +fn check_sources_names_the_private_member_behind_an_unresolved_reference() { + let lib = sysmlv2_testkit::library_dir(); + let findings = sysmlv2_transform::check_sources( + &[( + "blocked.sysml".into(), + "package P {\n constraint def MaxTime { private port maxTime; }\n part def Req { constraint c : MaxTime; attribute limit; bind c.maxTime = limit; }\n}\n".into(), + )], + Some(&lib), + ) + .expect("check runs"); + let f = findings + .iter() + .find(|f| f.message.starts_with("unresolved reference")) + .unwrap_or_else(|| panic!("{findings:?}")); + assert_eq!( + f.message, + "unresolved reference `maxTime` — `P::MaxTime::maxTime` exists but is private" + ); + assert_eq!(f.stage, sysmlv2_transform::CheckStage::Referential); +} + +// --------------------------------------------------------------------------- +// split: one file per nested package, references preserved +// --------------------------------------------------------------------------- + +const SPLIT_SRC: &str = "package Lib { part def Thing; } +package R { + private import Lib::*; + package A { + part def X; + part t : Thing; + part b : B::Y; + } + package B { + part def Y :> A::X; + } + part r : A::X; +} +package Q { + part q : R::A::X; + private import R::B::*; + part y : Y; +} +"; + +fn split_session(src: &str) -> sysmlv2_transform::Session { + sysmlv2_transform::Session::from_sources(vec![("models/r.sysml".into(), src.into())]).unwrap() +} + +#[test] +fn split_plan_names_one_unit_per_nested_package() { + let mut s = split_session(SPLIT_SRC); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + assert_eq!(plan.root_unit, "models/r.sysml"); + assert_eq!(plan.directory, "models/r"); + let units: Vec<(&str, &str, Option<&str>)> = plan + .entries + .iter() + .map(|e| (e.qualified.as_str(), e.unit.as_str(), e.new_name.as_deref())) + .collect(); + assert_eq!( + units, + [ + ("R::A", "models/r/A.sysml", None), + ("R::B", "models/r/B.sysml", None) + ] + ); + assert!(plan.entries.iter().all(|e| e.bytes > 0)); + // Not a package, or a package with nothing nested: refused with a reason. + let lib = s.resolved().resolve_qualified("Lib").unwrap(); + let err = s + .split_plan(lib, &sysmlv2_transform::SplitOptions::default()) + .unwrap_err(); + assert!(err.to_string().contains("owns no nested package"), "{err}"); +} + +#[test] +fn split_hoists_packages_and_keeps_every_reference_resolving() { + let mut s = split_session(SPLIT_SRC); + let before = s.resolved().unresolved_count(); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + let mut edit = s.edit(); + edit.split(&plan); + let report = edit.commit().unwrap_or_else(|e| panic!("{e}")); + // The root's `private import Lib::*` fed only the moved text: noted. + assert!( + report.findings.iter().all(|f| f.contains("import")), + "{:?}", + report.findings + ); + let unit = |name: &str| { + s.units() + .find(|(_, n, _)| *n == name) + .map(|(_, _, t)| t.to_string()) + .unwrap_or_else(|| panic!("no unit {name}")) + }; + let r = unit("models/r.sysml"); + // The root keeps its own members and re-exports the moved packages. + assert!(!r.contains("package A"), "{r}"); + assert!(r.contains(" part r : A::X;\n"), "{r}"); + assert!(r.contains(" public import A;\n"), "{r}"); + assert!(r.contains(" public import B;\n"), "{r}"); + // Moved text is dedented and outward references are spelled in full; + // references inside the moved package stay as written. + let a = unit("models/r/A.sysml"); + assert_eq!( + a, + "package A {\n part def X;\n part t : Lib::Thing;\n part b : R::B::Y;\n}\n" + ); + let b = unit("models/r/B.sysml"); + assert_eq!(b, "package B {\n part def Y :> R::A::X;\n}\n"); + assert_eq!(s.resolved().unresolved_count(), before); + // Qualified references through the root, from inside and outside, + // still denote the same elements. + let q = s.resolved().resolve_qualified("Q::q").unwrap(); + let x = s.resolved().resolve_qualified("A::X").unwrap(); + assert_eq!(s.resolved().typings(q), vec![x]); + assert_eq!(s.resolved().resolve_qualified("R::A::X"), Some(x)); + assert_eq!( + s.resolved().resolve_qualified("R::B::Y"), + s.resolved().resolve_qualified("B::Y") + ); +} + +#[test] +fn split_renames_a_colliding_package_and_aliases_it() { + // `Lib` already exists at the root: the nested one is renamed and + // the root keeps an alias, so `R::Lib::K` still resolves. + let src = "package Lib { part def Thing; } +package R { + package Lib { part def K; } + part k : Lib::K; +} +package Q { part k : R::Lib::K; } +"; + let mut s = split_session(src); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan( + root, + &sysmlv2_transform::SplitOptions { + naming: sysmlv2_transform::SplitNaming::Slug, + directory: Some("out".into()), + uri_units: false, + }, + ) + .unwrap(); + assert_eq!(plan.entries.len(), 1); + assert_eq!(plan.entries[0].new_name.as_deref(), Some("R Lib")); + assert_eq!(plan.entries[0].unit, "out/R-Lib.sysml"); + let mut edit = s.edit(); + edit.split(&plan); + edit.commit().unwrap_or_else(|e| panic!("{e}")); + let r = s + .units() + .find(|(_, n, _)| *n == "models/r.sysml") + .map(|(_, _, t)| t.to_string()) + .unwrap(); + assert!(r.contains(" public alias Lib for 'R Lib';\n"), "{r}"); + let moved = s + .units() + .find(|(_, n, _)| *n == "out/R-Lib.sysml") + .map(|(_, _, t)| t.to_string()) + .unwrap(); + assert_eq!(moved, "package 'R Lib' { part def K; }\n"); + assert_eq!(s.resolved().unresolved_count(), 0); + let k = s.resolved().resolve_qualified("'R Lib'::K").unwrap(); + assert_eq!(s.resolved().resolve_qualified("R::Lib::K"), Some(k)); +} + +#[test] +fn split_respells_a_renamed_package_naming_itself_and_keeps_its_own_imports() { + // `Lib::K` written inside the nested `Lib` names the package itself: + // under the new name it must follow. `Thing` resolves through the + // package's own import, which moves with it: left as written. + let src = "package Lib { part def Thing; } +package R { + package Lib { + private import $::Lib::*; + part def K; + part k : Lib::K; + part k2 : R::Lib::K; + part k3 : $::R::Lib::K; + part t : Thing; + } +} +"; + let mut s = split_session(src); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + let mut edit = s.edit(); + edit.split(&plan); + edit.commit().unwrap_or_else(|e| panic!("{e}")); + let moved = s + .units() + .find(|(_, n, _)| *n == "models/r/R Lib.sysml") + .map(|(_, _, t)| t.to_string()) + .unwrap(); + assert_eq!( + moved, + "package 'R Lib' {\n private import $::Lib::*;\n part def K;\n part k : 'R Lib'::K;\n part k2 : R::Lib::K;\n part k3 : $::R::Lib::K;\n part t : Thing;\n}\n" + ); + assert_eq!(s.resolved().unresolved_count(), 0); +} + +#[test] +fn split_prefixes_a_respelled_reference_the_moved_text_would_shadow() { + // `A::X` and `Thing` respell to `R::A::X` and `Lib::Thing`, whose + // first segments the moved package's own members `R` and `Lib` would + // capture: both spellings start from the global root instead. + let src = "package Lib { part def Thing; } +package R { + private import Lib::*; + package A { part def X; } + package B { + part def R; + part def Lib; + part def Y :> A::X; + part t : Thing; + } +} +"; + let mut s = split_session(src); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + let mut edit = s.edit(); + edit.split(&plan); + edit.commit().unwrap_or_else(|e| panic!("{e}")); + let moved = s + .units() + .find(|(_, n, _)| *n == "models/r/B.sysml") + .map(|(_, _, t)| t.to_string()) + .unwrap(); + assert_eq!( + moved, + "package B {\n part def R;\n part def Lib;\n part def Y :> $::R::A::X;\n part t : $::Lib::Thing;\n}\n" + ); + assert_eq!(s.resolved().unresolved_count(), 0); +} + +#[test] +fn split_plan_reads_the_extension_from_the_file_segment_only() { + let src = "package R { package A { part def X; } }\n"; + let mut s = + sysmlv2_transform::Session::from_sources(vec![("models.v2/r".into(), src.into())]).unwrap(); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + assert_eq!(plan.directory, "models.v2/r"); + assert_eq!(plan.entries[0].unit, "models.v2/r/A.sysml"); + let mut s = sysmlv2_transform::Session::from_sources(vec![( + "k.kerml".into(), + "package R { package 'A/B' { classifier X; } }\n".into(), + )]) + .unwrap(); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + // A path separator in a name never nests the file; the dialect's + // extension carries over. + assert_eq!(plan.entries[0].unit, "k/A-B.kerml"); +} + +#[test] +fn split_keeps_global_rooted_references_global() { + // Inside B a member named `R` shadows the root package, so the + // reference into A is written from the global root; the hoist must + // not strip that prefix, which would make it denote the local `R`. + let src = "package R { + package A { part def X; } + package B { + part def R { part def X; } + part x : $::R::A::X; + part y : R::X; + } +} +"; + let mut s = split_session(src); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + let mut edit = s.edit(); + edit.split(&plan); + edit.commit().unwrap_or_else(|e| panic!("{e}")); + let b = s + .units() + .find(|(_, n, _)| *n == "models/r/B.sysml") + .map(|(_, _, t)| t.to_string()) + .unwrap(); + assert!(b.contains(" part x : $::R::A::X;\n"), "{b}"); + assert!(b.contains(" part y : R::X;\n"), "{b}"); + let x = s.resolved().resolve_qualified("B::x").unwrap(); + let ax = s.resolved().resolve_qualified("A::X").unwrap(); + assert_eq!(s.resolved().typings(x), vec![ax]); +} + +#[test] +fn split_dry_run_reports_the_new_units_as_splices_and_leaves_the_session() { + let mut s = split_session(SPLIT_SRC); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan(root, &sysmlv2_transform::SplitOptions::default()) + .unwrap(); + let mut edit = s.edit(); + edit.split(&plan); + let report = edit.check().unwrap_or_else(|e| panic!("{e}")); + let new_a: String = report + .splices + .iter() + .filter(|sp| sp.unit == "models/r/A.sysml") + .map(|sp| sp.text.as_str()) + .collect(); + assert!(new_a.starts_with("package A {"), "{new_a}"); + assert_eq!(s.units().count(), 1, "a dry run adds no unit"); +} + +// --------------------------------------------------------------------------- +// lenient sources: drop the members that do not parse, keep the rest +// --------------------------------------------------------------------------- + +fn lenient(src: &str) -> sysmlv2_transform::LenientSources { + sysmlv2_transform::lenient_sources(&[("p.sysml".into(), src.into())]) +} + +/// Every record slices the original text it names; the repaired text +/// builds a session. +fn assert_lenient_records(src: &str, r: &sysmlv2_transform::LenientSources) { + for d in &r.dropped { + assert_eq!(&src[d.start as usize..d.end as usize], d.text, "{d:?}"); + } + assert!(r.unrepaired.is_empty(), "{:?}", r.unrepaired); + // The records account for every line break the repair took or added. + let removed: usize = r.dropped.iter().map(|d| d.lines_removed as usize).sum(); + let added: usize = r + .dropped + .iter() + .map(|d| d.inserted.matches('\n').count()) + .sum(); + let repaired = &r.sources[0].1; + assert_eq!( + src.matches('\n').count() - removed + added, + repaired.matches('\n').count(), + "{:?}", + r.dropped + ); + sysmlv2_transform::Session::from_sources(r.sources.clone()).expect("repaired text parses"); +} + +#[test] +fn lenient_sources_drop_only_the_members_that_carry_parse_errors() { + let src = "package P {\n part def A;\n part def B {\n part x : ;\n part ok : A;\n }\n part a : A;\n}\n"; + let r = lenient(src); + assert_eq!(r.sources.len(), 1); + assert_eq!( + r.sources[0].1, + "package P {\n part def A;\n part def B {\n part ok : A;\n }\n part a : A;\n}\n" + ); + assert_eq!(r.dropped.len(), 1, "{:?}", r.dropped); + let d = &r.dropped[0]; + assert_eq!( + (d.unit.as_str(), d.line, d.col, d.end_line, d.end_col), + ("p.sysml", 4, 9, 4, 19) + ); + assert_eq!(d.text, "part x : ;"); + assert!(d.inserted.is_empty()); + // The whole line went, one line break with it. + assert_eq!((d.lines_removed, d.whole_lines), (1, true)); + assert!(d.message.contains("expected"), "{}", d.message); + assert_lenient_records(src, &r); + // Clean sources come back untouched with nothing dropped. + let clean = "package Q { part def C; }\n"; + let r2 = lenient(clean); + assert_eq!(r2.sources[0].1, clean); + assert!(r2.dropped.is_empty() && r2.unrepaired.is_empty()); +} + +#[test] +fn lenient_sources_drop_stray_closers_outside_any_member() { + let src = "package P { part def A; }\n}}}\npackage Q { part def B; }\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P { part def A; }\npackage Q { part def B; }\n" + ); + // Three closers on one line: the parser reports two per round, so + // the first two go together and the last goes with the line break. + let texts: Vec<&str> = r.dropped.iter().map(|d| d.text.as_str()).collect(); + assert_eq!(texts, ["}}", "}"]); + assert_eq!((r.dropped[0].line, r.dropped[0].col), (2, 1)); + assert_eq!( + (r.dropped[0].lines_removed, r.dropped[0].whole_lines), + (0, false) + ); + assert_eq!( + (r.dropped[1].lines_removed, r.dropped[1].whole_lines), + (1, true) + ); +} + +#[test] +fn lenient_sources_recover_a_failed_member_the_parser_skipped() { + // A stray statement at package level has no member node: its text is + // recovered from the tokens, and the package keeps its other members. + let src = "package P {\n part def A;\n foo bar;\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P {\n part def A;\n part def C;\n}\n" + ); + let texts: Vec<&str> = r.dropped.iter().map(|d| d.text.as_str()).collect(); + assert_eq!(texts, ["foo bar;"]); + // Inside a state's sub-action body as well. + let src = "state def S { do action a { part q : ; part r; } }\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "state def S { do action a { part r; } }\n"); + assert_eq!(r.dropped[0].text, "part q : ;"); +} + +#[test] +fn lenient_sources_keep_records_exact_when_cuts_enclose_earlier_ones() { + // `x` fails inside `B`, and `B` itself then fails on `foo bar`: the + // whole of `B` goes in a later round, and every record still slices + // the original text. + let src = "package P {\n part def B {\n part x : ;\n foo bar\n }\n part y : ;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert!( + r.dropped.iter().any(|d| d.text == "part y : ;"), + "{:?}", + r.dropped + ); + assert!( + r.sources[0].1.starts_with("package P {\n"), + "{}", + r.sources[0].1 + ); + assert!(!r.sources[0].1.contains("foo bar"), "{}", r.sources[0].1); +} + +#[test] +fn lenient_sources_cut_only_the_member_when_it_shares_a_line() { + let src = "package P { part def A; part x : ; part def C; }\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P { part def A; part def C; }\n"); + assert_eq!((r.dropped[0].line, r.dropped[0].col), (1, 25)); + assert_eq!( + (r.dropped[0].lines_removed, r.dropped[0].whole_lines), + (0, false) + ); + // A member missing its `;` is the one that goes: the parser kept it + // and reported a zero-width error at its end, so its neighbour stays. + let src = "package P {\n part x : Foo\n part y;\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P {\n part y;\n part def C;\n}\n" + ); + assert_eq!(r.dropped[0].text, "part x : Foo"); + assert_eq!( + (r.dropped[0].lines_removed, r.dropped[0].whole_lines), + (1, true) + ); + // Two broken members on one line leave no blank line behind. + let src = "package P {\n part x : ; part y : ;\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\n part def C;\n}\n"); +} + +#[test] +fn lenient_sources_close_bodies_left_open_at_the_end() { + let src = "package P {\n part def A;\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\n part def A;\n}\n"); + assert_eq!(r.dropped.len(), 1); + let d = &r.dropped[0]; + assert_eq!( + (d.start, d.end, d.text.as_str(), d.inserted.as_str()), + (src.len() as u32, src.len() as u32, "", "}\n") + ); + assert_eq!((d.line, d.col), (3, 1)); + assert!(d.message.contains("end of input"), "{}", d.message); + // Without a trailing line break the closer starts a new line, and a + // nested body left open gets both closers. + let src = "package P {\n part def A {\n part x;"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P {\n part def A {\n part x;\n}\n}\n" + ); +} + +#[test] +fn lenient_sources_handle_kerml_crlf_and_many_errors() { + let src = "package P {\n class A;\n feature x : ;\n class C;\n}\n"; + let r = sysmlv2_transform::lenient_sources(&[("p.kerml".into(), src.into())]); + assert!(r.unrepaired.is_empty(), "{:?}", r.unrepaired); + assert_eq!( + r.sources[0].1, + "package P {\n class A;\n class C;\n}\n" + ); + assert_eq!(r.dropped[0].text, "feature x : ;"); + assert_eq!((r.dropped[0].line, r.dropped[0].col), (3, 5)); + let src = "package P {\r\n part def A;\r\n part x : ;\r\n}\r\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\r\n part def A;\r\n}\r\n"); + // Many broken members repair in a handful of rounds, all recorded. + let mut src = String::from("package P {\n"); + for i in 0..100 { + src.push_str(" part x"); + src.push_str(&i.to_string()); + src.push_str(" : ;\n"); + } + src.push_str(" part def Z;\n}\n"); + let r = lenient(&src); + assert_lenient_records(&src, &r); + assert_eq!(r.dropped.len(), 100); + assert_eq!(r.sources[0].1, "package P {\n part def Z;\n}\n"); +} + +#[test] +fn lenient_sources_keep_unit_order_and_name_units_that_stay_broken() { + let r = sysmlv2_transform::lenient_sources(&[ + ("a.sysml".into(), "package A { part x : ; }\n".into()), + ("b.sysml".into(), "package B { part def Y; }\n".into()), + ("c.sysml".into(), "package C {\n part x : ;\n".into()), + ]); + let names: Vec<&str> = r.sources.iter().map(|(n, _)| n.as_str()).collect(); + assert_eq!(names, ["a.sysml", "b.sysml", "c.sysml"]); + assert_eq!(r.sources[1].1, "package B { part def Y; }\n"); + assert_eq!(r.sources[2].1, "package C {\n}\n"); + assert!( + r.dropped + .iter() + .all(|d| d.unit == "a.sysml" || d.unit == "c.sysml") + ); + assert!(r.unrepaired.is_empty(), "{:?}", r.unrepaired); + // A unit that is nothing but a broken statement repairs to nothing. + let r = sysmlv2_transform::lenient_sources(&[("d.sysml".into(), "package".into())]); + assert_eq!(r.sources[0].1, ""); + assert_eq!(r.dropped[0].text, "package"); + assert!(r.unrepaired.is_empty(), "{r:?}"); +} + +#[test] +fn lenient_sources_drop_a_stray_opener_alone() { + // A diagnostic sitting on a brace names that brace: it goes alone, + // and the package after it stays. + let src = "package P { part def A; }\n{\npackage Q { part def B; }\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P { part def A; }\npackage Q { part def B; }\n" + ); + let texts: Vec<&str> = r.dropped.iter().map(|d| d.text.as_str()).collect(); + assert_eq!(texts, ["{"]); +} + +#[test] +fn lenient_sources_keep_healthy_siblings_of_a_member_missing_its_terminator() { + // The parser keeps a member that lacks its `;` and reports a + // zero-width error at its end; the repair must charge that member, + // never the sibling after it, or the cut cascades through the unit. + let src = "package P {\n action def Act {\n while c {\n action a;\n } until ;\n action b;\n }\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert!(r.sources[0].1.contains("action b;"), "{}", r.sources[0].1); + assert!( + r.sources[0].1.contains("action def Act {"), + "{}", + r.sources[0].1 + ); + assert!(r.dropped.len() <= 2, "{:?}", r.dropped); + let src = + "package P {\n attribute f = {in a; a + 1} foo;\n part def C;\n part def D;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P {\n part def C;\n part def D;\n}\n" + ); + let src = "package P { part def A; } part x : A \n\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert!( + r.sources[0].1.starts_with("package P { part def A; }"), + "{}", + r.sources[0].1 + ); + assert_eq!(r.dropped[0].text, "part x : A"); + // A failed member whose header holds an expression body goes as one + // record, from its first token through the body it opens. + let src = + "package P {\n part x : A = {1} foo {\n part a;\n }\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\n part def C;\n}\n"); + assert_eq!(r.dropped.len(), 1, "{:?}", r.dropped); +} + +#[test] +fn lenient_sources_repair_a_unit_left_open_by_an_unterminated_literal() { + // The literal swallows the rest of the unit; the failed member goes + // from its start to the end, and the package gets its closer back. + let src = + "package P {\n part def A;\n attribute b = \"unterminated;\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\n part def A;\n}\n"); + assert!( + r.dropped[0] + .text + .starts_with("attribute b = \"unterminated;"), + "{:?}", + r.dropped + ); + assert_eq!(r.dropped[1].inserted, "}\n"); + let src = "package P {\n part def A;\n /* open\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!(r.sources[0].1, "package P {\n part def A;\n}\n"); + // Stray closers cut one round at a time still converge. + let src = "package P { part def A; }\n}}\npackage Q { part def B; }\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P { part def A; }\npackage Q { part def B; }\n" + ); +} + +#[test] +fn lenient_sources_drop_a_stray_opener_inside_a_body() { + // The stray `{` is closed by the package's own `}`, which leaves the + // package open at the end: the brace goes alone, the members stay, + // and the closer the first round would have appended is not needed. + let src = "package P {\n part def A;\n {\n part def C;\n}\n"; + let r = lenient(src); + assert_lenient_records(src, &r); + assert_eq!( + r.sources[0].1, + "package P {\n part def A;\n part def C;\n}\n" + ); + let texts: Vec<&str> = r + .dropped + .iter() + .filter(|d| !d.text.is_empty()) + .map(|d| d.text.as_str()) + .collect(); + assert_eq!(texts, ["{"]); +} + +/// A fully qualified reference spelled through a renamed ancestor +/// (`'A B'::X`) is respelled at the ancestor segment and verified +/// through the batch's correspondence map, with an unrelated rename in +/// flight alongside. +#[test] +fn batch_respells_ancestor_qualified_references() { + let src = "package 'A B' { + part def X; +} +package Q { + part def other_def; + part x : 'A B'::X; + part o : other_def; +} +"; + let mut s = session(src); + let ab = s.resolved().resolve_qualified("'A B'").unwrap(); + let other = s.resolved().resolve_qualified("Q::other_def").unwrap(); + let mut edit = s.edit(); + edit.rename(ab, "AB"); + edit.rename(other, "OtherDef"); + let report = edit.commit().expect("legal batch must commit"); + assert!(report.findings.is_empty(), "{:?}", report.findings); + let out = text(&s); + assert!(out.contains("package AB {"), "{out}"); + assert!(out.contains("part x : AB::X;"), "{out}"); + assert!(out.contains("part o : OtherDef;"), "{out}"); + assert_eq!(s.resolved().unresolved_count(), 0); + assert!(s.resolved().resolve_qualified("AB::X").is_some()); +} + +/// A rename whose new name a sibling already carries would make every +/// qualified reference to either ambiguous. By default the batch +/// refuses up front, naming the clash; under the skip policy the +/// colliding rename is dropped and reported while the rest commits. +#[test] +fn colliding_rename_refuses_or_is_skipped_with_a_finding() { + let src = "package P { + part def Foo; + part def foo; + part def bar; + part a : P::Foo; + part b : P::foo; +} +"; + let mut s = session(src); + let foo = s.resolved().resolve_qualified("P::foo").unwrap(); + let bar = s.resolved().resolve_qualified("P::bar").unwrap(); + + let mut edit = s.edit(); + edit.rename(foo, "Foo"); + edit.rename(bar, "Bar"); + let err = edit.commit().expect_err("sibling clash refuses"); + match err { + TransformError::NameTaken { name, existing } => { + assert_eq!(name, "Foo"); + assert_eq!(existing, "P::Foo"); + } + other => panic!("{other}"), + } + assert_eq!(text(&s), src); + + let mut edit = s.edit(); + edit.skip_colliding_renames(); + edit.rename(foo, "Foo"); + edit.rename(bar, "Bar"); + let report = edit.commit().expect("the rest of the batch commits"); + assert_eq!(report.findings.len(), 1, "{:?}", report.findings); + assert!( + report.findings[0].contains("rename of `P::foo` to `Foo` skipped") + && report.findings[0].contains("`P::Foo` is already named `Foo`"), + "{}", + report.findings[0] + ); + let out = text(&s); + assert!(out.contains("part def foo;"), "{out}"); + assert!(out.contains("part def Bar;"), "{out}"); + assert!(out.contains("part b : P::foo;"), "{out}"); + assert_eq!(s.resolved().unresolved_count(), 0); +} + +/// Two renames in one batch claiming the same name in one owner clash +/// with each other: the second is the one dropped. A batch that is +/// nothing but dropped renames leaves the session untouched. +#[test] +fn renames_claiming_one_name_clash_within_the_batch() { + let src = "package P { + part def foo_a; + part def foo_b; +} +"; + let mut s = session(src); + let a = s.resolved().resolve_qualified("P::foo_a").unwrap(); + let b = s.resolved().resolve_qualified("P::foo_b").unwrap(); + let mut edit = s.edit(); + edit.skip_colliding_renames(); + edit.rename(a, "Foo"); + edit.rename(b, "Foo"); + let report = edit.commit().expect("commits"); + assert_eq!(report.findings.len(), 1, "{:?}", report.findings); + assert!( + report.findings[0].contains("rename of `P::foo_b` to `Foo` skipped") + && report.findings[0].contains("already renames its sibling `P::foo_a` to `Foo`"), + "{}", + report.findings[0] + ); + let out = text(&s); + assert!( + out.contains("part def Foo;") && out.contains("part def foo_b;"), + "{out}" + ); + + // Swapping two sibling names is not a clash: both old names leave. + let foo = s.resolved().resolve_qualified("P::Foo").unwrap(); + let b = s.resolved().resolve_qualified("P::foo_b").unwrap(); + let mut edit = s.edit(); + edit.rename(foo, "foo_b"); + edit.rename(b, "Foo"); + edit.commit().expect("a swap commits"); + + // Only a dropped rename: nothing planned, nothing changed. + let before = text(&s); + let b = s.resolved().resolve_qualified("P::Foo").unwrap(); + let mut edit = s.edit(); + edit.skip_colliding_renames(); + edit.rename(b, "foo_b"); + let report = edit.commit().expect("an all-dropped batch reports"); + assert_eq!(report.findings.len(), 1); + assert!(report.splices.is_empty()); + assert_eq!(text(&s), before); +} + +#[test] +fn split_plan_spells_uri_units_as_the_editor_does() { + // Uri-named units: kept names percent-encode everything outside the + // unreserved set (after the path-separator repair), slugs stay + // plain; the directory comes from the uri stem. + let src = "package R {\n package 'a/b%c é~' { part def K; }\n package Plain { part def P; }\n}\n"; + let mut s = sysmlv2_transform::Session::from_sources(vec![( + "file:///w/models/r.sysml".into(), + src.into(), + )]) + .unwrap(); + let root = s.resolved().resolve_qualified("R").unwrap(); + let plan = s + .split_plan( + root, + &sysmlv2_transform::SplitOptions { + uri_units: true, + ..Default::default() + }, + ) + .unwrap(); + assert_eq!(plan.directory, "file:///w/models/r"); + let units: Vec<&str> = plan.entries.iter().map(|e| e.unit.as_str()).collect(); + assert_eq!( + units, + [ + "file:///w/models/r/a-b%25c%20%C3%A9~.sysml", + "file:///w/models/r/Plain.sysml" + ] + ); + let plan = s + .split_plan( + root, + &sysmlv2_transform::SplitOptions { + naming: sysmlv2_transform::SplitNaming::Slug, + uri_units: true, + ..Default::default() + }, + ) + .unwrap(); + assert_eq!( + plan.entries[0].unit, + "file:///w/models/r/a-b-c-%C3%A9.sysml" + ); +} diff --git a/crates/sysmlv2-transform/tests/unused_imports.rs b/crates/sysmlv2-transform/tests/unused_imports.rs index 69f9920..2394925 100644 --- a/crates/sysmlv2-transform/tests/unused_imports.rs +++ b/crates/sysmlv2-transform/tests/unused_imports.rs @@ -118,3 +118,44 @@ fn corpus_ratchet() { "the doc-carrier family disappeared: {named:#?}" ); } + +/// Checking a session leaves its unused-import answer a fresh build's: +/// the validation passes look names up speculatively (alias targets, +/// constraint references), and those lookups are not source references. +#[test] +fn check_findings_do_not_count_import_use() { + use sysmlv2_transform::Library; + let lib = Library::Sources { + units: std::sync::Arc::new(vec![( + "MiniLib.kerml".to_string(), + "standard library package MiniLib { class Thing; }".to_string(), + )]), + snapshot: None, + }; + // (body, unused imports a fresh build reports) + let cases = [ + ("package A { private import MiniLib::*; }", 1), + ( + "package A { private import MiniLib::*; alias T for Thing; }", + 0, + ), + ( + "package A { private import MiniLib::*; part p : Thing; }", + 0, + ), + // An alias that fails to resolve walks the import without using it. + ( + "package A { private import MiniLib::*; alias T for Nope; }", + 1, + ), + ]; + for (body, expected) in cases { + let src = vec![("a.sysml".to_string(), body.to_string())]; + let mut fresh = Session::from_sources_with_library(src.clone(), Some(lib.clone())).unwrap(); + let unused_fresh = fresh.unused_private_imports(); + assert_eq!(unused_fresh.len(), expected, "{body}"); + let mut checked = Session::from_sources_with_library(src, Some(lib.clone())).unwrap(); + let _ = checked.check_findings(); + assert_eq!(checked.unused_private_imports(), unused_fresh, "{body}"); + } +} diff --git a/crates/sysmlv2-viz/Cargo.toml b/crates/sysmlv2-viz/Cargo.toml index ea99c2e..0aff27c 100644 --- a/crates/sysmlv2-viz/Cargo.toml +++ b/crates/sysmlv2-viz/Cargo.toml @@ -10,6 +10,8 @@ name = "sysmlv2-viz" description = "PlantUML emission for SysML v2 / KerML models" readme = "README.md" +keywords = ["sysml", "kerml", "mbse", "plantuml", "diagram"] +categories = ["visualization"] version.workspace = true edition.workspace = true rust-version.workspace = true @@ -17,8 +19,9 @@ license.workspace = true repository.workspace = true [dependencies] -sysmlv2-model = { path = "../sysmlv2-model", version = "0.6.0" } -sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.6.0" } +sysmlv2-model = { path = "../sysmlv2-model", version = "0.9.0" } +sysmlv2-syntax = { path = "../sysmlv2-syntax", version = "0.9.0" } +serde.workspace = true serde_json.workspace = true [dev-dependencies] diff --git a/crates/sysmlv2-viz/README.md b/crates/sysmlv2-viz/README.md index 42a6957..8922987 100644 --- a/crates/sysmlv2-viz/README.md +++ b/crates/sysmlv2-viz/README.md @@ -12,7 +12,7 @@ PlantUML emission for OMG SysML v2 / KerML models, over the [sysmlv2](https://gi | `case` | use cases: actors, `<>` rectangles, objectives as notes, `«include»` edges | | `mixed` | everything on one canvas: structure, connectors, behavior edges, cases, typing | -Cross-view options (`VizOptions`): comment/doc bodies as attached notes, prefix metadata as extra node stereotypes, `^`-marked inherited compartment lines, referenced library types as marked nodes, `«import»` edges, polyline/ortho line routing, a stereotype-keyed color palette, and `[[hyperlink]]` templates (`{file}`/`{line}`/`{col}`/`{qname}`/`{id}`) that PlantUML carries into rendered SVG — diagram nodes click through to their source declarations. +Cross-view options (`VizOptions`): comment/doc bodies as attached notes, prefix metadata as extra node stereotypes, `^`-marked inherited compartment lines, referenced library types as marked nodes, `«import»` edges, polyline/ortho line routing, a stereotype-keyed color palette, and `[[hyperlink]]` templates (`{file}`/`{line}`/`{col}`/`{qname}`/`{id}`) that PlantUML carries into rendered SVG — diagram nodes click through to their source declarations. Options are built from `VizOptions::default()` with one `with_…` setter per option, so a later option does not break callers. `View` and `LineStyle` carry their host spellings (`tree`, `interconnection` / `ic`, …) through `FromStr`, `Display` and serde, so a host does not have to spell out its own table. ```rust use sysmlv2_model::{json::ResolvedModel, model::Model}; @@ -21,15 +21,27 @@ use sysmlv2_viz::{plantuml, View, VizOptions}; let mut model = Model::new(); model.add_source("demo.sysml", "package P { part def V; part v : V; }"); let mut resolved = ResolvedModel::build(&model); -let text = plantuml(&mut resolved, None, &VizOptions { - view: View::Interconnection, - ..Default::default() -}); +let opts = VizOptions::default().with_view(View::Interconnection); +let text = plantuml(&mut resolved, None, &opts); // text is `@startuml … @enduml`; pipe it to plantuml.jar for SVG/PNG ``` The same emitter backs the CLI verb (`sysmlv2 viz --view …`) and the Python binding (`Session.to_plantuml(view=…)`); worked tours with real outputs live in the repository's `CLI.md` and `SDK.md`. Every view is gated by goldens and a whole-corpus sweep validated against a real PlantUML build (`cargo run -p sysmlv2-viz --example vizsweep`, then `plantuml.jar -checkonly`). +The structured `graph` API supports tree, interconnection, state and action +views. Interconnection endpoints retain their occurrence context: a flow through +`a.p.value` attaches to the rendered port on `a`, rather than the separate +`value` declaration on the port type. When deeper features are not drawn, +`sourcePath` / `targetPath` retain the complete feature-chain labels; PlantUML +emits the same information as end labels. Unresolved connector ends do not form +shortcut edges between the remaining ends. + +Behavior successions use the declaration order of their owning body, including +parts and packages that are transparent in the view. Bare `then` members follow +the preceding action, inline targets are resolved to their following declaration, +and consecutive `then` members after a fork preserve fan-out. Initial markers +reset that context; unresolved markers do not become initial transitions. + ## License Apache License 2.0 — Copyright 2026 Open-MBEE. diff --git a/crates/sysmlv2-viz/examples/vizsweep.rs b/crates/sysmlv2-viz/examples/vizsweep.rs index a3d4439..a71f75b 100644 --- a/crates/sysmlv2-viz/examples/vizsweep.rs +++ b/crates/sysmlv2-viz/examples/vizsweep.rs @@ -46,10 +46,7 @@ fn main() { .map(|c| if c.is_alphanumeric() { c } else { '_' }) .collect(); for (view, suffix) in VIEWS { - let opts = VizOptions { - view: *view, - ..Default::default() - }; + let opts = VizOptions::default().with_view(*view); let out = plantuml(&mut r, None, &opts); if out == "@startuml\n@enduml\n" { empty += 1; diff --git a/crates/sysmlv2-viz/src/behavior.rs b/crates/sysmlv2-viz/src/behavior.rs index 725b708..85b14bd 100644 --- a/crates/sysmlv2-viz/src/behavior.rs +++ b/crates/sysmlv2-viz/src/behavior.rs @@ -64,10 +64,30 @@ pub(crate) fn emit( alias: HashMap::new(), body: String::new(), edges: String::new(), + stray: Vec::new(), }; for &e in tops { em.collect(e); } + // The pass owns the stray list: nothing adds to it once collection + // is over, and holding it apart from `em` leaves the emitter free + // to mutate while each edge is written. + let stray = std::mem::take(&mut em.stray); + let contexts = edge_contexts(em.r, &stray, view); + for e in stray { + let context = contexts.get(&e); + let prev = context.and_then(|c| anchor_alias(c.source, &em.alias)); + let target = context + .and_then(|c| c.target) + .and_then(|t| em.alias.get(&t).cloned()); + let mut edges = String::new(); + if em.r.element_type(e) == "TransitionUsage" { + em.emit_transition_with(e, 0, &mut edges, prev.as_deref(), &mut None); + } else { + em.emit_edge_with(e, 0, &mut edges, prev.as_deref(), target.as_deref()); + } + em.edges.push_str(&edges); + } let (body, edges) = (em.body, em.edges); let header = crate::style_header(opts, &["state"]); frame(opts, &header, &body, &edges) @@ -81,6 +101,7 @@ struct Emitter<'a> { body: String, /// Edges outside any composite (from transparent containers). edges: String, + stray: Vec, } impl Emitter<'_> { @@ -124,9 +145,7 @@ impl Emitter<'_> { return; } if self.is_edge(ty) { - let mut edges = String::new(); - self.emit_edge(e, 0, &mut edges); - self.edges.push_str(&edges); + self.stray.push(e); return; } for m in self.r.owned_members(e) { @@ -192,6 +211,14 @@ impl Emitter<'_> { } } + let members: Vec<_> = flow + .iter() + .filter_map(|fm| match fm { + BodyFlowMember::Member(e) => Some(*e), + _ => None, + }) + .collect(); + let contexts = edge_contexts(self.r, &members, self.view); let stereos = crate::stereo_text(self.r, self.opts, e, &stereo); let link = crate::link_suffix(self.r, self.opts, e); self.indent(depth); @@ -206,7 +233,6 @@ impl Emitter<'_> { self.body.push_str(" {\n"); let mut edges = String::new(); let mut prev: Option = None; - let mut pending: Vec<(String, String)> = Vec::new(); let mut last_transition_source: Option = None; for fm in flow { match fm { @@ -224,10 +250,6 @@ impl Emitter<'_> { if self.is_node(&mty) { self.render_node(m, depth + 1); let a = self.alias_for(m); - for (src, suffix) in pending.drain(..) { - Self::indent_into(&mut edges, depth + 1); - let _ = writeln!(edges, "{src} --> {a}{suffix}"); - } prev = Some(a); } else if mty == "TransitionUsage" { self.emit_transition_with( @@ -238,12 +260,17 @@ impl Emitter<'_> { &mut last_transition_source, ); } else if self.is_edge(&mty) { + let context = contexts.get(&m); + let source = context.and_then(|c| anchor_alias(c.source, &self.alias)); + let target = context + .and_then(|c| c.target) + .and_then(|t| self.alias.get(&t).cloned()); self.emit_edge_with( m, depth + 1, &mut edges, - prev.as_deref(), - Some(&mut pending), + source.as_deref(), + target.as_deref(), ); } } @@ -295,25 +322,13 @@ impl Emitter<'_> { .find_map(|link| self.alias.get(link).cloned()) } - /// Stray edges found outside any rendered node have no flow-order - /// context: no anchor, inline-target successions dropped. - fn emit_edge(&mut self, e: ElementRef, depth: usize, out: &mut String) { - let ty = self.r.element_type(e).to_string(); - if ty == "TransitionUsage" { - let mut last = None; - self.emit_transition_with(e, depth, out, None, &mut last); - return; - } - self.emit_edge_with(e, depth, out, None, None); - } - fn emit_edge_with( &mut self, e: ElementRef, depth: usize, out: &mut String, prev: Option<&str>, - pending: Option<&mut Vec<(String, String)>>, + inline_target: Option<&str>, ) { let ty = self.r.element_type(e); let is_flow = FLOWS.contains(&ty); @@ -336,9 +351,9 @@ impl Emitter<'_> { }; let source = match ends.first() { Some(end) if end.chain.is_empty() && end.spelling.is_none() => { - // A bare source (`then x;`): the current flow anchor, or - // the initial pseudostate when nothing precedes. - Some(prev.unwrap_or("[*]").to_string()) + // Declaration-order context supplies either the preceding + // node or an explicit initial/final pseudostate. + prev.map(str::to_string) } Some(end) => self.chain_alias(&end.chain).or_else(|| pseudo(self, end)), None => None, @@ -359,15 +374,14 @@ impl Emitter<'_> { let target_end = ends.last().cloned().expect("two ends checked above"); let target = self .chain_alias(&target_end.chain) - .or_else(|| pseudo(self, &target_end)); + .or_else(|| pseudo(self, &target_end)) + .or_else(|| { + (!is_flow && target_end.chain.is_empty() && target_end.spelling.is_none()) + .then_some(inline_target) + .flatten() + .map(str::to_string) + }); let Some(target) = target else { - // An inline node declaration follows (`then fork;`, - // `then action sum { … }`): defer until it renders. - if !is_flow && target_end.chain.is_empty() && target_end.spelling.is_none() { - if let Some(pending) = pending { - pending.push((source, suffix)); - } - } return; }; Self::indent_into(out, depth); @@ -484,3 +498,81 @@ pub(crate) fn transition_edge_label( } pieces.join(" ") } + +#[derive(Clone, Copy)] +pub(crate) enum FlowAnchor { + Node(ElementRef), + Pseudo(bool), +} + +pub(crate) struct FlowContext { + pub source: Option, + pub target: Option, +} + +fn anchor_alias( + anchor: Option, + aliases: &HashMap, +) -> Option { + match anchor? { + FlowAnchor::Node(e) => aliases.get(&e).cloned(), + FlowAnchor::Pseudo(_) => Some("[*]".to_string()), + } +} + +/// Declaration-order context belongs to the owning body even when that body +/// is transparent in the selected view. Edges do not advance the anchor, so +/// consecutive bare `then` members after a fork remain a fan-out. +pub(crate) fn edge_contexts( + r: &mut ResolvedModel, + edges: &[ElementRef], + view: View, +) -> HashMap { + let owners: std::collections::HashSet<_> = edges.iter().filter_map(|&e| r.owner(e)).collect(); + let mut contexts: HashMap = HashMap::new(); + for owner in owners { + let mut anchor = Some(FlowAnchor::Pseudo(true)); + let mut pending = Vec::new(); + for member in r.body_flow_members(owner) { + match member { + BodyFlowMember::Initial(elem, spelling) => { + let name = elem + .and_then(|e| r.element_name(e).map(str::to_string)) + .or(spelling); + anchor = match name.as_deref() { + Some("start") => Some(FlowAnchor::Pseudo(true)), + Some("done") => Some(FlowAnchor::Pseudo(false)), + _ => elem.map(FlowAnchor::Node), + }; + pending.clear(); + } + BodyFlowMember::Member(e) => { + let ty = r.element_type(e); + let node = if view == View::State { + STATES.contains(&ty) + } else { + ACTIONS.contains(&ty) || CONTROL_NODES.contains(&ty) + }; + if node { + for edge in pending.drain(..) { + contexts.get_mut(&edge).unwrap().target = Some(e); + } + anchor = Some(FlowAnchor::Node(e)); + } else if matches!(ty, "SuccessionAsUsage" | "Succession") + || FLOWS.contains(&ty) + { + contexts.insert( + e, + FlowContext { + source: anchor, + target: None, + }, + ); + pending.push(e); + } + } + } + } + } + contexts +} diff --git a/crates/sysmlv2-viz/src/case.rs b/crates/sysmlv2-viz/src/case.rs index 8de3c93..4d3b679 100644 --- a/crates/sysmlv2-viz/src/case.rs +++ b/crates/sysmlv2-viz/src/case.rs @@ -10,14 +10,14 @@ //! (`use case def X { use case y; }`) render flat under a composition //! edge (`usecase` cannot nest in PlantUML). -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::fmt::Write as _; use sysmlv2_model::json::{ElementRef, ResolvedModel}; use crate::{ - VizOptions, escape, frame, inline_label, link_suffix, stereo_text, stereotype, style_header, - usage_label, + VizOptions, escape, frame, inline_label, link_suffix, note_text, stereo_text, stereotype, + style_header, usage_label, }; /// Case-family node metaclasses. @@ -38,6 +38,7 @@ pub(crate) fn emit(r: &mut ResolvedModel, tops: &[ElementRef], opts: &VizOptions r, opts, alias: HashMap::new(), + drawn: HashSet::new(), body: String::new(), edges: String::new(), notes: 0, @@ -61,6 +62,8 @@ struct Emitter<'a> { r: &'a mut ResolvedModel, opts: &'a VizOptions, alias: HashMap, + /// Every element whose node line is already in `body`. + drawn: HashSet, body: String, edges: String, /// Objective-note counter (`o1…` — disjoint from node aliases and @@ -102,10 +105,8 @@ impl Emitter<'_> { let target_alias = self.alias_for(target); let _ = writeln!(self.edges, "{owner_alias} ..> {target_alias} : «include»"); // The target renders on its own when reached; a - // forward reference draws the node lazily below. - if !self.body.contains(&format!(" as {target_alias} ")) { - self.ensure_case_node(target); - } + // forward reference draws the node lazily here. + self.ensure_case_node(target); } return; } @@ -133,8 +134,13 @@ impl Emitter<'_> { } } - /// The `usecase` node line for a case element. + /// The `usecase` node line for a case element, once — an element + /// reached both through an `«include»` reference and through the + /// containment walk keeps the single declaration it already has. fn emit_case_node(&mut self, e: ElementRef, alias: &str) { + if !self.drawn.insert(e) { + return; + } let ty = self.r.element_type(e); let stereo = stereotype(ty); let label = if ty.ends_with("Definition") { @@ -159,14 +165,11 @@ impl Emitter<'_> { /// A case referenced before (or without) its own traversal still /// gets a node. fn ensure_case_node(&mut self, e: ElementRef) { - let alias = self.alias_for(e); - let marker = format!(" as {alias} "); - if self.body.contains(&marker) { + if self.drawn.contains(&e) || !CASES.contains(&self.r.element_type(e)) { return; } - if CASES.contains(&self.r.element_type(e)) { - self.emit_case_node(e, &alias); - } + let alias = self.alias_for(e); + self.emit_case_node(e, &alias); } fn render_actor(&mut self, m: ElementRef, case_alias: &str) { @@ -212,19 +215,17 @@ impl Emitter<'_> { .collect(); self.notes += 1; let k = self.notes; - let _ = writeln!(self.edges, "note as o{k}"); let header = if label.trim().is_empty() { "«objective»".to_string() } else { format!("«objective» {}", inline_label(&label)) }; - let _ = writeln!(self.edges, "{header}"); + let mut text = escape(&header); for b in bodies { - for line in b.lines() { - let _ = writeln!(self.edges, "{line}"); - } + text.push_str("\\n"); + text.push_str(¬e_text(&b)); } - let _ = writeln!(self.edges, "end note"); + let _ = writeln!(self.edges, "note \"{text}\" as o{k}"); let _ = writeln!(self.edges, "o{k} .. {case_alias}"); } } diff --git a/crates/sysmlv2-viz/src/graph.rs b/crates/sysmlv2-viz/src/graph.rs index 45f02be..3e19179 100644 --- a/crates/sysmlv2-viz/src/graph.rs +++ b/crates/sysmlv2-viz/src/graph.rs @@ -33,6 +33,7 @@ //! "importKind"?: "membership" | "namespace" | "recursive", //! "visibility"?: "private" | "protected", // imports //! "portionKind"?: "timeslice" | "snapshot", +//! "sourcePath"?, "targetPath"?, // projected feature paths //! "sourceRole"?, "sourceMultiplicity"?, // connector ends //! "targetRole"?, "targetMultiplicity"?, //! "sourceAdornments"?, "targetAdornments"?: ["ordered", …], @@ -49,14 +50,35 @@ use crate::behavior::{ACTIONS, CONTROL_NODES, FLOWS, STATES, node_label, transit use crate::interconnect::{BLOCK_USAGES, CONNECTORS, KERML_BLOCKS}; use crate::{Kind, View, VizOptions, classify, roots_of, stereotype, usage_label}; -/// Emit the structured graph for a view. Tree and interconnection so -/// far — other views stay on the PlantUML path until they grow native -/// renderers. +/// Why [`graph`] drew nothing. +#[derive(Clone, PartialEq, Eq, Debug)] +#[non_exhaustive] +pub enum GraphError { + /// The view has no structured-graph emitter yet; it is reachable + /// through [`crate::plantuml`]. + UnsupportedView(View), +} + +impl std::fmt::Display for GraphError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + GraphError::UnsupportedView(view) => { + write!(f, "no structured-graph emitter for view: {view}") + } + } + } +} + +impl std::error::Error for GraphError {} + +/// Emit the structured graph for a view. Tree, interconnection, state +/// and action so far — other views stay on the PlantUML path until they +/// grow native renderers. pub fn graph( r: &mut ResolvedModel, root: Option, opts: &VizOptions, -) -> Result { +) -> Result { let tops = roots_of(r, root, opts); let mut aliases: HashMap> = HashMap::new(); for (name, target) in r.alias_members() { @@ -78,7 +100,7 @@ pub fn graph( } g.reference_edges(); emit_note_nodes(g.r, opts, &g.drawn, &mut g.nodes, &mut g.edges); - Ok(json!({ "view": "tree", "nodes": g.nodes, "edges": g.edges })) + Ok(json!({ "view": opts.view.as_str(), "nodes": g.nodes, "edges": g.edges })) } View::Interconnection => { let mut g = IcGraphEmitter { @@ -90,13 +112,14 @@ pub fn graph( drawn: HashMap::new(), typed_port: HashMap::new(), connectors: Vec::new(), + content: HashMap::new(), }; for e in tops { g.render(e, None); } g.connector_edges(); emit_note_nodes(g.r, opts, &g.drawn, &mut g.nodes, &mut g.edges); - Ok(json!({ "view": "interconnection", "nodes": g.nodes, "edges": g.edges })) + Ok(json!({ "view": opts.view.as_str(), "nodes": g.nodes, "edges": g.edges })) } View::State | View::Action => { let mut g = BehaviorGraphEmitter { @@ -112,14 +135,9 @@ pub fn graph( g.collect(e, None); } g.emit_edges(); - let name = if opts.view == View::State { - "state" - } else { - "action" - }; - Ok(json!({ "view": name, "nodes": g.nodes, "edges": g.edges })) + Ok(json!({ "view": opts.view.as_str(), "nodes": g.nodes, "edges": g.edges })) } - _ => Err("no structured-graph emitter for this view yet".to_string()), + view => Err(GraphError::UnsupportedView(view)), } } @@ -198,7 +216,7 @@ struct GraphEmitter<'a> { } impl GraphEmitter<'_> { - fn id_of(&mut self, e: ElementRef) -> String { + fn id_of(&self, e: ElementRef) -> String { self.r.element_id(e).to_string() } @@ -464,7 +482,9 @@ impl GraphEmitter<'_> { /// «keyword» reference edges for the shorthand usages, and /// dependency edges. fn reference_edges(&mut self) { - for (e, is_usage) in self.rendered.clone() { + // Collection is over, so the pass takes the list rather than + // copying it to keep the emitter free to mutate. + for (e, is_usage) in std::mem::take(&mut self.rendered) { let id = self.drawn[&e].clone(); let typings = if is_usage { self.r.typings(e) @@ -643,6 +663,8 @@ struct IcGraphEmitter<'a> { drawn: HashMap, typed_port: HashMap<(ElementRef, ElementRef), String>, connectors: Vec, + /// Memo of [`Self::has_content`] per element. + content: HashMap, } enum IcKind { @@ -654,7 +676,7 @@ enum IcKind { } impl IcGraphEmitter<'_> { - fn id_of(&mut self, e: ElementRef) -> String { + fn id_of(&self, e: ElementRef) -> String { self.r.element_id(e).to_string() } @@ -693,12 +715,17 @@ impl IcGraphEmitter<'_> { } /// Does `e`'s subtree contribute interconnection content? (The - /// PlantUML emitter's gate, verbatim.) + /// PlantUML emitter's gate, verbatim, memoized the same way.) fn has_content(&mut self, e: ElementRef) -> bool { + if let Some(&known) = self.content.get(&e) { + return known; + } + let mut found = false; for m in self.r.owned_members(e) { let ty = self.r.element_type(m); if ty == "PortUsage" || CONNECTORS.contains(&ty) || BLOCK_USAGES.contains(&ty) { - return true; + found = true; + break; } if (ty == "Package" || ty == "LibraryPackage" @@ -706,10 +733,12 @@ impl IcGraphEmitter<'_> { || KERML_BLOCKS.contains(&ty)) && self.has_content(m) { - return true; + found = true; + break; } } - false + self.content.insert(e, found); + found } fn render(&mut self, e: ElementRef, parent: Option<&str>) { @@ -792,31 +821,22 @@ impl IcGraphEmitter<'_> { _ => self.render(m, Some(&id)), } } - // Ports declared on the usage's definitions render on the - // usage, not shadowed by same-named owned ports. + // Ports the usage inherits through its written heritage render on + // the usage, shadowing applied (the resolver's own walk). Implied + // bases stay out (every part inherits the standard library's + // generic `ownedPorts` through its implied base), and so do the + // library's abstract port usages reached by a written + // `:> Parts::Part` — neither is structure the model declares. A + // concrete port declared by a library definition the usage is + // typed by still arrives. if is_usage { - let own_names: Vec = self + let inherited: Vec = self .r - .owned_members(e) + .inherited_features(e, false) .into_iter() .filter(|&m| self.r.element_type(m) == "PortUsage") - .filter_map(|m| self.r.element_name(m).map(str::to_string)) + .filter(|&m| !(self.r.is_library_element(m) && self.r.is_abstract(m))) .collect(); - let mut inherited = Vec::new(); - for t in self.r.typings(e) { - for m in self.r.owned_members(t) { - if self.r.element_type(m) != "PortUsage" { - continue; - } - let shadowed = self - .r - .element_name(m) - .is_some_and(|n| own_names.iter().any(|o| o == n)); - if !shadowed && !inherited.contains(&m) { - inherited.push(m); - } - } - } for p in inherited { self.render_port(p, Some(&id), Some(e)); } @@ -870,44 +890,36 @@ impl IcGraphEmitter<'_> { } } - /// The node id of the deepest rendered link of one end's feature - /// chain, per-usage port nodes included (the PlantUML emitter's - /// resolution, over ids). - fn end_node(&mut self, chain: &[ElementRef]) -> Option { - let mut best = None; - let mut context = None; - for &link in chain { - if let Some(ctx) = context { - if let Some(id) = self.typed_port.get(&(ctx, link)) { - best = Some(id.clone()); - context = None; - continue; - } - } - if let Some(id) = self.drawn.get(&link) { - best = Some(id.clone()); - context = Some(link); - } - } - best - } - fn connector_edges(&mut self) { // Per resolved end — the notation places role, multiplicity, // and c-adornment keywords at each end. struct End { node: String, role: Option, + path: Option, mult: Option, adorn: Vec, } - for c in self.connectors.clone() { + for c in std::mem::take(&mut self.connectors) { let ends = self.r.connector_end_targets(c); let mut nodes: Vec = Vec::new(); for end in &ends { - let Some(node) = self.end_node(&end.chain) else { - continue; + let projected = if end.spelling.is_none() { + crate::interconnect::project_end( + self.r, + &end.chain, + &self.drawn, + &self.typed_port, + ) + } else { + None }; + let Some((node, prefix)) = projected else { + nodes.clear(); + break; + }; + let path = + (prefix < end.chain.len()).then(|| crate::chain_label(self.r, &end.chain)); let role = self .r .element_name(end.feature) @@ -917,6 +929,7 @@ impl IcGraphEmitter<'_> { let adorn = end_adornments(self.r, end.feature); nodes.push(End { node, + path, role, mult, adorn, @@ -960,6 +973,12 @@ impl IcGraphEmitter<'_> { let mut obj = base.clone(); obj.insert("source".into(), json!(w[0].node)); obj.insert("target".into(), json!(w[1].node)); + if let Some(path) = &w[0].path { + obj.insert("sourcePath".into(), json!(path)); + } + if let Some(path) = &w[1].path { + obj.insert("targetPath".into(), json!(path)); + } if let Some(role) = &w[0].role { obj.insert("sourceRole".into(), json!(role)); } @@ -1008,7 +1027,7 @@ struct BehaviorGraphEmitter<'a> { } impl BehaviorGraphEmitter<'_> { - fn id_of(&mut self, e: ElementRef) -> String { + fn id_of(&self, e: ElementRef) -> String { self.r.element_id(e).to_string() } @@ -1156,16 +1175,21 @@ impl BehaviorGraphEmitter<'_> { } /// The `[*]` pseudostate of a scope, synthesized on first use. - fn pseudo_node(&mut self, scope: &Option, initial: bool) -> String { - let key = (scope.clone().unwrap_or_default(), initial); + fn pseudo_node( + &mut self, + scope: &Option, + initial: bool, + owner: Option, + ) -> String { + let body = owner + .map(|e| self.id_of(e)) + .or_else(|| scope.clone()) + .unwrap_or_else(|| "root".to_string()); + let key = (body.clone(), initial); if let Some(id) = self.pseudo.get(&key) { return id.clone(); } - let id = format!( - "{}~{}", - scope.as_deref().unwrap_or("root"), - if initial { "initial" } else { "final" } - ); + let id = format!("{}~{}", body, if initial { "initial" } else { "final" }); let mut obj = serde_json::Map::new(); obj.insert("id".into(), json!(id)); obj.insert("label".into(), json!("")); @@ -1185,7 +1209,13 @@ impl BehaviorGraphEmitter<'_> { } fn emit_edges(&mut self) { - for (e, scope) in self.edge_members.clone() { + // Collection is over, so the pass takes the list rather than + // copying it to keep the emitter free to mutate. + let edge_members = std::mem::take(&mut self.edge_members); + let members: Vec<_> = edge_members.iter().map(|(e, _)| *e).collect(); + let contexts = crate::behavior::edge_contexts(self.r, &members, self.view); + for (e, scope) in edge_members { + let owner = self.r.owner(e); let ty = self.r.element_type(e).to_string(); if ty == "TransitionUsage" { let parts = self.r.transition_parts(e); @@ -1228,21 +1258,39 @@ impl BehaviorGraphEmitter<'_> { } }; let target_end = ends.last().cloned().expect("two ends checked"); - let target = match self.chain_node(&target_end.chain) { + let inline_target = + (!is_flow && target_end.chain.is_empty() && target_end.spelling.is_none()) + .then(|| { + contexts + .get(&e) + .and_then(|c| c.target) + .and_then(|t| self.drawn.get(&t).cloned()) + }) + .flatten(); + let target = match self.chain_node(&target_end.chain).or(inline_target) { Some(t) => t, None => match pseudo_name(self.r, &target_end) { - Some(initial) => self.pseudo_node(&scope, initial), + Some(initial) => self.pseudo_node(&scope, initial, owner), None => continue, }, }; let source_end = ends.first().cloned().expect("two ends checked"); let source = if source_end.chain.is_empty() && source_end.spelling.is_none() { - self.pseudo_node(&scope, true) + match contexts.get(&e).and_then(|c| c.source) { + Some(crate::behavior::FlowAnchor::Node(n)) => match self.drawn.get(&n) { + Some(id) => id.clone(), + None => continue, + }, + Some(crate::behavior::FlowAnchor::Pseudo(initial)) => { + self.pseudo_node(&scope, initial, owner) + } + None => continue, + } } else { match self.chain_node(&source_end.chain) { Some(s) => s, None => match pseudo_name(self.r, &source_end) { - Some(initial) => self.pseudo_node(&scope, initial), + Some(initial) => self.pseudo_node(&scope, initial, owner), None => continue, }, } diff --git a/crates/sysmlv2-viz/src/interconnect.rs b/crates/sysmlv2-viz/src/interconnect.rs index ff5488b..478ef71 100644 --- a/crates/sysmlv2-viz/src/interconnect.rs +++ b/crates/sysmlv2-viz/src/interconnect.rs @@ -125,6 +125,7 @@ pub(crate) fn emit( connectors: Vec::new(), behavior_edges: Vec::new(), rendered: Vec::new(), + content: HashMap::new(), }; for &e in tops { em.render(e, 0); @@ -167,10 +168,12 @@ struct Emitter<'a> { behavior_edges: Vec, /// Every node drawn (mixed reference-edge pass). rendered: Vec, + /// Memo of [`Self::has_content`] per element. + content: HashMap, } impl Emitter<'_> { - fn next_alias(&mut self) -> String { + fn next_alias(&self) -> String { format!("n{}", self.alias.len() + self.typed_port_alias.len() + 1) } @@ -223,12 +226,19 @@ impl Emitter<'_> { } /// Does `e`'s subtree contribute interconnection content (a part, - /// port, or connector)? + /// port, or connector)? Memoized: the gate runs from `classify` for + /// every definition and again from `render_package`, so without the + /// memo each subtree would be re-walked once per ancestor level. fn has_content(&mut self, e: ElementRef) -> bool { + if let Some(&known) = self.content.get(&e) { + return known; + } + let mut found = false; for m in self.r.owned_members(e) { let ty = self.r.element_type(m); if ty == "PortUsage" || CONNECTORS.contains(&ty) || BLOCK_USAGES.contains(&ty) { - return true; + found = true; + break; } if (ty == "Package" || ty == "LibraryPackage" @@ -236,10 +246,12 @@ impl Emitter<'_> { || KERML_BLOCKS.contains(&ty)) && self.has_content(m) { - return true; + found = true; + break; } } - false + self.content.insert(e, found); + found } fn indent(&mut self, depth: usize) { @@ -286,7 +298,7 @@ impl Emitter<'_> { /// The node keyword for a block: `rectangle` everywhere; actor /// members read better as PlantUML actors (mixed). - fn block_keyword(&mut self, e: ElementRef) -> &'static str { + fn block_keyword(&self, e: ElementRef) -> &'static str { if self.mixed && self.r.owning_membership_type(e) == Some("ActorMembership") { "actor" } else { @@ -405,33 +417,22 @@ impl Emitter<'_> { } } - /// Ports owned by `e`'s definitions (direct typings, user or - /// library), in declaration order, not shadowed by an owned port of - /// the same name. + /// Ports `e` inherits through its *written* heritage (typings and + /// specializations, transitively), shadowing applied — the resolver's + /// own walk ([`ResolvedModel::inherited_features`]). Two kinds stay + /// out: implied bases (every part inherits the standard library's + /// generic `ownedPorts` through its implied base), and the library's + /// *abstract* port usages when a written `:> Parts::Part` reaches + /// them — neither is structure the model declares. Concrete ports + /// declared by a definition that happens to live in a loaded library + /// still arrive, because the typing that reaches them is written. fn inherited_ports(&mut self, e: ElementRef) -> Vec { - let own_names: Vec = self - .r - .owned_members(e) + self.r + .inherited_features(e, false) .into_iter() .filter(|&m| self.r.element_type(m) == "PortUsage") - .filter_map(|m| self.r.element_name(m).map(str::to_string)) - .collect(); - let mut out = Vec::new(); - for t in self.r.typings(e) { - for m in self.r.owned_members(t) { - if self.r.element_type(m) != "PortUsage" { - continue; - } - let shadowed = self - .r - .element_name(m) - .is_some_and(|n| own_names.iter().any(|o| o == n)); - if !shadowed && !out.contains(&m) { - out.push(m); - } - } - } - out + .filter(|&m| !(self.r.is_library_element(m) && self.r.is_abstract(m))) + .collect() } /// One port node. `on` is the usage box a definition port renders @@ -487,39 +488,27 @@ impl Emitter<'_> { self.rendered.push(e); } - /// The alias of the deepest rendered link of one end's feature - /// chain, tracking the usage context so definition ports resolve to - /// their per-usage node (`tank.fuelOut` → the `fuelOut` port on the - /// `tank` box). fn end_alias(&mut self, chain: &[ElementRef]) -> Option { - let mut best = None; - let mut context = None; - for &link in chain { - // A definition port reached through a usage names *that - // usage's* port node, not the definition's own — the - // per-usage alias wins over the link's global one. - if let Some(ctx) = context { - if let Some(a) = self.typed_port_alias.get(&(ctx, link)) { - best = Some(a.clone()); - context = None; - continue; - } - } - if let Some(a) = self.alias.get(&link) { - best = Some(a.clone()); - context = Some(link); - } - } - best + project_end(self.r, chain, &self.alias, &self.typed_port_alias).map(|(id, _)| id) } fn emit_connector_edges(&mut self) { - for c in self.connectors.clone() { + // Collection is over, so the pass takes the list rather than + // copying it to keep the emitter free to mutate. + for c in std::mem::take(&mut self.connectors) { let ends = self.r.connector_end_targets(c); - let aliases: Vec = ends + let Some(aliases): Option> = ends .iter() - .filter_map(|end| self.end_alias(&end.chain)) - .collect(); + .map(|end| { + if end.spelling.is_some() { + return None; + } + project_end(self.r, &end.chain, &self.alias, &self.typed_port_alias) + }) + .collect() + else { + continue; + }; if aliases.len() < 2 { continue; } @@ -553,8 +542,24 @@ impl Emitter<'_> { } else { format!(" : {}", inline_label(&label)) }; - for w in aliases.windows(2) { - let _ = writeln!(self.edges, "{} {arrow} {}{suffix}", w[0], w[1]); + for (at, w) in aliases.windows(2).enumerate() { + let end_label = |at: usize, projected: &(String, usize)| { + if projected.1 < ends[at].chain.len() { + format!( + " \"{}\"", + escape(&crate::chain_label(self.r, &ends[at].chain)) + ) + } else { + String::new() + } + }; + let source_label = end_label(at, &w[0]); + let target_label = end_label(at + 1, &w[1]); + let _ = writeln!( + self.edges, + "{}{source_label} {arrow}{target_label} {}{suffix}", + w[0].0, w[1].0 + ); } } } @@ -562,7 +567,7 @@ impl Emitter<'_> { /// Succession and transition edges (mixed). The component dialect /// has no `[*]` pseudostate, so unspelled ends drop their edge. fn emit_behavior_edges(&mut self) { - for e in self.behavior_edges.clone() { + for e in std::mem::take(&mut self.behavior_edges) { if self.r.element_type(e) == "TransitionUsage" { let parts = self.r.transition_parts(e); let (Some(src), Some(tgt)) = ( @@ -603,7 +608,7 @@ impl Emitter<'_> { /// Typing / specialization / stereotyped reference / import edges /// between rendered nodes (mixed). fn emit_reference_edges(&mut self) { - for e in self.rendered.clone() { + for e in std::mem::take(&mut self.rendered) { let alias = self.alias[&e].clone(); let ty = self.r.element_type(e); let is_usage = !ty.ends_with("Definition") && !KERML_BLOCKS.contains(&ty); @@ -668,3 +673,32 @@ impl Emitter<'_> { Some(alias) } } + +/// Project a chain onto its deepest rendered occurrence. Crossing into a +/// type's member must not jump to that member's separate declaration box. +/// The returned prefix length lets callers retain the unrendered feature path. +pub(crate) fn project_end( + r: &mut ResolvedModel, + chain: &[ElementRef], + drawn: &HashMap, + typed_ports: &HashMap<(ElementRef, ElementRef), String>, +) -> Option<(String, usize)> { + let mut best = None; + let mut context = None; + for (i, &link) in chain.iter().enumerate() { + if let Some(ctx) = context { + if let Some(id) = typed_ports.get(&(ctx, link)) { + // Per-usage port chips have no rendered descendants. + return Some((id.clone(), i + 1)); + } + if r.owner(link) != Some(ctx) { + break; + } + } + if let Some(id) = drawn.get(&link) { + best = Some((id.clone(), i + 1)); + } + context = Some(link); + } + best +} diff --git a/crates/sysmlv2-viz/src/lib.rs b/crates/sysmlv2-viz/src/lib.rs index 95b2ddc..a1d0e61 100644 --- a/crates/sysmlv2-viz/src/lib.rs +++ b/crates/sysmlv2-viz/src/lib.rs @@ -46,11 +46,14 @@ mod graph; mod interconnect; mod sequence; -pub use graph::graph; +pub use graph::{GraphError, graph}; use std::collections::HashMap; +use std::fmt; use std::fmt::Write as _; +use std::str::FromStr; +use serde::{Deserialize, Serialize}; use sysmlv2_model::eval::Value; use sysmlv2_model::json::{ElementRef, ResolvedModel}; @@ -63,18 +66,32 @@ pub enum Direction { } /// Which diagram to emit (the Pilot Implementation's view repertoire). -#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] +/// +/// The variants carry the spelling hosts use on a command line or in an +/// options object, through [`FromStr`], [`Display`](fmt::Display) and +/// serde: +/// +/// ``` +/// use sysmlv2_viz::View; +/// +/// assert_eq!("ic".parse::().unwrap(), View::Interconnection); +/// assert_eq!(View::Interconnection.to_string(), "interconnection"); +/// ``` +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] pub enum View { /// Structure ("tree") view: packages, definitions, usages. #[default] Tree, /// Parts, ports, and connector edges. + #[serde(alias = "ic")] Interconnection, /// State machines: states, transitions, entry/do/exit. State, /// Action flows: actions, control nodes, successions, flows. Action, /// Lifelines and messages, ordered by event successions. + #[serde(alias = "seq")] Sequence, /// Use cases: actors, subjects, objectives, includes. Case, @@ -83,8 +100,63 @@ pub enum View { Mixed, } +impl View { + /// The spelling of each view, canonical spellings only. + const SPELLINGS: &'static [(&'static str, View)] = &[ + ("tree", View::Tree), + ("interconnection", View::Interconnection), + ("state", View::State), + ("action", View::Action), + ("sequence", View::Sequence), + ("case", View::Case), + ("mixed", View::Mixed), + ]; + + /// The short spellings hosts also accept, beside the canonical ones. + const SHORTHANDS: &'static [(&'static str, View)] = + &[("ic", View::Interconnection), ("seq", View::Sequence)]; + + /// The canonical spelling — what [`Display`](fmt::Display), serde + /// and the structured graph's `view` field write. Matched rather + /// than looked up, so a view added without a spelling is a compile + /// error instead of a silent misspelling of another one. + pub fn as_str(self) -> &'static str { + match self { + View::Tree => "tree", + View::Interconnection => "interconnection", + View::State => "state", + View::Action => "action", + View::Sequence => "sequence", + View::Case => "case", + View::Mixed => "mixed", + } + } +} + +impl fmt::Display for View { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +impl FromStr for View { + type Err = ParseOptionError; + + fn from_str(s: &str) -> Result { + Self::SPELLINGS + .iter() + .chain(Self::SHORTHANDS) + .find(|(spelling, _)| *spelling == s) + .map(|(_, v)| *v) + .ok_or_else(|| ParseOptionError::new("view", s, Self::SPELLINGS)) + } +} + /// Edge routing (PlantUML `skinparam linetype`). -#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)] +/// +/// Spelled the same way as [`View`] on every host surface. +#[derive(Clone, Copy, PartialEq, Eq, Debug, Default, Serialize, Deserialize)] +#[serde(rename_all = "lowercase")] pub enum LineStyle { /// PlantUML's default splines. #[default] @@ -93,10 +165,108 @@ pub enum LineStyle { Ortho, } +impl LineStyle { + const SPELLINGS: &'static [(&'static str, LineStyle)] = &[ + ("default", LineStyle::Default), + ("polyline", LineStyle::Polyline), + ("ortho", LineStyle::Ortho), + ]; + + /// The canonical spelling — what [`Display`](fmt::Display) and + /// serde write. Matched rather than looked up, for the reason + /// [`View::as_str`] gives. + pub fn as_str(self) -> &'static str { + match self { + LineStyle::Default => "default", + LineStyle::Polyline => "polyline", + LineStyle::Ortho => "ortho", + } + } +} + +impl fmt::Display for LineStyle { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.write_str(self.as_str()) + } +} + +impl FromStr for LineStyle { + type Err = ParseOptionError; + + fn from_str(s: &str) -> Result { + Self::SPELLINGS + .iter() + .find(|(spelling, _)| *spelling == s) + .map(|(_, v)| *v) + .ok_or_else(|| ParseOptionError::new("line style", s, Self::SPELLINGS)) + } +} + +/// A spelling that names no member of one of the option enums — +/// the error of [`View`]'s and [`LineStyle`]'s [`FromStr`]. +#[derive(Clone, PartialEq, Eq, Debug)] +pub struct ParseOptionError { + option: &'static str, + spelling: String, + expected: Vec<&'static str>, +} + +impl ParseOptionError { + fn new(option: &'static str, spelling: &str, expected: &[(&'static str, T)]) -> Self { + ParseOptionError { + option, + spelling: spelling.to_string(), + expected: expected.iter().map(|(s, _)| *s).collect(), + } + } + + /// What was being named: `view`, `line style`. + pub fn option(&self) -> &str { + self.option + } + + /// The spelling that named nothing. + pub fn spelling(&self) -> &str { + &self.spelling + } + + /// The canonical spellings, in declaration order. + pub fn expected(&self) -> &[&'static str] { + &self.expected + } +} + +impl fmt::Display for ParseOptionError { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "unknown {}: {}", self.option, self.spelling)?; + match self.expected.split_last() { + Some((last, [])) => write!(f, " (expected {last})"), + Some((last, rest)) => write!(f, " (expected {}, or {last})", rest.join(", ")), + None => Ok(()), + } + } +} + +impl std::error::Error for ParseOptionError {} + /// Options for [`plantuml`]. `show_values` renders `= value` on /// attribute lines when the attribute's value expression evaluates to a /// scalar (evaluation failures are silently skipped; tree view only). +/// +/// Build one from [`VizOptions::default`] and the `with_…` setters, so +/// that a later option does not break callers: +/// +/// ``` +/// use sysmlv2_viz::{View, VizOptions}; +/// +/// let opts = VizOptions::default() +/// .with_view(View::Case) +/// .with_show_notes(false); +/// assert_eq!(opts.view, View::Case); +/// assert!(!opts.show_notes); +/// ``` #[derive(Clone, Debug)] +#[non_exhaustive] pub struct VizOptions { pub direction: Direction, pub show_values: bool, @@ -151,6 +321,83 @@ impl Default for VizOptions { } } +/// One setter per option, each consuming and returning the options so +/// they chain from [`VizOptions::default`]. +impl VizOptions { + /// Layout direction. + pub fn with_direction(mut self, direction: Direction) -> VizOptions { + self.direction = direction; + self + } + + /// Render `= value` on attribute lines. + pub fn with_show_values(mut self, on: bool) -> VizOptions { + self.show_values = on; + self + } + + /// Which diagram to emit. + pub fn with_view(mut self, view: View) -> VizOptions { + self.view = view; + self + } + + /// Attach comment/documentation bodies as notes. + pub fn with_show_notes(mut self, on: bool) -> VizOptions { + self.show_notes = on; + self + } + + /// Show metadata as stereotypes and nodes. + pub fn with_show_metadata(mut self, on: bool) -> VizOptions { + self.show_metadata = on; + self + } + + /// Add inherited compartment lines. + pub fn with_show_inherited(mut self, on: bool) -> VizOptions { + self.show_inherited = on; + self + } + + /// Give referenced library types their own marked nodes. + pub fn with_show_lib(mut self, on: bool) -> VizOptions { + self.show_lib = on; + self + } + + /// Draw `«import»` edges. + pub fn with_show_imported(mut self, on: bool) -> VizOptions { + self.show_imported = on; + self + } + + /// Edge routing. + pub fn with_line_style(mut self, line_style: LineStyle) -> VizOptions { + self.line_style = line_style; + self + } + + /// Color nodes by metaclass family. + pub fn with_std_color(mut self, on: bool) -> VizOptions { + self.std_color = on; + self + } + + /// Hyperlink template for node declarations; `None` draws no links. + pub fn with_link_template(mut self, link_template: Option) -> VizOptions { + self.link_template = link_template; + self + } + + /// Restrict the diagram to these top-level elements; `None` or + /// empty is the whole model. + pub fn with_roots(mut self, roots: Option>) -> VizOptions { + self.roots = roots; + self + } +} + /// What a *view usage* directs: the rendering style its `render` member /// requests (when it maps onto a PlantUML view) and the diagram roots its /// `expose`/`filter` members admit. Exposure reduces to the finest @@ -333,7 +580,7 @@ const LINE_USAGES: &[&str] = &["AttributeUsage", "ReferenceUsage", "EnumerationU /// PlantUML tree emitter and the structured graph emitter, so the two /// backends can never disagree about what is a node, a compartment /// line, or invisible. -pub(crate) fn classify(r: &mut ResolvedModel, show_metadata: bool, e: ElementRef) -> Kind { +pub(crate) fn classify(r: &ResolvedModel, show_metadata: bool, e: ElementRef) -> Kind { let ty = r.element_type(e); match ty { _ if !show_metadata && matches!(ty, "MetadataUsage" | "MetadataFeature") => Kind::Skip, @@ -378,7 +625,7 @@ impl Emitter<'_> { a } - fn classify(&mut self, e: ElementRef) -> Kind { + fn classify(&self, e: ElementRef) -> Kind { classify(self.r, self.opts.show_metadata, e) } @@ -589,7 +836,10 @@ impl Emitter<'_> { /// (their names already appear in node labels) — `show_lib` gives /// referenced library types their own marked nodes instead. fn emit_reference_edges(&mut self) { - for (e, is_usage) in self.rendered.clone() { + // Collection is over, so the pass takes the list rather than + // copying it to keep the emitter free to mutate. + let rendered = std::mem::take(&mut self.rendered); + for &(e, is_usage) in &rendered { let alias = self.alias[&e].clone(); let typings = if is_usage { self.r.typings(e) @@ -619,6 +869,11 @@ impl Emitter<'_> { } } } + // Library nodes drawn on demand during the pass were appended + // to the emptied list; the walked nodes go back in front of + // them, so the node list stays complete and in draw order. + let drawn_during = std::mem::replace(&mut self.rendered, rendered); + self.rendered.extend(drawn_during); } /// The alias an edge target draws to: its node when rendered; under @@ -710,12 +965,14 @@ pub(crate) fn value_suffix(r: &mut ResolvedModel, e: ElementRef) -> Option b.to_string(), Value::Integer(i) => i.to_string(), - Value::Rational(f) => format!("{f}"), + Value::Rational(r) => r.to_string(), + Value::Real(f) => format!("{f}"), Value::String(s) => format!("\"{s}\""), Value::Quantity(n, unit) => { let magnitude = match *n { Value::Integer(i) => i.to_string(), - Value::Rational(f) => format!("{f}"), + Value::Rational(r) => r.to_string(), + Value::Real(f) => format!("{f}"), _ => return None, }; format!("{magnitude} [{}]", unit.display()) @@ -778,7 +1035,7 @@ pub(crate) fn stereotype(ty: &str) -> String { /// The dotted spelling of a resolved feature chain (`a.b`) — edge-end /// and reference labels. -pub(crate) fn chain_label(r: &mut ResolvedModel, chain: &[ElementRef]) -> String { +pub(crate) fn chain_label(r: &ResolvedModel, chain: &[ElementRef]) -> String { chain .iter() .filter_map(|&link| r.element_name(link).map(str::to_string)) @@ -802,9 +1059,47 @@ pub(crate) fn payload_label(r: &mut ResolvedModel, e: ElementRef) -> Option String { - s.replace('"', "''") + let mut out = String::with_capacity(s.len()); + for ch in s.chars() { + match ch { + '\\' => out.push_str("\\\\"), + '"' => out.push_str("''"), + '\n' => out.push_str("\\n"), + '\r' => {} + c => out.push(c), + } + } + out +} + +/// Percent-encode the characters that would end or restructure a +/// `[[url]]` link: whitespace (ends the URL part), `]` (closes the +/// link), and braces (open a tooltip). +fn encode_link(url: &str) -> String { + let mut out = String::with_capacity(url.len()); + for ch in url.chars() { + match ch { + ' ' => out.push_str("%20"), + '\t' => out.push_str("%09"), + '\n' => out.push_str("%0A"), + '\r' => out.push_str("%0D"), + ']' => out.push_str("%5D"), + '{' => out.push_str("%7B"), + '}' => out.push_str("%7D"), + c => out.push(c), + } + } + out } /// The STDCOLOR palette: stereotype → background color, one hue family @@ -883,7 +1178,7 @@ pub(crate) fn link_suffix(r: &mut ResolvedModel, opts: &VizOptions, e: ElementRe if url.contains("{id}") { url = url.replace("{id}", &r.element_id(e).to_string()); } - format!(" [[{}]]", url.replace(' ', "%20")) + format!(" [[{}]]", encode_link(&url)) } /// `<>` plus one `<>` per prefix metadata annotating `e` @@ -921,7 +1216,7 @@ pub(crate) fn stereo_text( out } -/// Floating `note` blocks for every comment/documentation body whose +/// Floating notes for every comment/documentation body whose /// annotated element is on the diagram (`alias` map), attached with /// `..`. Note aliases are `c1…` — disjoint from the node `n…` space. pub(crate) fn emit_notes( @@ -939,26 +1234,31 @@ pub(crate) fn emit_notes( continue; }; k += 1; - let _ = writeln!(out, "note as c{k}"); - for line in body.lines() { - // A body line PlantUML would read as the block terminator - // gets an indent. - if line.trim() == "end note" { - let _ = writeln!(out, " {line}"); - } else { - let _ = writeln!(out, "{line}"); - } - } - let _ = writeln!(out, "end note"); + let _ = writeln!(out, "note \"{}\" as c{k}", note_text(&body)); let _ = writeln!(out, "c{k} .. {a}"); } } +/// A note body as the text of a quoted single-line `note "…" as x`: +/// one `\n` escape per line break. The block form (`note as x` … +/// `end note`) is not used because the renderer ends it at any body +/// line spelling the terminator (`end note`, `endnote`, in any case, +/// after any indent) and reads the rest as diagram commands; inside +/// quotes no body text can end the note. +pub(crate) fn note_text(body: &str) -> String { + body.lines().map(escape).collect::>().join("\\n") +} + /// Compartment lines are unquoted PlantUML member syntax; strip the /// characters that would change their parse (braces open a block, -/// leading `-`/`+`/`#` set visibility). +/// leading `-`/`+`/`#` set visibility, a line break ends the member — +/// it becomes a space; a carriage return is dropped). fn sanitize_line(s: &str) -> String { - let cleaned: String = s.chars().filter(|c| *c != '{' && *c != '}').collect(); + let cleaned: String = s + .chars() + .filter(|c| !matches!(c, '{' | '}' | '\r')) + .map(|c| if c == '\n' { ' ' } else { c }) + .collect(); let trimmed = cleaned.trim().to_string(); match trimmed.chars().next() { Some('-') | Some('+') | Some('#') | Some('~') => format!("\\{trimmed}"), diff --git a/crates/sysmlv2-viz/tests/emitter_walks.rs b/crates/sysmlv2-viz/tests/emitter_walks.rs new file mode 100644 index 0000000..c086467 --- /dev/null +++ b/crates/sysmlv2-viz/tests/emitter_walks.rs @@ -0,0 +1,90 @@ +//! Behaviour gates for the emitters' subtree walks and node +//! bookkeeping: the interconnection content gate (which packages and +//! definitions render, in text and graph form) and the case view's node +//! set (a case referenced before its declaration draws exactly once). + +use sysmlv2_model::json::ResolvedModel; +use sysmlv2_model::model::Model; +use sysmlv2_viz::{View, VizOptions, graph, plantuml}; + +fn resolved(src: &str) -> ResolvedModel { + let mut model = Model::new(); + let unit = model.add_source("walks.sysml".to_string(), src); + assert!( + unit.diagnostics.is_empty(), + "fixture must parse: {:?}", + unit.diagnostics + ); + ResolvedModel::build(&model) +} + +/// Content sits three containers deep (`Inner`'s port), beside empty +/// siblings at every level. +const NESTED: &str = "package Outer { + package Empty { part def NoContent; attribute def Plain; } + package Deep { + part def Shell { part def Inner { port p; } } + part def Bare; + } + part def Top { part sub; } +} +"; + +#[test] +fn interconnection_gate_renders_only_containers_with_content() { + let mut r = resolved(NESTED); + let opts = VizOptions::default().with_view(View::Interconnection); + let out = plantuml(&mut r, None, &opts); + let expected = "@startuml +package \"Outer\" as n1 { + package \"Deep\" as n2 { + rectangle \"Shell\" as n3 <> { + rectangle \"Inner\" as n4 <> { + port \"p\" as n5 + } + } + } + rectangle \"Top\" as n6 <> { + rectangle \"sub\" as n7 <> + } +} +@enduml +"; + assert_eq!(out, expected); + + let g = graph(&mut r, None, &opts).unwrap(); + let labels: Vec<&str> = g["nodes"] + .as_array() + .unwrap() + .iter() + .map(|n| n["label"].as_str().unwrap()) + .collect(); + assert_eq!( + labels, + ["Outer", "Deep", "Shell", "Inner", "p", "Top", "sub"] + ); +} + +/// An `include` reaching a case declared later in the package draws +/// that case once: the reference draws it lazily, and the containment +/// walk that reaches it afterwards keeps the declaration it has. +#[test] +fn case_view_draws_an_included_case_once() { + let mut r = resolved( + "package Ops { + use case def Drive { include unlock; } + use case unlock : UnlockVehicle; + use case def UnlockVehicle; +} +", + ); + let out = plantuml(&mut r, None, &VizOptions::default().with_view(View::Case)); + let expected = "@startuml +usecase \"Drive\" as n1 <> +usecase \"unlock : UnlockVehicle\" as n2 <> +usecase \"UnlockVehicle\" as n3 <> +n1 ..> n2 : «include» +@enduml +"; + assert_eq!(out, expected); +} diff --git a/crates/sysmlv2-viz/tests/endpoint_semantics.rs b/crates/sysmlv2-viz/tests/endpoint_semantics.rs new file mode 100644 index 0000000..c5dc453 --- /dev/null +++ b/crates/sysmlv2-viz/tests/endpoint_semantics.rs @@ -0,0 +1,344 @@ +use sysmlv2_model::{json::ResolvedModel, model::Model}; +use sysmlv2_viz::{View, VizOptions, graph, plantuml}; + +fn resolved(src: &str) -> ResolvedModel { + let mut m = Model::new(); + let unit = m.add_source("endpoints.sysml", src); + assert!(unit.diagnostics.is_empty(), "{:?}", unit.diagnostics); + ResolvedModel::build(&m) +} + +const INTERFACE: &str = "item def Item1; item def Item2; +port def Pa { out item i1Out : Item1; in item i2In : Item2; } +interface def Interface2 { + end supplierP : Pa; end consumerP : ~Pa; + flow supplierP.i1Out to consumerP.i1Out; + flow consumerP.i2In to supplierP.i2In; +}"; + +#[test] +fn interface_flow_paths_retain_distinct_port_occurrences() { + let opts = VizOptions::default().with_view(View::Interconnection); + for scoped in [false, true] { + let mut r = resolved(INTERFACE); + let root = if scoped { + r.resolve_qualified("Interface2") + } else { + None + }; + let g = graph(&mut r, root, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let id = |name| nodes.iter().find(|n| n["qname"] == name).unwrap()["id"].clone(); + let edges = g["edges"].as_array().unwrap(); + assert_eq!(edges.len(), 2); + for (edge, (src, tgt, sp, tp)) in edges.iter().zip([ + ( + "Interface2::supplierP", + "Interface2::consumerP", + "supplierP.i1Out", + "consumerP.i1Out", + ), + ( + "Interface2::consumerP", + "Interface2::supplierP", + "consumerP.i2In", + "supplierP.i2In", + ), + ]) { + assert_eq!(edge["source"], id(src)); + assert_eq!(edge["target"], id(tgt)); + assert_eq!(edge["sourcePath"], sp); + assert_eq!(edge["targetPath"], tp); + assert_eq!(edge["directed"], true); + let e = r.element_by_id(edge["id"].as_str().unwrap()).unwrap(); + assert_eq!(r.element_type(e), "FlowUsage"); + assert_eq!(r.declaration_position(e).unwrap().0, "endpoints.sysml"); + } + let uml = plantuml(&mut r, root, &opts); + assert!( + uml.contains("\"supplierP.i1Out\" --> \"consumerP.i1Out\""), + "{uml}" + ); + assert!( + uml.contains("\"consumerP.i2In\" --> \"supplierP.i2In\""), + "{uml}" + ); + } +} + +#[test] +fn inherited_ports_keep_usage_context_and_incomplete_paths_do_not_fabricate_edges() { + let mut r = resolved( + "port def P { item value; } + part def Device { port p : P; } + part a : Device; part b : Device; + flow a.p.value to b.p.value; + flow a.p.missing to b.p.value; + connect (a.p, missing, b.p);", + ); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let edges = g["edges"].as_array().unwrap(); + assert_eq!(edges.len(), 1, "{g}"); + let edge = &edges[0]; + for (side, owner) in [("source", "a"), ("target", "b")] { + let port = nodes.iter().find(|n| n["id"] == edge[side]).unwrap(); + let parent = nodes.iter().find(|n| n["id"] == port["parent"]).unwrap(); + assert_eq!(parent["qname"], owner); + assert_eq!(port["qname"], "Device::p"); + } + let uml = plantuml(&mut r, None, &opts); + assert_eq!( + uml.lines().filter(|l| l.contains(" --> ")).count(), + 1, + "{uml}" + ); +} + +#[test] +fn performed_action_succession_uses_each_transparent_body() { + let src = "part def PartDef2; + part part2 : PartDef2 { perform action action2; then perform action action3; } + part separate { perform action unrelated; } + part third { then perform action initialStep; } + part fourth { then perform action initialStep; }"; + let mut r = resolved(src); + let opts = VizOptions::default().with_view(View::Action); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let id = |name| nodes.iter().find(|n| n["qname"] == name).unwrap()["id"].clone(); + let edges = g["edges"].as_array().unwrap(); + assert_eq!(edges.len(), 3, "{g}"); + let edge = edges + .iter() + .find(|e| e["target"] == id("part2::action3")) + .unwrap(); + assert_eq!(edge["source"], id("part2::action2")); + assert_eq!(edge["kind"], "succession"); + assert!(r.element_by_id(edge["id"].as_str().unwrap()).is_some()); + let initial = edges + .iter() + .find(|e| e["target"] == id("third::initialStep")) + .unwrap(); + assert!( + nodes + .iter() + .any(|n| n["id"] == initial["source"] && n["kind"] == "pseudo") + ); + let other = edges + .iter() + .find(|e| e["target"] == id("fourth::initialStep")) + .unwrap(); + assert_ne!( + initial["source"], other["source"], + "transparent bodies retain separate initial nodes" + ); + let uml = plantuml(&mut r, None, &opts); + assert_eq!( + uml.lines().filter(|l| l.contains(" --> ")).count(), + 3, + "{uml}" + ); +} + +#[test] +fn native_action_anchors_preserve_fanout_initial_reset_and_unresolved_sources() { + let mut r = resolved( + "action def A { + action a; then b; action b; + first start; then fork; then a; then b; + join junction; then action wrap; + first missing; then wrap; + first missing then a; + }", + ); + let opts = VizOptions::default().with_view(View::Action); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let id = |label| nodes.iter().find(|n| n["label"] == label).unwrap()["id"].clone(); + let edges = g["edges"].as_array().unwrap(); + assert_eq!(edges.len(), 5, "{g}"); + for (s, t) in [ + ("a", "b"), + ("(fork)", "a"), + ("(fork)", "b"), + ("junction", "wrap"), + ] { + assert!( + edges + .iter() + .any(|e| e["source"] == id(s) && e["target"] == id(t)), + "{s} -> {t}: {g}" + ); + } + assert!(edges.iter().any(|e| { + e["target"] == id("(fork)") + && nodes + .iter() + .any(|n| n["id"] == e["source"] && n["kind"] == "pseudo") + })); + let uml = plantuml(&mut r, None, &opts); + assert_eq!( + uml.lines().filter(|l| l.contains(" --> ")).count(), + 5, + "{uml}" + ); +} + +#[test] +fn owned_nested_ports_still_resolve_to_the_deepest_drawn_node() { + let mut r = resolved( + "part outer { part inner { port p; } } part peer { port q; } + connect outer.inner.p to peer.q;", + ); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let edges = g["edges"].as_array().unwrap(); + assert_eq!(edges.len(), 1); + for (side, qname) in [("source", "outer::inner::p"), ("target", "peer::q")] { + assert!( + nodes + .iter() + .any(|n| n["qname"] == qname && n["id"] == edges[0][side]) + ); + } + assert!(edges[0]["sourcePath"].is_null()); + assert!(edges[0]["targetPath"].is_null()); +} + +#[test] +fn transitively_inherited_ports_render_once_and_redefinitions_shadow() { + let mut r = resolved( + "port def P; + part def Base { port p : P; } + part def Mid :> Base; + part def Leaf :> Mid; + part x : Leaf; + part z : Leaf { port :>> p; }", + ); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let ports_under = |owner: &str| -> Vec { + let parent = nodes.iter().find(|n| n["qname"] == owner).unwrap(); + nodes + .iter() + .filter(|n| n["parent"] == parent["id"] && n["kind"] == "port") + .map(|n| n["qname"].as_str().unwrap_or("").to_string()) + .collect() + }; + // Two levels up the definition hierarchy, one hop through the typing. + assert_eq!(ports_under("x"), ["Base::p"], "{g}"); + // The owned redefinition shadows the inherited port: one node, not two. + assert_eq!(ports_under("z").len(), 1, "{g}"); + assert_ne!(ports_under("z"), ["Base::p"], "{g}"); +} + +#[test] +fn library_owned_ports_stay_out_of_diagrams() { + let lib = sysmlv2_testkit::library_dir(); + if !lib.exists() { + eprintln!("skipping: corpus not present"); + return; + } + let mut m = Model::new(); + m.load_library_dir(&lib).expect("library loads"); + m.add_source( + "endpoints.sysml", + "package Q { port def P; part def Device { port p : P; } part d : Device; }", + ); + let mut r = ResolvedModel::build(&m); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let usage = nodes.iter().find(|n| n["qname"] == "Q::d").unwrap(); + let on_usage: Vec<&str> = nodes + .iter() + .filter(|n| n["kind"] == "port" && n["parent"] == usage["id"]) + .filter_map(|n| n["qname"].as_str()) + .collect(); + // The declared port arrives through the typing; the library's generic + // `ownedPorts`, which every part inherits through its implied base, + // does not — on this usage or anywhere else in the diagram. + assert_eq!(on_usage, ["Q::Device::p"], "{g}"); + assert!( + nodes + .iter() + .filter(|n| n["kind"] == "port") + .all(|n| !n["qname"].as_str().unwrap_or("").contains("ownedPorts")), + "{g}" + ); +} + +#[test] +fn ports_declared_by_a_domain_library_definition_still_render() { + // A definition loaded from a library directory is a library element, + // but a usage typed by it reaches its ports through *written* + // heritage, so they render — only implied library bases stay out. + let dir = std::env::temp_dir().join(format!( + "sysmlv2-viz-domlib-{}-{}", + std::process::id(), + std::time::SystemTime::now() + .duration_since(std::time::UNIX_EPOCH) + .unwrap() + .as_nanos() + )); + std::fs::create_dir_all(&dir).unwrap(); + std::fs::write( + dir.join("DomLib.sysml"), + "package DomLib { port def DP; part def Device { port dp : DP; } }", + ) + .unwrap(); + let mut m = Model::new(); + m.load_library_dir(&dir).expect("domain library loads"); + let _ = std::fs::remove_dir_all(&dir); + m.add_source("u.sysml", "package Q { part d : DomLib::Device; }"); + let mut r = ResolvedModel::build(&m); + let device = r.resolve_qualified("DomLib::Device").unwrap(); + assert!(r.is_library_element(device)); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let usage = nodes.iter().find(|n| n["qname"] == "Q::d").unwrap(); + let on_usage: Vec<&str> = nodes + .iter() + .filter(|n| n["kind"] == "port" && n["parent"] == usage["id"]) + .filter_map(|n| n["qname"].as_str()) + .collect(); + assert_eq!(on_usage, ["DomLib::Device::dp"], "{g}"); +} + +#[test] +fn written_specialization_of_a_library_part_keeps_abstract_library_ports_out() { + let lib = sysmlv2_testkit::library_dir(); + if !lib.exists() { + eprintln!("skipping: corpus not present"); + return; + } + let mut m = Model::new(); + m.load_library_dir(&lib).expect("library loads"); + // `Parts::Part` declares `abstract port ownedPorts`; a written + // `:> Parts::Part` reaches it through explicit heritage, and it must + // still not render — only the model's own port does. + m.add_source( + "endpoints.sysml", + "package Q { + port def P; + part def Vehicle :> Parts::Part { port p : P; } + part v : Vehicle; + }", + ); + let mut r = ResolvedModel::build(&m); + let opts = VizOptions::default().with_view(View::Interconnection); + let g = graph(&mut r, None, &opts).unwrap(); + let nodes = g["nodes"].as_array().unwrap(); + let usage = nodes.iter().find(|n| n["qname"] == "Q::v").unwrap(); + let on_usage: Vec<&str> = nodes + .iter() + .filter(|n| n["kind"] == "port" && n["parent"] == usage["id"]) + .filter_map(|n| n["qname"].as_str()) + .collect(); + assert_eq!(on_usage, ["Q::Vehicle::p"], "{g}"); +} diff --git a/crates/sysmlv2-viz/tests/escaping.rs b/crates/sysmlv2-viz/tests/escaping.rs new file mode 100644 index 0000000..9ab0837 --- /dev/null +++ b/crates/sysmlv2-viz/tests/escaping.rs @@ -0,0 +1,233 @@ +//! Label and note escaping gates: names carrying line breaks, carriage +//! returns, quotes and brackets reach every PlantUML emitter that +//! quotes labels without breaking the diagram text, link URLs stay +//! inside their `[[…]]`, and note bodies can spell the note terminator. + +use sysmlv2_model::json::ResolvedModel; +use sysmlv2_model::model::Model; +use sysmlv2_viz::{View, VizOptions, plantuml}; + +fn resolved_named(name: &str, src: &str) -> ResolvedModel { + let mut model = Model::new(); + let unit = model.add_source(name.to_string(), src); + assert!( + unit.diagnostics.is_empty(), + "fixture must parse: {:?}", + unit.diagnostics + ); + ResolvedModel::build(&model) +} + +fn resolved(src: &str) -> ResolvedModel { + resolved_named("odd.sysml", src) +} + +fn view_opts(view: View) -> VizOptions { + VizOptions::default().with_view(view) +} + +/// Names whose escape sequences the lexer decodes into real line +/// breaks, carriage returns and quotes. +const ODD: &str = r#"package 'Pkg\nOne' { + part def 'Def "Q"\r\n[x]' { + attribute 'att\nr' = "va\nl"; + part 'sub\npart' : 'Def "Q"\r\n[x]'; + port 'po\nrt'; + } + enum def 'En\num' { 'li\nt'; } + part 'top\npart' : 'Def "Q"\r\n[x]'; + part def 'Sy\ns' { part 'a\n1'; part 'b\n2'; flow from 'a\n1' to 'b\n2'; } + state def 'St\nDef' { state 'st\nate'; } + action def 'Ac\ntion' { action 'a\nct'; } + use case def 'Use\nCase' { actor 'ac\ntor'; subject 'sub\nj'; } +} +"#; + +/// Every command line closes the quotes it opens (a decoded line +/// break would split a quoted label across two lines, each with one +/// quote) and nothing carries a carriage return. +fn assert_well_formed(out: &str) { + assert!(out.starts_with("@startuml\n"), "{out}"); + assert!(out.ends_with("@enduml\n"), "{out}"); + assert!(!out.contains('\r'), "carriage return survived: {out:?}"); + for line in out.lines() { + assert_eq!( + line.matches('"').count() % 2, + 0, + "unbalanced quotes on line {line:?} of\n{out}" + ); + } +} + +#[test] +fn tree_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &VizOptions::default()); + assert_well_formed(&out); + assert!(out.contains("package \"Pkg\\nOne\" as"), "{out}"); + assert!(out.contains("class \"Def ''Q''\\n[x]\" as"), "{out}"); + assert!( + out.contains("class \"top\\npart : Def ''Q''\\n[x]\" as"), + "{out}" + ); + assert!(out.contains("enum \"En\\num\" as"), "{out}"); + // Compartment lines are unquoted member syntax: line breaks become + // spaces there. + assert!(out.contains(" att r = \"va l\"\n"), "{out}"); + assert!(out.contains(" li t\n"), "{out}"); +} + +#[test] +fn interconnection_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::Interconnection)); + assert_well_formed(&out); + assert!(out.contains("package \"Pkg\\nOne\" as"), "{out}"); + assert!(out.contains("rectangle \"Def ''Q''\\n[x]\" as"), "{out}"); + assert!(out.contains("port \"po\\nrt\" as"), "{out}"); + assert!( + out.contains("rectangle \"sub\\npart : Def ''Q''\\n[x]\" as"), + "{out}" + ); +} + +#[test] +fn behavior_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::State)); + assert_well_formed(&out); + assert!(out.contains("state \"St\\nDef\" as"), "{out}"); + assert!(out.contains("state \"st\\nate\" as"), "{out}"); + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::Action)); + assert_well_formed(&out); + assert!(out.contains("state \"Ac\\ntion\" as"), "{out}"); + assert!(out.contains("state \"a\\nct\" as"), "{out}"); +} + +#[test] +fn sequence_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::Sequence)); + assert_well_formed(&out); + assert!(out.contains("box \"Sy\\ns\"\n"), "{out}"); + assert!(out.contains("participant \"a\\n1\" as"), "{out}"); + assert!(out.contains("participant \"b\\n2\" as"), "{out}"); +} + +#[test] +fn case_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::Case)); + assert_well_formed(&out); + assert!(out.contains("usecase \"Use\\nCase\" as"), "{out}"); + assert!(out.contains("actor \"ac\\ntor\" as"), "{out}"); + assert!(out.contains("rectangle \"sub\\nj\" as"), "{out}"); +} + +#[test] +fn mixed_labels_escape_line_breaks() { + let mut r = resolved(ODD); + let out = plantuml(&mut r, None, &view_opts(View::Mixed)); + assert_well_formed(&out); + assert!(out.contains("package \"Pkg\\nOne\" as"), "{out}"); + assert!(out.contains("usecase \"Use\\nCase\" as"), "{out}"); + assert!(out.contains("actor \"ac\\ntor\" as"), "{out}"); + assert!(out.contains("rectangle \"St\\nDef\" as"), "{out}"); +} + +#[test] +fn link_urls_encode_link_delimiters() { + // `{file}` carries the unit name verbatim; `{qname}` carries the + // element's (re-escaped) qualified name. + let mut r = resolved_named( + "odd ]{}\r\nname.sysml", + "package P { part def 'a]b{c}'; }\n", + ); + let opts = VizOptions::default().with_link_template(Some("edit://{file}#{qname}".to_string())); + let out = plantuml(&mut r, None, &opts); + assert_well_formed(&out); + assert!( + out.contains("[[edit://odd%20%5D%7B%7D%0D%0Aname.sysml#P::'a%5Db%7Bc%7D']]"), + "{out}" + ); + // Neither delimiter survives inside any link. + for line in out.lines() { + if let Some(start) = line.find("[[") { + let link = &line[start + 2..line.rfind("]]").unwrap()]; + assert!( + !link.contains([']', '{', '}', ' ', '\n']), + "unencoded delimiter in link {link:?}" + ); + } + } +} + +/// The quoted note form cannot be ended by its own body: every +/// spelling the renderer accepts as the block terminator stays inside +/// the note, and each body line is one `\n`-separated line of it. +#[test] +fn note_bodies_cannot_end_the_note() { + let src = "package P { + part def A { + doc /* first line + * end note + * endnote + * END NOTE + * end note + * says \"end note\" and goes on */ + } + use case def U { + objective { doc /* aim + * end note + * still the aim */ } + } +} +"; + let terminator = |line: &str| { + line.trim() + .to_lowercase() + .split_whitespace() + .collect::() + == "endnote" + }; + let mut r = resolved(src); + let out = plantuml(&mut r, None, &VizOptions::default()); + assert_well_formed(&out); + assert!(!out.lines().any(terminator), "{out}"); + assert!( + out.contains( + "note \"first line\\nend note\\nendnote\\nEND NOTE\\nend note\\nsays ''end note'' and goes on \" as c1\n" + ), + "{out}" + ); + assert!(out.contains("\nc1 .. n"), "{out}"); + + let mut r = resolved(src); + let out = plantuml(&mut r, None, &view_opts(View::Case)); + assert_well_formed(&out); + assert!(!out.lines().any(terminator), "{out}"); + assert!( + out.contains("note \"«objective»\\naim\\nend note\\nstill the aim \" as o1\n"), + "{out}" + ); + assert!(out.contains("\no1 .. n1\n"), "{out}"); +} + +/// A name carrying the two characters `\` and `n` must not reach the +/// renderer spelled like one carrying a line break: the backslash is +/// doubled, so the two labels stay distinguishable and the mapping is +/// reversible. +#[test] +fn labels_double_a_literal_backslash() { + let src = r#"package P { + part def 'Lit\\nEral'; + part def 'Bro\nken'; +} +"#; + let mut r = resolved(src); + let out = plantuml(&mut r, None, &VizOptions::default()); + assert_well_formed(&out); + assert!(out.contains(r#"class "Lit\\nEral" as"#), "{out}"); + assert!(out.contains(r#"class "Bro\nken" as"#), "{out}"); +} diff --git a/crates/sysmlv2-viz/tests/options.rs b/crates/sysmlv2-viz/tests/options.rs new file mode 100644 index 0000000..e7444e3 --- /dev/null +++ b/crates/sysmlv2-viz/tests/options.rs @@ -0,0 +1,144 @@ +//! The option surface hosts sit on: the options builder, the spelling +//! of the option enums (parse, display, serde), and the typed error the +//! structured graph returns for a view it has no emitter for. + +use sysmlv2_model::json::ResolvedModel; +use sysmlv2_model::model::Model; +use sysmlv2_viz::{Direction, GraphError, LineStyle, View, VizOptions, graph}; + +#[test] +fn setters_change_one_option_each() { + let d = VizOptions::default(); + assert_eq!(d.direction, Direction::TopToBottom); + assert_eq!(d.view, View::Tree); + assert_eq!(d.line_style, LineStyle::Default); + assert!(d.show_values && d.show_notes && d.show_metadata); + assert!(!d.show_inherited && !d.show_lib && !d.show_imported && !d.std_color); + assert!(d.link_template.is_none() && d.roots.is_none()); + + let opts = VizOptions::default() + .with_direction(Direction::LeftToRight) + .with_show_values(false) + .with_view(View::Mixed) + .with_show_notes(false) + .with_show_metadata(false) + .with_show_inherited(true) + .with_show_lib(true) + .with_show_imported(true) + .with_line_style(LineStyle::Ortho) + .with_std_color(true) + .with_link_template(Some("edit://{file}".to_string())) + .with_roots(Some(Vec::new())); + assert_eq!(opts.direction, Direction::LeftToRight); + assert!(!opts.show_values); + assert_eq!(opts.view, View::Mixed); + assert!(!opts.show_notes); + assert!(!opts.show_metadata); + assert!(opts.show_inherited); + assert!(opts.show_lib); + assert!(opts.show_imported); + assert_eq!(opts.line_style, LineStyle::Ortho); + assert!(opts.std_color); + assert_eq!(opts.link_template.as_deref(), Some("edit://{file}")); + assert_eq!(opts.roots.as_deref(), Some(&[][..])); +} + +/// Every view round-trips through its canonical spelling, and the two +/// shorthands hosts accept parse to the same views. +#[test] +fn view_spellings_round_trip() { + let all = [ + (View::Tree, "tree"), + (View::Interconnection, "interconnection"), + (View::State, "state"), + (View::Action, "action"), + (View::Sequence, "sequence"), + (View::Case, "case"), + (View::Mixed, "mixed"), + ]; + for (view, spelling) in all { + assert_eq!(view.as_str(), spelling); + assert_eq!(view.to_string(), spelling); + assert_eq!(spelling.parse::().unwrap(), view); + assert_eq!( + serde_json::to_string(&view).unwrap(), + format!("\"{spelling}\"") + ); + assert_eq!( + serde_json::from_str::(&format!("\"{spelling}\"")).unwrap(), + view + ); + } + for (short, view) in [("ic", View::Interconnection), ("seq", View::Sequence)] { + assert_eq!(short.parse::().unwrap(), view); + assert_eq!( + serde_json::from_str::(&format!("\"{short}\"")).unwrap(), + view + ); + } +} + +#[test] +fn line_style_spellings_round_trip() { + for (style, spelling) in [ + (LineStyle::Default, "default"), + (LineStyle::Polyline, "polyline"), + (LineStyle::Ortho, "ortho"), + ] { + assert_eq!(style.as_str(), spelling); + assert_eq!(style.to_string(), spelling); + assert_eq!(spelling.parse::().unwrap(), style); + assert_eq!( + serde_json::to_string(&style).unwrap(), + format!("\"{spelling}\"") + ); + assert_eq!( + serde_json::from_str::(&format!("\"{spelling}\"")).unwrap(), + style + ); + } +} + +/// A spelling that names nothing says what was named and what it could +/// have been. +#[test] +fn unknown_spellings_report_the_alternatives() { + let e = "treee".parse::().unwrap_err(); + assert_eq!(e.option(), "view"); + assert_eq!(e.spelling(), "treee"); + assert_eq!(e.expected().first(), Some(&"tree")); + assert_eq!( + e.to_string(), + "unknown view: treee (expected tree, interconnection, state, action, sequence, case, or mixed)" + ); + + let e = "dotted".parse::().unwrap_err(); + assert_eq!(e.option(), "line style"); + assert_eq!( + e.to_string(), + "unknown line style: dotted (expected default, polyline, or ortho)" + ); +} + +/// The structured graph names the view it cannot draw, and the views it +/// can draw label their output with the same spelling. +#[test] +fn graph_reports_the_view_it_cannot_draw() { + let mut model = Model::new(); + model.add_source("p.sysml".to_string(), "package P { part def A; }\n"); + let mut r = ResolvedModel::build(&model); + + for view in [View::Tree, View::Interconnection, View::State, View::Action] { + let g = graph(&mut r, None, &VizOptions::default().with_view(view)).unwrap(); + assert_eq!(g["view"].as_str(), Some(view.as_str())); + } + + for view in [View::Sequence, View::Case, View::Mixed] { + let e = graph(&mut r, None, &VizOptions::default().with_view(view)).unwrap_err(); + assert_eq!(e, GraphError::UnsupportedView(view)); + assert_eq!( + e.to_string(), + format!("no structured-graph emitter for view: {view}") + ); + } +} diff --git a/crates/sysmlv2-viz/tests/viz.rs b/crates/sysmlv2-viz/tests/viz.rs index c18949d..b3293f7 100644 --- a/crates/sysmlv2-viz/tests/viz.rs +++ b/crates/sysmlv2-viz/tests/viz.rs @@ -33,6 +33,32 @@ fn resolved_named(name: &str, src: &str) -> ResolvedModel { ResolvedModel::build(&model) } +#[test] +fn graph_redefined_nodes_and_rows_have_resolvable_qualified_names() { + let mut r = resolved( + "package P { + part def Tank { attribute mass = 1; } + part base { part tank : Tank; } + part actual :> base { part :>> tank { attribute :>> mass = 2; } } + }", + ); + let graph = sysmlv2_viz::graph(&mut r, None, &VizOptions::default()).unwrap(); + for name in ["P::actual::tank", "P::actual::tank::mass"] { + let element = r.resolve_qualified(name).expect(name); + let id = r.element_id(element).to_string(); + let item = graph["nodes"] + .as_array() + .unwrap() + .iter() + .flat_map(|n| std::iter::once(n).chain(n["rows"].as_array().unwrap().iter())) + .find(|n| n["id"] == id) + .expect(name); + assert_eq!(item["qname"], name); + assert_eq!(item["file"], "demo.sysml"); + assert!(item["line"].as_u64().unwrap() > 0); + } +} + #[test] fn demo_golden() { let mut r = resolved(DEMO); @@ -74,10 +100,7 @@ fn demo_is_deterministic() { #[test] fn direction_toggle() { let mut r = resolved(DEMO); - let opts = VizOptions { - direction: Direction::LeftToRight, - ..Default::default() - }; + let opts = VizOptions::default().with_direction(Direction::LeftToRight); let out = plantuml(&mut r, None, &opts); assert!(out.contains("left to right direction")); } @@ -85,10 +108,7 @@ fn direction_toggle() { #[test] fn values_toggle_off() { let mut r = resolved(DEMO); - let opts = VizOptions { - show_values: false, - ..Default::default() - }; + let opts = VizOptions::default().with_show_values(false); let out = plantuml(&mut r, None, &opts); assert!(!out.contains("= 1200"), "{out}"); } @@ -126,10 +146,7 @@ fn top_level_valued_usages_keep_values_as_nodes() { assert!(out.contains("budget = 42"), "{out}"); let g = sysmlv2_viz::graph(&mut r, None, &VizOptions::default()).unwrap(); assert!(serde_json::to_string(&g).unwrap().contains("budget = 42")); - let opts = VizOptions { - show_values: false, - ..Default::default() - }; + let opts = VizOptions::default().with_show_values(false); let out = plantuml(&mut r, None, &opts); assert!(!out.contains("= 42"), "{out}"); } @@ -167,10 +184,7 @@ fn anonymous_redefining_members_label_by_target_name() { // The borrowed name also shadows: with inherited lines on, the // target's own `mode : Mode` must not reappear beside it. - let opts = VizOptions { - show_inherited: true, - ..Default::default() - }; + let opts = VizOptions::default().with_show_inherited(true); let out = plantuml(&mut r, None, &opts); assert!(!out.contains("^mode"), "shadowing lost: {out}"); assert!(out.contains("mode : Mode = run"), "{out}"); @@ -209,10 +223,7 @@ fn graph_emits_note_nodes_for_doc_bodies() { // The toggle drops both the node and its edge. let mut r = resolved(src); - let opts = VizOptions { - show_notes: false, - ..Default::default() - }; + let opts = VizOptions::default().with_show_notes(false); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); assert!( !g["nodes"] @@ -259,10 +270,7 @@ package Gamma { part def C; } let alpha = r.resolve_qualified("Alpha").expect("resolves"); let gamma = r.resolve_qualified("Gamma").expect("resolves"); - let opts = VizOptions { - roots: Some(vec![alpha, gamma]), - ..Default::default() - }; + let opts = VizOptions::default().with_roots(Some(vec![alpha, gamma])); let out = plantuml(&mut r, None, &opts); assert!(out.contains("\"Alpha\""), "{out}"); assert!(out.contains("\"Gamma\""), "{out}"); @@ -298,10 +306,7 @@ package Gamma { part def C; } // Empty selection is treated as "no filter" (whole model), never // an empty diagram — the panel gates the truly-empty case itself. - let empty_opts = VizOptions { - roots: Some(vec![]), - ..Default::default() - }; + let empty_opts = VizOptions::default().with_roots(Some(vec![])); let out = plantuml(&mut r, None, &empty_opts); assert!( out.contains("\"Beta\""), @@ -360,10 +365,7 @@ const IC_DEMO: &str = "package Rig { "; fn view_opts(view: View) -> VizOptions { - VizOptions { - view, - ..Default::default() - } + VizOptions::default().with_view(view) } /// Ports declared on a part's definition render per usage, and both @@ -633,10 +635,7 @@ actor \"driver : Driver\" as n4 usecase \"UnlockVehicle\" as n5 <> n2 -- n3 : «subject» n4 -- n2 -note as o1 -«objective» -get from A to B safely -end note +note \"«objective»\\nget from A to B safely \" as o1 o1 .. n2 n2 ..> n1 : «include» @enduml @@ -676,7 +675,7 @@ fn mixed_everything_on_one_canvas() { assert!(out.contains("actor \"rider\" as"), "{out}"); // Typing edge and exhibit typing, doc note. assert!(out.contains("..>"), "{out}"); - assert!(out.contains("note as c1"), "{out}"); + assert!(out.contains("\" as c1\n"), "{out}"); assert!(out.contains("The whole system."), "{out}"); // Attributes stay off the canvas (no compartments in this dialect). assert!(!out.contains("mass"), "{out}"); @@ -693,18 +692,11 @@ fn tree_notes_toggle() { "; let mut r = resolved(src); let out = plantuml(&mut r, None, &VizOptions::default()); - assert!(out.contains("note as c1"), "{out}"); + assert!(out.contains("\" as c1\n"), "{out}"); assert!(out.contains("documented"), "{out}"); assert!(out.contains("commented"), "{out}"); let mut r = resolved(src); - let out = plantuml( - &mut r, - None, - &VizOptions { - show_notes: false, - ..Default::default() - }, - ); + let out = plantuml(&mut r, None, &VizOptions::default().with_show_notes(false)); assert!(!out.contains("note"), "{out}"); } @@ -724,10 +716,7 @@ fn metadata_stereotypes_and_hide() { let out = plantuml( &mut r, None, - &VizOptions { - show_metadata: false, - ..Default::default() - }, + &VizOptions::default().with_show_metadata(false), ); assert!(!out.contains("<>"), "{out}"); } @@ -746,10 +735,7 @@ fn tree_inherited_compartments() { let out = plantuml( &mut r, None, - &VizOptions { - show_inherited: true, - ..Default::default() - }, + &VizOptions::default().with_show_inherited(true), ); assert!(out.contains("^mass"), "{out}"); // Own `kind` shadows the inherited one. @@ -768,14 +754,7 @@ fn tree_show_lib_nodes() { "package Typed { part def Sensor :> Parts::Part; }\n", ); let mut r = ResolvedModel::build(&model); - let out = plantuml( - &mut r, - None, - &VizOptions { - show_lib: true, - ..Default::default() - }, - ); + let out = plantuml(&mut r, None, &VizOptions::default().with_show_lib(true)); assert!(out.contains("<>"), "{out}"); assert!(out.contains("--|>"), "{out}"); } @@ -791,10 +770,7 @@ package Car { private import Lib::Wheel; part w : Wheel; } let out = plantuml( &mut r, None, - &VizOptions { - show_imported: true, - ..Default::default() - }, + &VizOptions::default().with_show_imported(true), ); assert!(out.contains("«import»"), "{out}"); } @@ -807,12 +783,10 @@ fn style_and_link_options() { let out = plantuml( &mut r, None, - &VizOptions { - line_style: LineStyle::Ortho, - std_color: true, - link_template: Some("vscode://file/{file}:{line}".to_string()), - ..Default::default() - }, + &VizOptions::default() + .with_line_style(LineStyle::Ortho) + .with_std_color(true) + .with_link_template(Some("vscode://file/{file}:{line}".to_string())), ); assert!(out.contains("skinparam linetype ortho"), "{out}"); assert!(out.contains("BackgroundColor<>"), "{out}"); @@ -944,10 +918,7 @@ fn graph_tree_carries_identity_rows_and_edges() { #[test] fn graph_rejects_views_without_emitters() { let mut r = resolved(DEMO); - let opts = VizOptions { - view: View::Sequence, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Sequence); assert!(sysmlv2_viz::graph(&mut r, None, &opts).is_err()); } @@ -967,10 +938,7 @@ const IC_GRAPH_DEMO: &str = "package Rig { #[test] fn graph_interconnection_edges_carry_connector_identity() { let mut r = resolved(IC_GRAPH_DEMO); - let opts = VizOptions { - view: View::Interconnection, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Interconnection); let g = sysmlv2_viz::graph(&mut r, None, &opts).expect("ic graph"); let nodes = g["nodes"].as_array().unwrap(); @@ -1040,10 +1008,7 @@ fn graph_state_view_pseudostates_and_transition_identity() { } "; let mut r = resolved(SRC); - let opts = VizOptions { - view: View::State, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::State); let g = sysmlv2_viz::graph(&mut r, None, &opts).expect("state graph"); let nodes = g["nodes"].as_array().unwrap(); let edges = g["edges"].as_array().unwrap(); @@ -1126,11 +1091,9 @@ fn view_directed_rendering() { && names.contains(&"VD::stage::main".to_string()), "{names:?}" ); - let opts = VizOptions { - view: View::Interconnection, - roots: Some(roots), - ..Default::default() - }; + let opts = VizOptions::default() + .with_view(View::Interconnection) + .with_roots(Some(roots)); let out = plantuml(&mut r, None, &opts); // Exactly one connector edge: the untagged cable draws, the // LOUD-tagged one is filtered off. The untagged parts (including @@ -1180,10 +1143,7 @@ fn action_view_flow_anchors() { } }"; let mut r = resolved(src); - let opts = VizOptions { - view: View::Action, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Action); let out = plantuml(&mut r, None, &opts); let alias = |name: &str| { let tag = format!("\"{name}\" as "); @@ -1262,10 +1222,7 @@ fn state_view_anonymous_do_actions_list_steps() { } }"; let mut r = resolved(src); - let opts = VizOptions { - view: View::State, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::State); let out = plantuml(&mut r, None, &opts); assert!(out.contains(": do / sweep : Chore; polish"), "{out}"); assert!(out.contains(": do / rinse"), "{out}"); @@ -1357,10 +1314,7 @@ package RecUser { import Lib::**; part def B; } package MemUser { import Lib::L; part def C; } "; let mut r = resolved(SRC); - let opts = VizOptions { - show_imported: true, - ..Default::default() - }; + let opts = VizOptions::default().with_show_imported(true); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let nodes = g["nodes"].as_array().unwrap(); let edges = g["edges"].as_array().unwrap(); @@ -1459,10 +1413,7 @@ fn graph_connector_ends_carry_roles() { } "; let mut r = resolved(SRC); - let opts = VizOptions { - view: View::Interconnection, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Interconnection); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let edges = g["edges"].as_array().unwrap(); let conn = edges @@ -1490,10 +1441,7 @@ fn graph_ports_carry_direction_and_conjugation() { } "; let mut r = resolved(SRC); - let opts = VizOptions { - view: View::Interconnection, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Interconnection); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let nodes = g["nodes"].as_array().unwrap(); let port = |l: &str| { @@ -1572,10 +1520,7 @@ fn graph_connector_ends_carry_adornments() { } "; let mut r = resolved(SRC); - let opts = VizOptions { - view: View::Interconnection, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Interconnection); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let edges = g["edges"].as_array().unwrap(); let conn = edges @@ -1631,10 +1576,7 @@ package Priv { private import Lib::*; part def A; } package Pub { import Lib::*; part def B; } "; let mut r = resolved(SRC); - let opts = VizOptions { - show_imported: true, - ..Default::default() - }; + let opts = VizOptions::default().with_show_imported(true); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let nodes = g["nodes"].as_array().unwrap(); let edges = g["edges"].as_array().unwrap(); @@ -1667,10 +1609,7 @@ fn graph_action_view_params_are_border_chips() { } "; let mut r = resolved(SRC); - let opts = VizOptions { - view: View::Action, - ..Default::default() - }; + let opts = VizOptions::default().with_view(View::Action); let g = sysmlv2_viz::graph(&mut r, None, &opts).unwrap(); let nodes = g["nodes"].as_array().unwrap(); let capture = nodes diff --git a/crates/sysmlv2-wasm/README.md b/crates/sysmlv2-wasm/README.md index 609b13a..6b6a7da 100644 --- a/crates/sysmlv2-wasm/README.md +++ b/crates/sysmlv2-wasm/README.md @@ -14,7 +14,7 @@ const sources = JSON.stringify([ { name: "demo.sysml", text: "package Demo { part def Vehicle; part car : Vehicle; }" }, ]); -// Diagnostics: [{severity, message, unit, line, col}]. +// Diagnostics: [{severity, stage, message, unit, line, col, endLine, endCol}]. const findings = JSON.parse(check(sources)); // Sessions: navigation, queries, interchange JSON, diagrams. @@ -23,8 +23,19 @@ const car = session.resolve("Demo::car"); console.log(session.metaclass(car)); // "PartUsage" const uml = session.toPlantuml(JSON.stringify({ view: "tree" })); const interchange = session.toFullJson(true); + +// Lint: the same {findings, summary} document `sysmlv2 lint --format json` emits. +const lint = JSON.parse(session.lint(/* sysmlint.json text, optional */)); ``` +`session.lint(config)` runs the configurable project-policy rules over the session's user units — `config` is `sysmlint.json` text, omitted for every rule at its default — and returns the report document shared with the CLI's `--format json`: each finding carries `rule`, `severity` (`error` / `warn` / `info` / `hint`), `message`, `unit` / `unitName`, byte offsets and 1-based positions, `element`, `suggest`, and any `fix` (byte-offset edits; `deletes` and `semantic` mark fixes to gate behind explicit consent). `lintRules()` lists the rule inventory with defaults, scopes and options. + +## Errors + +Input the binding can describe is refused by throwing a string: `check`, `Session.fromSources` and every session method reject malformed JSON, unknown options and unresolvable names that way, so `try`/`catch` around a call gets a message you can show. + +A defect in the toolkit is different. It aborts the call with `RuntimeError: unreachable` and leaves the module instance trapped — every later call into it fails too, and a session caught mid-edit may be half-mutated. The panic report (message and location) is written to `console.error` as the instance traps, so the console says what happened even though the thrown value does not. **A host that catches a `RuntimeError` must discard the module instance and `init()` a fresh one**; reusing it, or its sessions, is not safe. Reload the sources into the new instance to carry on. + ## The standard library The package ships the OMG standard library under `stdlib/`: @@ -49,10 +60,57 @@ const session = Session.fromSources(sources); session.loadLibrarySources(bundle, snapshot); // library-aware navigation ``` +Without a bundle, `check(sources)` runs parse and structural checks. Supplying a bundle adds referential and semantic checks; this API does not report unused private imports. Its sealed resolution snapshot is distinct from the native CLI’s directory-backed `.prepared` graph cache. + `Session.fromInterchangeJson(json, bundle, snapshot)` accepts the same pair for lifting library-typed interchange payloads (Flexo `{payload, identity}` change records included). +For repeated builds in a worker, prepare the final library bundle once and share +its immutable graph. Each session keeps its own resolver state: + +```js +import { PreparedLibrary, Session } from "@sysml/wasm/sysmlv2.js"; +const library = new PreparedLibrary(bundle, snapshot); +const session = Session.fromSourcesWithPreparedLibrary(sources, library); +const findings = JSON.parse(session.check()); +library.free(); // the session retains the library through subsequent edits +session.free(); +``` + +Use a new handle when library text or unit order changes. Preparation costs are +paid once per handle, so retain it across builds to amortize them. Existing source +and snapshot APIs remain available. `fromInterchangeJsonWithPreparedLibrary`, +`fromCompactCborWithPreparedLibrary`, and `loadPreparedLibrary` accept the same +handle; attaching a library invalidates existing element handles. + +## Running the command-line module + +The package ships the toolkit's command line as a `wasm32-wasip1` module under `cli/`, version-locked to the kernel module beside it. It reserves a 16 MiB stack, because the parser's recursion bounds are sized to report a finding on deep input rather than exhaust the stack, and that reservation is the module's declared initial memory. + +Run it under **Node 24 or newer**. Node 22 on x86_64 faults inside its own WASI host on a module this shape: over 40 runs of one artifact, 6 ended in a segmentation fault of the node process — not a trap the module can raise, since it imports no means of raising a signal. The rate follows the declared initial memory, and Node 20 and 24 on the same architecture, and Node 22 on arm64, were clean over the same count. The kernel module (`sysmlv2_bg.wasm`), which reserves no such stack, is unaffected. + ## Building from source -`node crates/sysmlv2-wasm/npm/build.mjs` (needs wasm-pack, the `wasm32-unknown-unknown` target, node ≥ 18, and the SysML-v2-Release submodule for the stdlib). Output: `npm/pkg/` (the package) and `npm/dist/sysmlv2-wasm-.tgz`. The tarball is attached to each GitHub release; the package is not published to npm. +`node crates/sysmlv2-wasm/npm/build.mjs` (needs wasm-pack, both the `wasm32-unknown-unknown` and `wasm32-wasip1` targets, node ≥ 18 to build and ≥ 24 to run the smokes, and the SysML-v2-Release submodule for the stdlib). Output: `npm/pkg/` (the package) and `npm/dist/sysml-wasm-.tgz`. The release workflow attaches the tarball to tagged releases. It also attempts registry publishing of `@sysml/wasm` on tag/manual runs when `NPM_TOKEN` is configured; otherwise that step is skipped. A local build does not publish. [sysmlv2]: https://github.com/Open-MBEE/sysml-toolkit + +### Reference spelling + +`session.qualifiedName(element)` is the specification's derived qualified name: +a reserved word used as a name stays bare (`part::view` for `part 'view';` +inside `package 'part'`), which is also what the normative library ids hash. That +string does not parse as a reference. `session.referenceSpelling(element)` and +the free `spellReference(qualifiedName, dialect?)` quote such segments +(`'part'::'view'`) — omit `dialect` for text that must parse in either dialect, +or pass `"sysml"` / `"kerml"` for a known unit — so use them, not +`qualifiedName`, to generate `import` and `expose` targets. + +### Lookup by interchange ID + +`session.elementById(id)` returns the same kind of generation-checked handle as +`session.resolve(qualifiedName)`, including for anonymous elements emitted by +`toGraph`. It returns `undefined` for malformed or missing UUIDs. Qualified names +remain absent for genuinely anonymous elements; IDs are not display names. +Library elements can be inspected by ID but remain read-only. Reacquire handles +after an edit or library reload; IDs refer to the current model state and can +change when an element's ownership path changes. diff --git a/crates/sysmlv2-wasm/npm/build.mjs b/crates/sysmlv2-wasm/npm/build.mjs index 589065b..35f4e7d 100644 --- a/crates/sysmlv2-wasm/npm/build.mjs +++ b/crates/sysmlv2-wasm/npm/build.mjs @@ -18,7 +18,7 @@ // dist/ sysml-wasm-.tgz import { execFileSync } from "node:child_process"; -import { copyFileSync, readFileSync, writeFileSync, mkdirSync, renameSync, readdirSync, existsSync } from "node:fs"; +import { copyFileSync, readFileSync, writeFileSync, mkdirSync, readdirSync, existsSync } from "node:fs"; import { dirname, join, resolve, delimiter } from "node:path"; import { homedir } from "node:os"; import { fileURLToPath } from "node:url"; @@ -34,13 +34,17 @@ const npmDir = join(crateDir, "npm"); const localWasmPack = join(npmDir, "node_modules", ".bin", "wasm-pack"); const wasmPack = process.env.WASM_PACK ?? (existsSync(localWasmPack) ? localWasmPack : "wasm-pack"); const rustupToolchains = join(homedir(), ".rustup", "toolchains"); -const stableBin = existsSync(rustupToolchains) +const pinnedChannel = readFileSync(join(repoRoot, "rust-toolchain.toml"), "utf8") + .match(/^channel\s*=\s*"([^"]+)"/m)?.[1]; +if (!pinnedChannel) throw new Error("rust-toolchain.toml does not declare a channel"); +const channel = process.env.RUSTUP_TOOLCHAIN ?? pinnedChannel; +const toolchainBin = existsSync(rustupToolchains) ? readdirSync(rustupToolchains) - .filter((d) => d.startsWith("stable-")) + .filter((d) => d === channel || d.startsWith(`${channel}-`)) .map((d) => join(rustupToolchains, d, "bin")) .find((b) => existsSync(join(b, "cargo"))) : undefined; -const env = stableBin ? { ...process.env, PATH: `${stableBin}${delimiter}${process.env.PATH}` } : process.env; +const env = toolchainBin ? { ...process.env, PATH: `${toolchainBin}${delimiter}${process.env.PATH}` } : process.env; const libraryDir = process.env.SYSMLV2_LIBRARY ?? join(repoRoot, "spec-refs", "SysML-v2-Release", "sysml.library"); @@ -52,9 +56,44 @@ const run = (cmd, args, opts = {}) => { // 1. The package module (web target: explicit init(url) — works in // browsers, workers, and bundlers without wasm-aware config) and the -// smoke-test module (nodejs target). -run(wasmPack, ["build", crateDir, "--release", "--target", "web", "--out-dir", "npm/pkg", "--out-name", "sysmlv2"]); -run(wasmPack, ["build", crateDir, "--release", "--target", "nodejs", "--out-dir", "npm/pkg-node", "--out-name", "sysmlv2"]); +// smoke-test module (nodejs target). The linear memory is capped below +// the wasm32 maximum: a runaway allocation then fails inside the module +// (an error the host reports and a worker restart clears) instead of +// growing until the browser kills the whole tab. The cap leaves ample +// room above what the largest models and library snapshots use. +const MAX_MEMORY_BYTES = 2 * 1024 * 1024 * 1024; +// The module's stack is reserved explicitly rather than left at the +// linker's default megabyte, which is below the depths the toolkit's +// recursive passes bound themselves to — on this target running out of +// stack traps instead of unwinding, so a bound the stack cannot hold is +// a crash where the host expects a finding. The size is declared in the +// crate, next to the reasoning, and read from there so the two cannot +// drift; tests/stack.rs holds them together. +const stackSizeBytes = (() => { + const src = readFileSync(join(crateDir, "src", "lib.rs"), "utf8"); + const found = src.match(/pub const WASM_STACK_BYTES: usize = (\d+);/); + if (!found) throw new Error("WASM_STACK_BYTES not found in crates/sysmlv2-wasm/src/lib.rs"); + return Number(found[1]); +})(); +// The link flag goes in the wasm32-only rustflags variable, never the +// global RUSTFLAGS: the packager inherits this environment when it installs +// its helper binary for the host (a plain `cargo install`, no --target), +// and the host linker rejects a wasm-only argument. Cargo reads exactly +// one rustflags source, and a set (encoded) RUSTFLAGS wins over the +// target variable, so any flags the caller exported are folded into the +// target variable and removed from the environment wasm-pack sees. +const encodedRustflags = process.env.CARGO_ENCODED_RUSTFLAGS?.split("\x1f") ?? []; +const targetRustflags = [ + ...encodedRustflags, + process.env.RUSTFLAGS, + process.env.CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS, + `-C link-arg=--max-memory=${MAX_MEMORY_BYTES}`, + `-C link-arg=-zstack-size=${stackSizeBytes}`, +].filter(Boolean).join(" "); +const { RUSTFLAGS: _rustflags, CARGO_ENCODED_RUSTFLAGS: _encoded, ...hostEnv } = env; +const wasmEnv = { ...hostEnv, CARGO_TARGET_WASM32_UNKNOWN_UNKNOWN_RUSTFLAGS: targetRustflags }; +run(wasmPack, ["build", crateDir, "--release", "--target", "web", "--out-dir", "npm/pkg", "--out-name", "sysmlv2"], { env: wasmEnv }); +run(wasmPack, ["build", crateDir, "--release", "--target", "nodejs", "--out-dir", "npm/pkg-node", "--out-name", "sysmlv2"], { env: wasmEnv }); // 2. Standard-library artifacts into the package. The shipped bundle // carries the ambient libraries (Web, Template, engine overlays, @@ -72,10 +111,21 @@ run("cargo", ["run", "--release", "-p", "sysmlv2-wasm", "--bin", "gen_stdlib_bun // toolchain-path care as any wasm build on machines where another // cargo shadows rustup (CARGO / CARGO_TARGET_DIR are honored). const cargo = process.env.CARGO ?? "cargo"; +// The same stack reservation as the module above: the recursion bounds +// and the trap-on-overflow behaviour are the target's, not the binding's. +const wasiEnv = { + ...hostEnv, + CARGO_TARGET_WASM32_WASIP1_RUSTFLAGS: [ + ...encodedRustflags, + process.env.RUSTFLAGS, + process.env.CARGO_TARGET_WASM32_WASIP1_RUSTFLAGS, + `-C link-arg=-zstack-size=${stackSizeBytes}`, + ].filter(Boolean).join(" "), +}; run( cargo, ["build", "-p", "sysmlv2-cli", "--no-default-features", "--features", "solve,viz", "--target", "wasm32-wasip1", "--profile", "wasi-release"], - { cwd: repoRoot } + { cwd: repoRoot, env: wasiEnv } ); const targetDir = process.env.CARGO_TARGET_DIR ? resolve(repoRoot, process.env.CARGO_TARGET_DIR) @@ -123,7 +173,8 @@ writeFileSync(pkgJsonPath, JSON.stringify(pkg, null, 2) + "\n"); const distDir = join(crateDir, "npm", "dist"); mkdirSync(distDir, { recursive: true }); run("npm", ["pack", "--pack-destination", distDir], { cwd: join(crateDir, "npm", "pkg") }); -const packed = readdirSync(distDir).find((f) => f.endsWith(".tgz") && f.startsWith("sysml-wasm-")); +// npm derives this filename from the scoped package identity. Never pick a +// tarball by directory order: dist may also contain older package versions. const final = `sysml-wasm-${pkg.version}.tgz`; -if (packed && packed !== final) renameSync(join(distDir, packed), join(distDir, final)); +if (!existsSync(join(distDir, final))) throw new Error(`npm pack did not produce ${final}`); console.log(`packaged: npm/dist/${final}`); diff --git a/crates/sysmlv2-wasm/npm/smoke.mjs b/crates/sysmlv2-wasm/npm/smoke.mjs index 7d49512..c19d3b8 100644 --- a/crates/sysmlv2-wasm/npm/smoke.mjs +++ b/crates/sysmlv2-wasm/npm/smoke.mjs @@ -13,16 +13,31 @@ import assert from "node:assert/strict"; const here = dirname(fileURLToPath(import.meta.url)); const require = createRequire(import.meta.url); -const { Session, check, version } = require(join(here, "pkg-node", "sysmlv2.js")); +const { PreparedLibrary, Session, check, version } = require(join(here, "pkg-node", "sysmlv2.js")); console.log(`sysmlv2-wasm ${version()}`); // Parse error -> positioned finding. const bad = JSON.parse(check(JSON.stringify([{ name: "bad.sysml", text: "part def {" }]))); assert.equal(bad[0].severity, "error"); +assert.equal(bad[0].stage, "parse"); assert.equal(bad[0].unit, "bad.sysml"); assert.ok(bad[0].line >= 1); +// Exercise the linked module's real stack and conversion paths, rather +// than relying only on native threads with an equivalent reservation. +const chainSource = "attribute sum = " + Array(1025).fill("1").join(" + ") + ";"; +const chainSession = Session.fromSources(JSON.stringify([{ name: "chain.sysml", text: chainSource }])); +for (const payload of [chainSession.toCompactJson(), chainSession.toFullJson(true)]) { + const lifted = Session.fromInterchangeJson(payload); + assert.equal(lifted.query("sum"), "1025", "every operand survives lifting"); + lifted.free(); +} +chainSession.free(); +const deepIf = JSON.parse(check(JSON.stringify([{ name: "deep.sysml", + text: "action a { " + "if true {} else ".repeat(1000) + "{} }" }]))); +assert.ok(deepIf.some(d => d.message.includes("nesting is too deep")), "else-if depth is diagnosed without trapping"); + // Session -> diagram. const model = JSON.stringify([ { @@ -31,6 +46,12 @@ const model = JSON.stringify([ }, ]); const session = Session.fromSources(model); +// Numbers cross exactly: a terminating decimal is a JSON number, any +// other rational an explicit fraction with a double approximation. +assert.equal(JSON.parse(session.query("0.1 + 0.2")), 0.3); +assert.equal(session.query("0.1 + 0.2 == 0.3"), "true"); +assert.deepEqual(JSON.parse(session.query("1 / 3")), { "@rational": "1/3", approx: 1 / 3 }); +assert.equal(JSON.parse(session.query("2 ** 200"))["@rational"], `${2n ** 200n}/1`); const uml = session.toPlantuml(JSON.stringify({ view: "tree" })); assert.ok(uml.startsWith("@startuml"), "PlantUML emission"); @@ -38,6 +59,23 @@ assert.ok(uml.startsWith("@startuml"), "PlantUML emission"); const back = Session.fromInterchangeJson(session.toFullJson(true)); assert.ok(back.resolve("Flashlight::flashlight::body"), "round-trip resolve"); +// Anonymous graph nodes have IDs, but deliberately have no qualified name. +const anonymous = Session.fromSources(JSON.stringify([{ name: "anonymous.sysml", text: + "package P { action a; action b; succession first a then b; constraint { true } }" }])); +const graph = JSON.parse(anonymous.toGraph(JSON.stringify({ view: "tree" }))); +assert.equal(typeof anonymous.elementById, "function", "ID lookup is exposed to JavaScript"); +for (const kind of ["ConstraintUsage", "SuccessionAsUsage"]) { + const node = graph.nodes.find(n => n.metaclass === kind); + assert.ok(node && !node.qname, kind + " is anonymous"); + const element = anonymous.elementById(node.id); + assert.ok(element, kind + " is reachable by graph ID"); + assert.equal(anonymous.metaclass(element), kind); + assert.equal(anonymous.qualifiedName(element), undefined); + assert.ok(anonymous.declarationSite(element)); +} +assert.equal(anonymous.elementById("not-an-id"), undefined); +assert.equal(anonymous.elementById("00000000-0000-0000-0000-000000000000"), undefined); + // Real standard library: bundle + sealed snapshot. The library-typed // source below only checks clean when stdlib resolution works, and the // snapshot must make the warm build decisively faster than the cold one @@ -78,4 +116,25 @@ const real = s2.resolve("ScalarValues::Real"); assert.ok(real, "stdlib element resolves"); assert.ok(s2.isLibraryElement(real)); +// Shared graph preparation preserves results, including after the host releases +// its handle. Each session keeps its own reference and resolver state. +const prepared = new PreparedLibrary(bundle, snapshot); +const shared = Session.fromSourcesWithPreparedLibrary(user, prepared); +const sibling = Session.fromSourcesWithPreparedLibrary(user, prepared); +assert.equal(shared.toCompactJson(), s2.toCompactJson()); +assert.equal(shared.toFullJson(true), s2.toFullJson(true)); +assert.equal(shared.check(), s2.check()); +const liftedShared = Session.fromInterchangeJsonWithPreparedLibrary(shared.toCompactJson(), prepared); +assert.deepEqual(JSON.parse(liftedShared.check()), []); +liftedShared.free(); +prepared.free(); +shared.edit(JSON.stringify([{ op: "rename", target: "Demo::car", newName: "vehicle" }])); +const edited = shared.resolve("Demo::vehicle"); +assert.ok(edited); +edited.free(); +assert.equal(sibling.toCompactJson(), s2.toCompactJson()); +assert.deepEqual(JSON.parse(shared.check()), []); +shared.free(); +sibling.free(); + console.log("smoke: ok"); diff --git a/crates/sysmlv2-wasm/src/bin/gen_stdlib_bundle.rs b/crates/sysmlv2-wasm/src/bin/gen_stdlib_bundle.rs index 49599c6..c04eb01 100644 --- a/crates/sysmlv2-wasm/src/bin/gen_stdlib_bundle.rs +++ b/crates/sysmlv2-wasm/src/bin/gen_stdlib_bundle.rs @@ -42,14 +42,18 @@ fn gzip(data: &[u8]) -> Vec { let mut out = vec![0x1f, 0x8b, 0x08, 0, 0, 0, 0, 0, 0, 0xff]; out.extend_from_slice(&miniz_oxide::deflate::compress_to_vec(data, 9)); out.extend_from_slice(&crc32(data).to_le_bytes()); - out.extend_from_slice(&(data.len() as u32).to_le_bytes()); + // The trailer's size field is the input length modulo 2^32, which + // is what the low 32 bits of the length are. + #[allow(clippy::cast_possible_truncation)] + let isize_field = data.len() as u32; + out.extend_from_slice(&isize_field.to_le_bytes()); out } fn crc32(data: &[u8]) -> u32 { let mut table = [0u32; 256]; - for (n, slot) in table.iter_mut().enumerate() { - let mut c = n as u32; + for (n, slot) in (0u32..).zip(table.iter_mut()) { + let mut c = n; for _ in 0..8 { c = if c & 1 != 0 { 0xedb88320 ^ (c >> 1) diff --git a/crates/sysmlv2-wasm/src/lib.rs b/crates/sysmlv2-wasm/src/lib.rs index a00c24d..9d31c94 100644 --- a/crates/sysmlv2-wasm/src/lib.rs +++ b/crates/sysmlv2-wasm/src/lib.rs @@ -14,6 +14,8 @@ //! session and invalidates outstanding handles — using one afterwards //! errors instead of silently denoting the wrong element. +use std::collections::HashMap; + use serde::Deserialize; use serde_json::json; use wasm_bindgen::prelude::*; @@ -26,6 +28,47 @@ use sysmlv2_syntax::parser::parse_expression; use sysmlv2_syntax::span::LineIndex; use sysmlv2_transform::{Indent, Library, Session as TSession, check_sources_with_library}; +/// Stack reserved for the module, in bytes (16 MiB). +/// +/// The toolkit's passes recurse, and each bounds itself by a depth that +/// stops unbounded input with a diagnostic instead of a crash: the parser +/// at [`sysmlv2_syntax::parser::MAX_NESTING`] levels of bodies and +/// expressions, the lift at [`sysmlv2_model::lift::MAX_LIFT_DEPTH`] +/// ownership steps. A bound only does that where the stack holds it. On +/// this target it would otherwise be the linker's default megabyte — too +/// little for either bound, and running out of stack here is a trap the +/// host cannot report as a finding, not an unwind. +/// +/// So the module reserves its own, with room to spare: the deepest +/// optimized parse measures in single megabytes and the deepest lift +/// under three. `npm/build.mjs` reads this number and passes it to the +/// linker; `tests/stack.rs` holds the two together. +/// +/// This is address space in the module's linear memory, not resident +/// pages, and it sits far below the memory cap the same build applies. +pub const WASM_STACK_BYTES: usize = 16777216; + +/// The host console, for the panic hook below. +#[cfg(target_arch = "wasm32")] +#[wasm_bindgen] +extern "C" { + #[wasm_bindgen(js_namespace = console, js_name = error)] + fn console_error(message: &str); +} + +/// Runs once when the module is instantiated: routes every panic +/// report to the host's `console.error`. On this target a panic has no +/// stderr to print to and then traps the instance — the host sees a +/// bare `RuntimeError: unreachable` — so without the hook the reason +/// is lost. The trapped instance is not recoverable (a session may be +/// half-mutated): a host that catches a `RuntimeError` must discard +/// the module instance and instantiate the module again. +#[cfg(target_arch = "wasm32")] +#[wasm_bindgen(start)] +pub fn install_panic_hook() { + std::panic::set_hook(Box::new(|info| console_error(&info.to_string()))); +} + /// `[{name, text}]` — the JSON shape sources cross the boundary in. #[derive(Deserialize)] struct SourceIn { @@ -40,10 +83,9 @@ struct SourceIn { /// session does not hold. fn resolve_edit_target(inner: &mut TSession, name: &str) -> Result { let e = if let Some(id) = name.strip_prefix('@') { - let r = inner.resolved(); - let all: Vec = r.user_elements().collect(); - all.into_iter() - .find(|e| r.element_id(*e).to_string() == id) + inner + .resolved() + .element_by_id(id) .ok_or_else(|| format!("element not found: {name}"))? } else { inner @@ -57,9 +99,25 @@ fn resolve_edit_target(inner: &mut TSession, name: &str) -> Result, + values: Vec<(String, EvalValue)>, +} + fn parse_sources(json: &str) -> Result, String> { let sources: Vec = serde_json::from_str(json).map_err(|e| format!("sources must be [{{name, text}}]: {e}"))?; + // A unit's name is its identity everywhere downstream (findings, + // splices, the lifted root namespace), so an empty one is refused + // at the boundary, by position, instead of failing deep inside a + // later emission. + if let Some(i) = sources.iter().position(|s| s.name.is_empty()) { + return Err(format!( + "sources must be [{{name, text}}]: source {i} has an empty name" + )); + } Ok(sources.into_iter().map(|s| (s.name, s.text)).collect()) } @@ -113,6 +171,8 @@ fn verify_status( ("undecided", format!("undecided ({why}; propagation: {m})")) } Some(PropagateOutcome::Undecided) | None => ("undecided", format!("undecided ({why})")), + // A conclusion this build does not recognize stays undecided. + Some(_) => ("undecided", format!("undecided ({why})")), }, } } @@ -167,6 +227,42 @@ fn yes() -> bool { true } +/// The `view` and `lineStyle` vocabularies are the diagram crate's own +/// (`tree`, `interconnection` / `ic`, `state`, `action`, `sequence` / +/// `seq`, `case`, `mixed`; `polyline`, `ortho`), parsed and spelled +/// through it so this surface cannot drift from the others. +fn parse_view(name: &str) -> Result { + name.parse() + .map_err(|e: sysmlv2_viz::ParseOptionError| e.to_string()) +} + +/// A view's canonical spelling (its `--view` value without aliases). +fn view_name(view: sysmlv2_viz::View) -> &'static str { + view.as_str() +} + +/// An absent `lineStyle` is the emitter's default splines. +fn parse_line_style(name: Option<&str>) -> Result { + match name { + None => Ok(sysmlv2_viz::LineStyle::Default), + Some(s) => s + .parse() + .map_err(|e: sysmlv2_viz::ParseOptionError| e.to_string()), + } +} + +/// The memoized line index of a unit, built on first use; a unit whose +/// source the session does not hold (a library unit) indexes as empty. +fn unit_line_index<'a>( + indexes: &'a mut HashMap, + session: &TSession, + unit: usize, +) -> &'a LineIndex { + indexes + .entry(unit) + .or_insert_with(|| LineIndex::new(session.source(unit).unwrap_or(""))) +} + /// One edit-batch operation as JSON (the `edit` method takes an array): /// `{op: "rename", target, newName}` · `{op: "setFeatureValue", target, /// expr}` · `{op: "setFeatureType", target, type}` (replace the written @@ -257,9 +353,9 @@ impl Session { /// the diagram at every top-level element. fn resolve_roots( &mut self, - names: &Option>, + names: Option<&[String]>, ) -> Result>, String> { - let Some(names) = names.as_ref().filter(|n| !n.is_empty()) else { + let Some(names) = names.filter(|n| !n.is_empty()) else { return Ok(None); }; let mut refs = Vec::with_capacity(names.len()); @@ -274,14 +370,80 @@ impl Session { Ok(Some(refs)) } + /// Parse a diagram options document (absent or empty = `{}`, so + /// serde's field defaults apply uniformly) and resolve its scope + /// against the current model — the one path both diagram emitters + /// take, so they accept the same options and read a name the same + /// way. Returns the emitter options with `roots` filled in, and + /// the subtree root. A view usage named as `element` directs its + /// own diagram: the elements are what it exposes (filter conditions + /// applied), as the CLI renders it, while the requested view kind + /// stands — callers name it explicitly here. An empty exposure + /// comes back as `roots: Some([])`: an explicit empty selection, + /// never the whole model (which the emitters draw for a missing + /// selection). + fn diagram_request( + &mut self, + opts_json: Option<&str>, + ) -> Result<(sysmlv2_viz::VizOptions, Option), String> { + let opts: PlantumlOpts = + serde_json::from_str(opts_json.filter(|s| !s.is_empty()).unwrap_or("{}")) + .map_err(|e| format!("bad options: {e}"))?; + let view = parse_view(&opts.view)?; + let line_style = parse_line_style(opts.line_style.as_deref())?; + let mut root = opts + .element + .as_deref() + .map(|name| { + self.inner + .resolved() + .resolve_qualified(name) + .ok_or_else(|| format!("element not found: {name}")) + }) + .transpose()?; + let mut roots = self.resolve_roots(opts.roots.as_deref())?; + if let Some(e) = root { + if let Some((_, exposed)) = sysmlv2_viz::view_directed(self.inner.resolved(), e) { + roots = Some(exposed); + root = None; + } + } + let viz = sysmlv2_viz::VizOptions::default() + .with_direction(if opts.horizontal { + sysmlv2_viz::Direction::LeftToRight + } else { + sysmlv2_viz::Direction::TopToBottom + }) + .with_show_values(opts.show_values) + .with_view(view) + .with_show_notes(opts.show_notes) + .with_show_metadata(opts.show_metadata) + .with_show_inherited(opts.show_inherited) + .with_show_lib(opts.show_lib) + .with_show_imported(opts.show_imported) + .with_line_style(line_style) + .with_std_color(opts.std_color) + .with_link_template(opts.link_template) + .with_roots(roots); + Ok((viz, root)) + } + fn value_to_json(&mut self, v: &EvalValue) -> serde_json::Value { match v { EvalValue::Boolean(b) => json!(b), EvalValue::Integer(i) => json!(i), - EvalValue::Rational(f) => json!(f), + // A JSON number carries an exact rational only when its + // decimal spelling is the value; anything else crosses as an + // explicit fraction with a double approximation alongside. + EvalValue::Rational(r) if r.json_number_is_exact() => json!(r.to_f64()), + EvalValue::Rational(r) => { + let (n, d) = r.to_string_parts(); + json!({ "@rational": format!("{n}/{d}"), "approx": r.to_f64() }) + } + EvalValue::Real(f) => json!(f), EvalValue::String(s) => json!(s), EvalValue::Indeterminate => json!({ "@indeterminate": true }), - EvalValue::Element(e) | EvalValue::Unbound(e) => json!({ + EvalValue::Element(e) | EvalValue::Unbound(e) | EvalValue::UnboundMember(e) => json!({ "@element": self.inner.resolved().element_id(*e).to_string(), "qualifiedName": self.inner.resolved().element_qualified_name(*e), }), @@ -306,8 +468,96 @@ impl Session { } } +/// An immutable library graph reusable across session builds and edits. +/// Prepare the final ordered source bundle once. Changed sources require a new +/// handle. Sessions retain the library independently of this handle's lifetime. +#[wasm_bindgen] +pub struct PreparedLibrary { + inner: Library, +} + +#[wasm_bindgen] +impl PreparedLibrary { + /// Prepare library sources (JSON `[{name, text}]`) with an optional sealed + /// resolution snapshot. Stale or corrupt snapshots fall back to source. + #[wasm_bindgen(constructor)] + pub fn new(sources_json: &str, snapshot: Option>) -> Result { + Ok(Self { + inner: Library::prepared_sources(parse_sources(sources_json)?, snapshot) + .map_err(|e| e.to_string())?, + }) + } +} + #[wasm_bindgen] impl Session { + /// Open sources against a shared prepared library in one model build. + #[wasm_bindgen(js_name = fromSourcesWithPreparedLibrary)] + pub fn from_sources_with_prepared_library( + sources_json: &str, + library: &PreparedLibrary, + ) -> Result { + Ok(Session { + inner: TSession::from_sources_with_library( + parse_sources(sources_json)?, + Some(library.inner.clone()), + ) + .map_err(|e| e.to_string())?, + gen: 0, + }) + } + + /// Open interchange JSON against a shared prepared library. + #[allow(clippy::needless_pass_by_value)] + #[wasm_bindgen(js_name = fromInterchangeJsonWithPreparedLibrary)] + pub fn from_interchange_json_with_prepared_library( + json: &str, + library: &PreparedLibrary, + indent: Option, + ) -> Result { + let value = serde_json::from_str(json).map_err(|e| e.to_string())?; + Ok(Session { + inner: TSession::from_interchange_json_indented( + &value, + Some(&library.inner), + &[], + parse_indent(indent.as_deref())?, + ) + .map_err(|e| e.to_string())?, + gen: 0, + }) + } + + /// Open compact CBOR against a shared prepared library. + #[allow(clippy::needless_pass_by_value)] + #[wasm_bindgen(js_name = fromCompactCborWithPreparedLibrary)] + pub fn from_compact_cbor_with_prepared_library( + bytes: &[u8], + library: &PreparedLibrary, + indent: Option, + ) -> Result { + Ok(Session { + inner: TSession::from_compact_cbor_indented( + bytes, + Some(&library.inner), + parse_indent(indent.as_deref())?, + ) + .map_err(|e| e.to_string())?, + gen: 0, + }) + } + + /// Attach a shared prepared library and rebuild; existing element handles + /// become stale, just as with `loadLibrarySources`. + #[wasm_bindgen(js_name = loadPreparedLibrary)] + pub fn load_prepared_library(&mut self, library: &PreparedLibrary) -> Result<(), String> { + self.inner + .load_library_from(library.inner.clone()) + .map_err(|e| e.to_string())?; + self.gen += 1; + Ok(()) + } + /// Open a session over in-memory sources: JSON `[{name, text}]`. /// Unit names ending in `.kerml` parse as KerML. #[wasm_bindgen(js_name = fromSources)] @@ -319,6 +569,48 @@ impl Session { }) } + /// [`Self::from_sources`] resolved against standard-library sources + /// (JSON `[{name, text}]`, optional sealed snapshot — see + /// [`Self::from_interchange_json`]) in the same build. Opening a + /// session and then calling [`Self::load_library_sources`] resolves + /// the user units twice; this resolves them once. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] + #[wasm_bindgen(js_name = fromSourcesWithLibrary)] + pub fn from_sources_with_library( + sources_json: &str, + lib_sources_json: Option, + lib_snapshot: Option>, + ) -> Result { + let lib = lib_sources_json + .as_deref() + .map(|s| parse_library(s, lib_snapshot)) + .transpose()?; + Ok(Session { + inner: TSession::from_sources_with_library(parse_sources(sources_json)?, lib) + .map_err(|e| e.to_string())?, + gen: 0, + }) + } + + /// The session's check findings — the same JSON the free [`check`] + /// returns for the session's sources and library, read off this + /// session's build instead of a second one (no parse-stage entries: + /// the session holds only units that parsed; without a library the + /// resolution stages are skipped, as `check` skips them). A host + /// that partitions its units by [`check_syntax`] and opens a + /// session over the ones that parsed gets every stage with one + /// resolution. + pub fn check(&mut self) -> String { + let findings = self.inner.check_findings(); + let indexes: HashMap<&str, LineIndex> = self + .inner + .units() + .map(|(_, name, text)| (name, LineIndex::new(text))) + .collect(); + check_findings_json(findings, &indexes) + } + /// Open a session over an interchange JSON document (compact or full /// form; Flexo `{payload, identity}` wrapping accepted). Pass /// standard-library sources (JSON `[{name, text}]`) to name library @@ -332,6 +624,8 @@ impl Session { /// The optional `indent` names the indentation style for the /// lifted unit text: `"tabs"`, or a space count like `"4"` /// (default four spaces; presentation only, never identity). + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = fromInterchangeJson)] pub fn from_interchange_json( json: &str, @@ -359,6 +653,8 @@ impl Session { /// Open a session over a compact-form CBOR payload (a `Uint8Array`) /// — the binary counterpart of [`Self::from_interchange_json`]; /// library and indent arguments as there. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = fromCompactCbor)] pub fn from_compact_cbor( bytes: &[u8], @@ -407,6 +703,18 @@ impl Session { .map(|e| Element { e, gen }) } + /// Look up an interchange UUID, including unnamed and library elements. + /// Returns no handle for malformed or absent IDs. Like name-resolved + /// handles, the result goes stale when the session is rebuilt. + #[wasm_bindgen(js_name = elementById)] + pub fn element_by_id(&mut self, id: &str) -> Option { + let gen = self.gen; + self.inner + .resolved() + .element_by_id(id) + .map(|e| Element { e, gen }) + } + /// Evaluate an ad-hoc KerML query expression at the root namespace /// (the `sysmlv2 query` semantics). Returns the value as JSON; /// elements come back as `{"@element": id, "qualifiedName": …}`. @@ -433,6 +741,8 @@ impl Session { /// slice (semantic mode): `qualified_name` names the view /// usage; the result is the rendered node tree as JSON, or HTML when /// `format` is `"html"`. Evaluation writes nothing into the model. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = renderView)] pub fn render_view( &mut self, @@ -451,6 +761,103 @@ impl Session { }) } + /// Describe a `view` usage for tabular consumers: the rendering it + /// requests (`render …;` → the rendering usage's declared name), + /// the elements it exposes (its `expose` imports with the view's + /// `filter` conditions applied — the same exposure the CLI's + /// view-directed diagrams use), the view usages it owns (a matrix's + /// `columns` sub-view), and its prefix metadata with every owned + /// feature value evaluated (`@MatrixConfig { relationship = "…"; }` + /// → `{ "type": "…::MatrixConfig", "values": { "relationship": "…" } }`). + /// JSON `{ qualifiedName (canonical spelling), id, rendering, exposed: [{ id, qualifiedName, + /// metaclass }], views: [{ name, qualifiedName, id }], metadata: [{ type, + /// values }] }`; errors when the name does not resolve to a view usage. + /// Reads only; nothing is written into the model. + #[wasm_bindgen(js_name = viewInfo)] + pub fn view_info(&mut self, qualified_name: &str) -> Result { + let view = self + .inner + .resolved() + .resolve_qualified(qualified_name) + .ok_or_else(|| format!("element not found: {qualified_name}"))?; + if self.inner.resolved().element_type(view) != "ViewUsage" { + return Err(format!("{qualified_name} is not a view usage")); + } + let (qualified, id, rendering, exposed, views, metadata) = { + let r = self.inner.resolved(); + // The canonical spelling, not the caller's: a request may quote + // names the model spells bare (`P::'Verified'` vs `P::Verified`). + let qualified = r.element_qualified_name(view); + let id = r.element_id(view).to_string(); + let rendering = r.view_rendering(view); + let exposed: Vec = r + .view_exposed_elements(view) + .into_iter() + .map(|e| { + json!({ + "id": r.element_id(e).to_string(), + "qualifiedName": r.element_qualified_name(e), + "metaclass": r.element_type(e), + }) + }) + .collect(); + let owned: Vec = r + .owned_members(view) + .into_iter() + .filter(|&m| r.element_type(m) == "ViewUsage") + .collect(); + let mut views = Vec::with_capacity(owned.len()); + for m in owned { + let name = r.element_name(m).map(str::to_string); + views.push(json!({ + "name": name, + "qualifiedName": r.element_qualified_name(m), + "id": r.element_id(m).to_string(), + })); + } + // Each metadata usage: its (first) type and the evaluated + // values of the features its body declares; unevaluable + // values are omitted rather than failing the whole report. + let mut metadata: Vec = Vec::new(); + for m in r.metadata_of(view) { + let ty = r + .typings(m) + .first() + .and_then(|&t| r.element_qualified_name(t)); + let mut values = Vec::new(); + for f in r.owned_members(m) { + let Some(name) = r.element_name(f).map(str::to_string) else { + continue; + }; + if let Ok(v) = r.evaluate(f) { + values.push((name, v)); + } + } + metadata.push(MetadataValues { ty, values }); + } + (qualified, id, rendering, exposed, views, metadata) + }; + let metadata: Vec = metadata + .into_iter() + .map(|MetadataValues { ty, values }| { + let mut obj = serde_json::Map::new(); + for (name, v) in &values { + obj.insert(name.clone(), self.value_to_json(v)); + } + json!({ "type": ty, "values": serde_json::Value::Object(obj) }) + }) + .collect(); + Ok(json!({ + "qualifiedName": qualified, + "id": id, + "rendering": rendering, + "exposed": exposed, + "views": views, + "metadata": metadata, + }) + .to_string()) + } + /// Evaluate `e`'s bound feature value; JSON, as in [`Self::query`]. pub fn evaluate(&mut self, e: &Element) -> Result { self.guard(e)?; @@ -462,29 +869,204 @@ impl Session { Ok(self.value_to_json(&value).to_string()) } + // ---- derived properties (the spec-name read API) ---- + + /// The derived property `name` of `e`, by its specification name + /// (`"ownedFeature"`, `"owningNamespace"`, `"name"`, …), as JSON: `null` + /// for a null single value, a boolean or string, an array of strings, + /// an element as `{"@id": …}` and a list of elements as an array of + /// them; a target outside the model as `{"outside": true, "id"?: …, + /// "spelling"?: …}` (an element of an unloaded library or a foreign + /// payload by its id, or a reference that never resolved by its + /// spelling). Element handles for the same value come from + /// [`Self::derived_elements`]. Errors when the element's metaclass + /// does not declare the property as derived or the toolkit does not + /// compute it yet; `derives` tells in advance. + pub fn derived(&mut self, e: &Element, name: &str) -> Result { + use sysmlv2_model::json::{DerivedValue, Reference, dangling_id}; + self.guard(e)?; + let value = self.derived_value(e, name)?; + let r = self.inner.resolved(); + let id = |x: ElementRef| serde_json::json!({ "@id": r.element_id(x).to_string() }); + let reference = |x: &Reference| -> Result { + Ok(match x { + Reference::Element(x) => id(*x), + Reference::External(u) => { + serde_json::json!({ "outside": true, "id": u.to_string() }) + } + // The full form spells an unresolved reference as its + // deterministic dangling id: carried beside the spelling. + Reference::Unresolved(s) => serde_json::json!({ + "outside": true, + "spelling": s, + "danglingId": dangling_id(s), + }), + _ => return Err("unsupported reference shape from a newer toolkit".into()), + }) + }; + let json = match &value { + DerivedValue::Null => serde_json::Value::Null, + DerivedValue::Bool(b) => serde_json::Value::Bool(*b), + DerivedValue::Str(s) => serde_json::Value::String(s.clone()), + DerivedValue::Strings(ss) => serde_json::json!(ss), + DerivedValue::Element(x) => id(*x), + DerivedValue::Elements(xs) => { + serde_json::Value::Array(xs.iter().map(|&x| id(x)).collect()) + } + DerivedValue::Reference(x) => reference(x)?, + DerivedValue::References(xs) => { + serde_json::Value::Array(xs.iter().map(reference).collect::>()?) + } + _ => return Err("unsupported derived value shape from a newer toolkit".into()), + }; + Ok(json.to_string()) + } + + /// The element handles of the derived property `name` of `e`: the + /// element of a single-valued value, the elements of a list, the + /// in-model targets of a reference-typed value — a target outside the + /// model has no handle and is *dropped* here (it is in + /// [`Self::derived`]'s JSON as an `outside` object); empty for a + /// string or boolean. Errors as `derived` does. + #[wasm_bindgen(js_name = derivedElements)] + pub fn derived_elements(&mut self, e: &Element, name: &str) -> Result, String> { + use sysmlv2_model::json::DerivedValue; + self.guard(e)?; + let gen = self.gen; + let value = self.derived_value(e, name)?; + let handles: Vec = match &value { + DerivedValue::Element(x) => vec![*x], + DerivedValue::Elements(xs) => xs.clone(), + DerivedValue::Reference(r) => r.element().into_iter().collect(), + DerivedValue::References(rs) => rs.iter().filter_map(|r| r.element()).collect(), + _ => Vec::new(), + }; + Ok(handles.into_iter().map(|x| Element { e: x, gen }).collect()) + } + + fn derived_value( + &mut self, + e: &Element, + name: &str, + ) -> Result { + use sysmlv2_model::json::Derived; + match self.inner.resolved().derived(e.e, name) { + Derived::NotDeclared => Err(format!( + "{name} is not a derived property of {}", + self.inner.resolved().element_type(e.e) + )), + Derived::NotComputed => Err(format!("{name} is not computed by this toolkit yet")), + Derived::Value(v) => Ok(v), + } + } + + /// What `derived` answers for `name` on elements of `metaclass`, + /// decided without a model: `"not-declared"`, `"not-computed"`, + /// `"passthrough"` or `"exact"`. + pub fn derives(metaclass: &str, name: &str) -> String { + use sysmlv2_model::json::Derives; + match sysmlv2_model::json::derives(metaclass, name) { + Derives::NotDeclared => "not-declared", + Derives::NotComputed => "not-computed", + Derives::Passthrough => "passthrough", + Derives::Exact => "exact", + } + .to_string() + } + + /// Whether the abstract syntax owns `name` on `metaclass`. + #[wasm_bindgen(js_name = isOwnedProperty)] + pub fn is_owned_property(metaclass: &str, name: &str) -> bool { + sysmlv2_model::json::is_owned_property(metaclass, name) + } + + /// Every derived property name `derived` can answer on some + /// metaclass. + #[wasm_bindgen(js_name = computedNames)] + pub fn computed_names() -> Vec { + sysmlv2_model::json::computed_names() + .map(str::to_string) + .collect() + } + + /// The closure policy `derived` answers under: `"passthrough"` (the + /// default), `"closure"` or `"closure-implied"`. + #[wasm_bindgen(js_name = closurePolicy)] + pub fn closure_policy(&mut self) -> String { + use sysmlv2_model::json::ClosurePolicy; + match self.inner.resolved().closure_policy() { + ClosurePolicy::Passthrough => "passthrough", + ClosurePolicy::Closure { + include_implied: false, + } => "closure", + ClosurePolicy::Closure { + include_implied: true, + } => "closure-implied", + } + .to_string() + } + + /// Set the closure policy (see `closurePolicy`). + #[wasm_bindgen(js_name = setClosurePolicy)] + pub fn set_closure_policy(&mut self, policy: &str) -> Result<(), String> { + use sysmlv2_model::json::ClosurePolicy; + let policy = match policy { + "passthrough" => ClosurePolicy::Passthrough, + "closure" => ClosurePolicy::Closure { + include_implied: false, + }, + "closure-implied" => ClosurePolicy::Closure { + include_implied: true, + }, + other => { + return Err(format!( + "unknown closure policy {other:?}: passthrough, closure or closure-implied" + )); + } + }; + self.inner.resolved().set_closure_policy(policy); + Ok(()) + } + // ---- navigation ---- - /// The element's qualified name (undefined for anonymous elements). + /// The element's qualified name (undefined for anonymous elements): + /// the specification's derivation, in which a reserved word used as + /// a name stays bare (`part::view`). A model property, not source + /// text — splice [`Self::reference_spelling`] into generated + /// `import`/`expose` targets instead. #[wasm_bindgen(js_name = qualifiedName)] pub fn qualified_name(&mut self, e: &Element) -> Result, String> { self.guard(e)?; Ok(self.inner.resolved().element_qualified_name(e.e)) } - /// The element's declared name. + /// The element's qualified name spelled as reference text that + /// re-parses in either dialect: reserved words and non-basic names + /// quoted (`'part'::'view'` where `qualifiedName` reports + /// `part::view`). Undefined for anonymous elements. + #[wasm_bindgen(js_name = referenceSpelling)] + pub fn reference_spelling(&mut self, e: &Element) -> Result, String> { + self.guard(e)?; + Ok(self.inner.resolved().element_reference_spelling(e.e)) + } + + /// The element's declared name; the specification's `name` (an + /// unnamed feature named by what it redefines) is `derived(e, "name")`. pub fn name(&mut self, e: &Element) -> Result, String> { self.guard(e)?; Ok(self.inner.resolved().element_name(e.e).map(str::to_string)) } - /// The element's declared short name (``), when it has one. + /// The element's declared short name (``), when it has one; + /// the specification's `shortName` is `derived(e, "shortName")`. #[wasm_bindgen(js_name = shortName)] pub fn short_name(&mut self, e: &Element) -> Result, String> { self.guard(e)?; Ok(self .inner .resolved() - .element_short_name(e.e) + .element_declared_short_name(e.e) .map(str::to_string)) } @@ -706,8 +1288,10 @@ impl Session { /// payload digest. The session's library names the effective-name /// targets; decode against the same library version. #[wasm_bindgen(js_name = toCompactCborElided)] - pub fn to_compact_cbor_elided(&self) -> Vec { - self.inner.to_compact_cbor_elided() + pub fn to_compact_cbor_elided(&self) -> Result, String> { + self.inner + .to_compact_cbor_elided() + .map_err(|e| e.to_string()) } /// The model's **state digest** — the content identity a delta @@ -753,7 +1337,7 @@ impl Session { .inner .apply_delta_cbor(bytes, lenient) .map_err(|e| e.to_string())?; - Ok(apply_report_json(result, report)) + Ok(apply_report_json(&result, &report)) } /// Apply a delta payload against a caller-held base document (a @@ -775,7 +1359,7 @@ impl Session { .inner .apply_delta_cbor_to(bytes, &base, lenient) .map_err(|e| e.to_string())?; - Ok(apply_report_json(result, report)) + Ok(apply_report_json(&result, &report)) } /// [`Self::apply_delta_cbor_to`] with the applied result embedded @@ -823,65 +1407,14 @@ impl Session { /// Emit a PlantUML diagram of the session's model. Options as /// a JSON object (see `PlantumlOpts` docs); pass `undefined`/`"{}"` /// for the defaults (tree view). Feed the text to any PlantUML build. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = toPlantuml)] pub fn to_plantuml(&mut self, opts_json: Option) -> Result { - // Absent options deserialize as `{}` so serde's field defaults - // apply uniformly. - let opts_json = opts_json.filter(|s| !s.is_empty()); - let opts: PlantumlOpts = serde_json::from_str(opts_json.as_deref().unwrap_or("{}")) - .map_err(|e| format!("bad options: {e}"))?; - let view = match opts.view.as_str() { - "tree" => sysmlv2_viz::View::Tree, - "interconnection" | "ic" => sysmlv2_viz::View::Interconnection, - "state" => sysmlv2_viz::View::State, - "action" => sysmlv2_viz::View::Action, - "sequence" | "seq" => sysmlv2_viz::View::Sequence, - "case" => sysmlv2_viz::View::Case, - "mixed" => sysmlv2_viz::View::Mixed, - other => { - return Err(format!( - "unknown view: {other} (expected tree, interconnection, state, action, sequence, case, or mixed)" - )); - } - }; - let line_style = match opts.line_style.as_deref() { - None => sysmlv2_viz::LineStyle::Default, - Some("polyline") => sysmlv2_viz::LineStyle::Polyline, - Some("ortho") => sysmlv2_viz::LineStyle::Ortho, - Some(other) => { - return Err(format!( - "unknown line style: {other} (expected polyline or ortho)" - )); - } - }; - let root = match opts.element.as_deref() { - Some(name) => Some( - self.inner - .resolved() - .resolve_qualified(name) - .ok_or_else(|| format!("element not found: {name}"))?, - ), - None => None, - }; - let roots = self.resolve_roots(&opts.roots)?; - let viz = sysmlv2_viz::VizOptions { - direction: if opts.horizontal { - sysmlv2_viz::Direction::LeftToRight - } else { - sysmlv2_viz::Direction::TopToBottom - }, - show_values: opts.show_values, - view, - show_notes: opts.show_notes, - show_metadata: opts.show_metadata, - show_inherited: opts.show_inherited, - show_lib: opts.show_lib, - show_imported: opts.show_imported, - line_style, - std_color: opts.std_color, - link_template: opts.link_template, - roots, - }; + let (viz, root) = self.diagram_request(opts_json.as_deref())?; + if viz.roots.as_ref().is_some_and(|r| r.is_empty()) { + return Ok("@startuml\n' the view exposes nothing\n@enduml\n".to_string()); + } Ok(sysmlv2_viz::plantuml(self.inner.resolved(), root, &viz)) } @@ -889,40 +1422,27 @@ impl Session { /// source spans, and compartment rows; edges with kinds) for a /// view — the native renderer's input. Options as in /// [`Self::to_plantuml`]; views without a graph emitter yet error. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = toGraph)] pub fn to_graph(&mut self, opts_json: Option) -> Result { - let opts_json = opts_json.filter(|s| !s.is_empty()); - let opts: PlantumlOpts = serde_json::from_str(opts_json.as_deref().unwrap_or("{}")) - .map_err(|e| format!("bad options: {e}"))?; - let view = match opts.view.as_str() { - "tree" => sysmlv2_viz::View::Tree, - "interconnection" | "ic" => sysmlv2_viz::View::Interconnection, - "state" => sysmlv2_viz::View::State, - "action" => sysmlv2_viz::View::Action, - other => return Err(format!("no structured-graph emitter for view: {other}")), - }; - let root = match opts.element.as_deref() { - Some(name) => Some( - self.inner - .resolved() - .resolve_qualified(name) - .ok_or_else(|| format!("element not found: {name}"))?, - ), - None => None, - }; - let roots = self.resolve_roots(&opts.roots)?; - let viz = sysmlv2_viz::VizOptions { - view, - show_values: opts.show_values, - show_notes: opts.show_notes, - show_metadata: opts.show_metadata, - show_inherited: opts.show_inherited, - show_lib: opts.show_lib, - show_imported: opts.show_imported, - roots, - ..Default::default() - }; - sysmlv2_viz::graph(self.inner.resolved(), root, &viz).map(|v| v.to_string()) + let (viz, root) = self.diagram_request(opts_json.as_deref())?; + let view = view_name(viz.view); + if !matches!( + viz.view, + sysmlv2_viz::View::Tree + | sysmlv2_viz::View::Interconnection + | sysmlv2_viz::View::State + | sysmlv2_viz::View::Action + ) { + return Err(format!("no structured-graph emitter for view: {view}")); + } + if viz.roots.as_ref().is_some_and(|r| r.is_empty()) { + return Ok(json!({ "view": view, "nodes": [], "edges": [] }).to_string()); + } + sysmlv2_viz::graph(self.inner.resolved(), root, &viz) + .map(|v| v.to_string()) + .map_err(|e| e.to_string()) } /// Apply an edit batch (JSON array of `EditOpIn` operations) via @@ -936,9 +1456,16 @@ impl Session { /// newId]…], findings: [string…], splices: [{unit, start, end, /// text}…]}` — splices in pre-commit byte offsets per unit, exactly /// what an editor mirror needs to replay the change. + /// + /// A `rename` whose new name a sibling in the same owner already + /// carries (or that another rename in the batch gives a sibling) + /// is dropped rather than refusing the batch: the rest commits and + /// each dropped rename is one `findings` line. A batch of nothing + /// but dropped renames commits nothing and leaves handles valid. pub fn edit(&mut self, ops_json: &str) -> Result { let resolved = self.resolve_ops(Self::parse_ops(ops_json)?)?; let mut batch = self.inner.edit(); + batch.skip_colliding_renames(); Self::stage_ops(&mut batch, &resolved); let report = batch.commit().map_err(|e| e.to_string())?; self.gen += 1; @@ -963,6 +1490,7 @@ impl Session { } }; let mut batch = self.inner.edit(); + batch.skip_colliding_renames(); Self::stage_ops(&mut batch, &resolved); Ok(match batch.check() { Ok(report) => { @@ -1171,6 +1699,8 @@ impl Session { /// unitName?, line?, col?}`, empty for satisfied constraints); /// `features` = the free features the propagation term references /// (the keys into `ranges`). + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] pub fn verify(&mut self, opts_json: Option) -> Result { #[derive(Deserialize)] #[serde(rename_all = "camelCase", deny_unknown_fields)] @@ -1193,7 +1723,9 @@ impl Session { .units() .map(|(i, n, _)| (i, n.to_string())) .collect(); - let mut indexes: std::collections::HashMap = Default::default(); + // One line index per unit, built on first use and shared by the + // constraint spans and their bindings' declaration sites. + let mut indexes: HashMap = HashMap::new(); let (mut sat, mut vio, mut und) = (0usize, 0usize, 0usize); let inner = &self.inner; let constraints: Vec = report @@ -1240,11 +1772,14 @@ impl Session { // Declaration site → position, when the feature // lives in a user unit (library sources are not // held, so library declarations carry no position). - let pos = b.site.and_then(|(unit, span)| { - let src = inner.source(unit)?; - let lc = LineIndex::new(src).line_col(span.start); - Some((unit, lc)) - }); + let pos = b + .site + .filter(|(unit, _)| inner.source(*unit).is_some()) + .map(|(unit, span)| { + let lc = + unit_line_index(&mut indexes, inner, unit).line_col(span.start); + (unit, lc) + }); json!({ "feature": b.feature, "value": b.value, @@ -1254,9 +1789,7 @@ impl Session { }) }) .collect(); - let li = indexes - .entry(c.unit) - .or_insert_with(|| LineIndex::new(inner.source(c.unit).unwrap_or(""))); + let li = unit_line_index(&mut indexes, inner, c.unit); let start = li.line_col(c.span.start); let end = li.line_col(c.span.end); json!({ @@ -1285,6 +1818,7 @@ impl Session { "feature": r.feature, "unit": r.unit, "range": r.range, + "rangeApprox": r.range_approx, "narrowed": r.narrowed, }) }) @@ -1306,24 +1840,31 @@ impl Session { /// | {severity, …options}}}`); absent means every rule at its /// default severity; unknown ids/options surface as `lint-config` /// findings, and unreadable JSON is the only error. Returns - /// `{findings: [{rule, severity, message, unit, unitName, line, - /// col, endLine, endCol, element, suggest, fix}], summary: - /// {errors, warnings, infos, hints}}` — 1-based positions over the finding's - /// name span; `unit` and the positions are null on `lint-config` - /// findings. `element` (nullable) = the finding's edit-target - /// spelling (`::`-qualified name or `@`) for host quick fixes; + /// `{findings: [{stage, rule, severity, message, unit, unitName, + /// start, end, line, col, endLine, endCol, element, suggest, fix, + /// alternatives}], summary: {errors, warnings, infos, hints}}` (the + /// `sysmlv2_lint::json` report shape, shared with the CLI's + /// `--format json`; `stage` is always `lint` here) — byte offsets + /// and 1-based positions over the finding's name span; `unit` and + /// the positions are null on `lint-config` findings. `element` + /// (nullable) = the finding's edit-target spelling (`::`-qualified + /// name or `@`) for host quick fixes; /// `suggest` (nullable) = a naming finding's style-converted /// replacement name. `fix` (nullable) - /// = `{label, deletes, edits: [{unit, unitName, start, end, - /// replacement}]}` with **byte** offsets over the unit's current - /// text (the splice currency every edit surface here uses); - /// `deletes` marks fixes hosts must gate behind explicit opt-in. + /// = `{label, deletes, semantic, edits: [{unit, unitName, start, + /// end, replacement}]}` with **byte** offsets over the unit's + /// current text (the splice currency every edit surface here uses); + /// `deletes` marks fixes hosts must gate behind explicit opt-in, and + /// `semantic` marks fixes that change what a declaration means + /// (never part of a fix-all sweep). /// `alternatives` (array, same shape as `fix`) are equally-valid /// remedies for a quick-fix menu — a dimensionally ambiguous unit /// lists every compatible quantity type — never auto-applied. + // The export boundary converts an optional string only when owned. + #[allow(clippy::needless_pass_by_value)] pub fn lint(&mut self, config_json: Option) -> Result { let cfg = match config_json.as_deref().filter(|s| !s.trim().is_empty()) { - Some(text) => sysmlv2_lint::Config::from_json(text)?, + Some(text) => sysmlv2_lint::Config::from_json(text).map_err(|e| e.to_string())?, None => sysmlv2_lint::Config::default(), }; // The textual tier (`indentation`) reads the units' source @@ -1339,81 +1880,20 @@ impl Session { .map(|(i, n, t)| (*i, n.as_str(), t.as_str())) .collect(); let findings = sysmlv2_lint::lint_units(self.inner.resolved(), &cfg, &units); - let names: std::collections::HashMap = self - .inner - .units() - .map(|(i, n, _)| (i, n.to_string())) - .collect(); - let mut indexes: std::collections::HashMap = Default::default(); - let inner = &self.inner; - let (mut errors, mut warnings, mut infos, mut hints) = (0usize, 0usize, 0usize, 0usize); - let findings_json: Vec = findings - .iter() - .map(|f| { - let severity = match f.severity { - sysmlv2_lint::Severity::Error => { - errors += 1; - "error" - } - sysmlv2_lint::Severity::Info => { - infos += 1; - "info" - } - sysmlv2_lint::Severity::Hint => { - hints += 1; - "hint" - } - _ => { - warnings += 1; - "warn" - } - }; - let pos = f.unit.zip(f.span).map(|(unit, span)| { - let li = indexes - .entry(unit) - .or_insert_with(|| LineIndex::new(inner.source(unit).unwrap_or(""))); - (unit, li.line_col(span.start), li.line_col(span.end)) - }); - let fix_json = |fx: &sysmlv2_lint::Fix| { - let edits: Vec = fx - .edits - .iter() - .map(|e| { - json!({ - "unit": e.unit, - "unitName": names.get(&e.unit), - "start": e.span.start, - "end": e.span.end, - "replacement": e.replacement, - }) - }) - .collect(); - json!({"label": fx.label, "deletes": fx.deletes, "edits": edits}) - }; - let alternatives: Vec = - f.alternatives.iter().map(fix_json).collect(); - json!({ - "rule": f.rule, - "severity": severity, - "message": f.message, - "unit": f.unit, - "unitName": f.unit.and_then(|u| names.get(&u)), - "line": pos.map(|(_, s, _)| s.line), - "col": pos.map(|(_, s, _)| s.col), - "endLine": pos.map(|(_, _, e)| e.line), - "endCol": pos.map(|(_, _, e)| e.col), - "element": f.element, - "suggest": f.suggest, - "fix": f.fix.as_ref().map(fix_json), - "alternatives": alternatives, - }) - }) - .collect(); - Ok(json!({ - "findings": findings_json, - "summary": {"errors": errors, "warnings": warnings, "infos": infos, "hints": hints}, - }) - .to_string()) + // The shared report shape (`sysmlv2_lint::json`): engine unit + // indexes are reported unchanged — they are the session's — so + // every unit gets an identity alias (the table reports only + // aliased units). + let mut table = sysmlv2_lint::json::Units::new(); + for (i, name, text) in &texts { + table.add(*i, name, text); + table.alias(*i, *i); + } + let mut report = sysmlv2_lint::json::Report::new(); + for f in &findings { + report.push_finding(f, &table); + } + Ok(report.into_value().to_string()) } /// The lint engine's validated generated-ownership join, exposed @@ -1500,6 +1980,8 @@ impl Session { /// stays on one line. Rejects input that is not a single well-formed /// expression, reporting the first diagnostic — a formatter must not /// guess at broken input. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = formatQuery)] pub fn format_query( text: &str, @@ -1529,11 +2011,13 @@ pub fn format_query( /// diagnostics — a formatter must not guess at broken input — reporting /// the first as `":"` (1-based, byte columns) so /// hosts can map it onto their own spans. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = formatSource)] pub fn format_source_js(text: &str, config_json: Option) -> Result { let config = match config_json.as_deref() { None | Some("") => sysmlv2_lint::Config::default(), - Some(json) => sysmlv2_lint::Config::from_json(json)?, + Some(json) => sysmlv2_lint::Config::from_json(json).map_err(|e| e.to_string())?, }; sysmlv2_syntax::print::format_source_opts( text, @@ -1570,10 +2054,12 @@ pub fn member_structure_digest_js(text: &str) -> Result { /// configuration (absent/empty = engine defaults): resolved formatter /// options + enabled auto-fix rules/options + the canonicalizer /// schema version — the `canonicalizationDigest` provenance baseline. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = canonicalizationDigest)] pub fn canonicalization_digest_js(config_json: Option) -> Result { let cfg = match config_json.as_deref().filter(|s| !s.trim().is_empty()) { - Some(text) => sysmlv2_lint::Config::from_json(text)?, + Some(text) => sysmlv2_lint::Config::from_json(text).map_err(|e| e.to_string())?, None => sysmlv2_lint::Config::default(), }; Ok(sysmlv2_lint::canonicalization_digest(&cfg)) @@ -1590,6 +2076,7 @@ pub fn canonicalization_digest_js(config_json: Option) -> Result String { let rules: Vec = sysmlv2_lint::RULES @@ -1618,23 +2105,29 @@ pub fn lint_rules() -> String { .options .iter() .map(|o| { - let kind = match &o.kind { - sysmlv2_lint::OptionKind::Int { default, min, zero } => json!({ - "kind": "int", "default": default, "min": min, "zero": zero, - }), - sysmlv2_lint::OptionKind::Choice { default, values } => json!({ - "kind": "choice", "default": default, "values": values, - }), - }; - let mut o = json!({"key": o.key, "label": o.label}); - o.as_object_mut() - .unwrap() - .extend(kind.as_object().unwrap().clone()); - o + // One flat object: the option's identity followed by + // the fields its kind contributes. + let mut entry = serde_json::Map::new(); + entry.insert("key".to_string(), json!(o.key)); + entry.insert("label".to_string(), json!(o.label)); + match &o.kind { + sysmlv2_lint::OptionKind::Int { default, min, zero } => { + entry.insert("kind".to_string(), json!("int")); + entry.insert("default".to_string(), json!(default)); + entry.insert("min".to_string(), json!(min)); + entry.insert("zero".to_string(), json!(zero)); + } + sysmlv2_lint::OptionKind::Choice { default, values } => { + entry.insert("kind".to_string(), json!("choice")); + entry.insert("default".to_string(), json!(default)); + entry.insert("values".to_string(), json!(values)); + } + } + serde_json::Value::Object(entry) }) .collect(); json!({ - "id": r.id, + "id": r.id.id(), "description": r.description, "default": r.default.as_str(), "styles": r.styles, @@ -1644,17 +2137,64 @@ pub fn lint_rules() -> String { }) }) .collect(); - serde_json::to_string(&rules).unwrap() + serde_json::Value::Array(rules).to_string() +} + +/// Repair sources (JSON `[{name, text}]`) that fail to parse so a +/// session can be built over what parsed: a member carrying a parse +/// error is removed (a failed member the parser skipped is recovered +/// from the tokens around the error), bodies left open at the end of a +/// unit get their closers appended, until each unit parses. Returns JSON +/// `{sources: [{name, text}], dropped: [{unit, start, end, line, col, +/// endLine, endCol, text, inserted, linesRemoved, wholeLines, message}], +/// unrepaired: [{unit, line, col, message}]}` — `dropped` in the +/// original texts' coordinates (byte offsets and byte columns, as `check` +/// reports; `inserted` holds appended closers, then `text` is empty and +/// the span is empty; `linesRemoved` and `wholeLines` map a line of the +/// repaired text back to the original), `unrepaired` naming units still +/// broken after the repair, positioned in their repaired text. Units +/// that parse come back unchanged. +#[wasm_bindgen(js_name = lenientSources)] +pub fn lenient_sources(sources_json: &str) -> Result { + let sources = parse_sources(sources_json)?; + let result = sysmlv2_transform::lenient_sources(&sources); + let sources: Vec = result + .sources + .into_iter() + .map(|(name, text)| json!({"name": name, "text": text})) + .collect(); + let dropped: Vec = result + .dropped + .into_iter() + .map(|d| { + json!({ + "unit": d.unit, "start": d.start, "end": d.end, + "line": d.line, "col": d.col, "endLine": d.end_line, "endCol": d.end_col, + "text": d.text, "inserted": d.inserted, "message": d.message, + "linesRemoved": d.lines_removed, "wholeLines": d.whole_lines, + }) + }) + .collect(); + let unrepaired: Vec = result + .unrepaired + .into_iter() + .map(|u| json!({"unit": u.unit, "line": u.line, "col": u.col, "message": u.message})) + .collect(); + Ok(json!({"sources": sources, "dropped": dropped, "unrepaired": unrepaired}).to_string()) } /// Check sources (JSON `[{name, text}]`) the way `sysmlv2 check` does: /// per-unit parse and body-context validation always; referential and /// semantic checks against the standard library when `lib_sources_json` /// (same shape) is given. Returns findings as a JSON string: -/// `[{severity, message, unit, line, col, endLine, endCol}]` (1-based -/// positions; the end pair spans the full diagnostic, so markers cover -/// the whole offending construct rather than just its start). A broken -/// parse is a finding, not an error. +/// `[{severity, stage, message, unit, line, col, endLine, endCol}]` +/// (1-based positions; the end pair spans the full diagnostic, so +/// markers cover the whole offending construct rather than just its +/// start). `stage` is `parse`, `context`, `referential` or `semantic`; +/// only `parse` findings keep a unit out of a session. A broken parse +/// is a finding, not an error. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] #[wasm_bindgen] pub fn check( sources_json: &str, @@ -1667,10 +2207,33 @@ pub fn check( .map(|s| parse_library(s, lib_snapshot)) .transpose()?; let findings = check_sources_with_library(&sources, lib.as_ref()).map_err(|e| e.to_string())?; - let indexes: std::collections::HashMap<&str, LineIndex> = sources + let indexes: HashMap<&str, LineIndex> = sources + .iter() + .map(|(name, src)| (name.as_str(), LineIndex::new(src))) + .collect(); + Ok(check_findings_json(findings, &indexes)) +} + +/// The parse and context stages of [`check`] alone — no model is built, +/// so the cost is a parse per unit. The partition step of a host that +/// then opens a [`Session`] over the units that parsed and reads the +/// resolution stages from [`Session::check`]. +#[wasm_bindgen(js_name = checkSyntax)] +pub fn check_syntax(sources_json: &str) -> Result { + let sources = parse_sources(sources_json)?; + let findings = sysmlv2_transform::check_sources_syntax(&sources); + let indexes: HashMap<&str, LineIndex> = sources .iter() .map(|(name, src)| (name.as_str(), LineIndex::new(src))) .collect(); + Ok(check_findings_json(findings, &indexes)) +} + +/// The findings array `check` and its session twin share. +fn check_findings_json( + findings: Vec, + indexes: &HashMap<&str, LineIndex>, +) -> String { let findings: Vec = findings .into_iter() .map(|f| { @@ -1682,6 +2245,7 @@ pub fn check( sysmlv2_transform::Severity::Error => "error", sysmlv2_transform::Severity::Warning => "warning", }, + "stage": f.stage.as_str(), "message": f.message, "unit": f.unit, "line": f.line, @@ -1694,7 +2258,7 @@ pub fn check( obj }) .collect(); - Ok(serde_json::Value::Array(findings).to_string()) + serde_json::Value::Array(findings).to_string() } /// JSON envelope shared by the delta-apply surfaces. @@ -1714,30 +2278,60 @@ fn apply_report_value(report: &sysmlv2_cbor::ApplyReport) -> serde_json::Value { }) } -fn apply_report_json(result: serde_json::Value, report: sysmlv2_cbor::ApplyReport) -> String { - serde_json::json!({ "result": result, "report": apply_report_value(&report) }).to_string() +fn apply_report_json(result: &serde_json::Value, report: &sysmlv2_cbor::ApplyReport) -> String { + serde_json::json!({ "result": result, "report": apply_report_value(report) }).to_string() } /// The canonical spelling of an element name: /// JSON `{"spelling", "quoted"}` — `spelling` is exactly what the /// printer emits (bare, or a single-quoted restricted name for reserved /// words and non-basic characters) and `quoted` says which. Errors when -/// the string cannot be a name (empty). `dialect` is `"sysml"` (default) -/// or `"kerml"`; the reserved-word sets differ. Generators that mint +/// the string cannot be a name (empty). `dialect` is `"sysml"` or +/// `"kerml"`; the reserved-word sets differ, and an omitted dialect +/// means SysML here (unlike `spellReference`, whose omitted dialect +/// means either). Generators that mint /// names from external vocabularies call this instead of copying the /// parser's keyword table. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] #[wasm_bindgen(js_name = canonicalName)] pub fn canonical_name_js(name: &str, dialect: Option) -> Result { - let dialect = match dialect.as_deref() { - None | Some("") | Some("sysml") => sysmlv2_syntax::ast::Dialect::Sysml, - Some("kerml") => sysmlv2_syntax::ast::Dialect::Kerml, - Some(d) => return Err(format!("dialect must be \"sysml\" or \"kerml\", got {d:?}")), - }; + let dialect = parse_dialect(dialect.as_deref())?.unwrap_or(sysmlv2_syntax::ast::Dialect::Sysml); let c = sysmlv2_syntax::name::canonical_name(dialect, name).map_err(|e| e.to_string())?; Ok(json!({ "spelling": c.spelling, "quoted": c.quoted }).to_string()) } +/// Respell a canonical qualified name — as `qualifiedName` reports it, +/// or as interchange JSON carries it — as reference text that parses: +/// reserved words and non-basic names quoted per segment +/// (`spellReference("part::view")` is `'part'::'view'`). `dialect` is +/// `"sysml"` or `"kerml"` for text going into a unit of that kind; +/// omitted, the spelling re-parses in either (every reserved word of +/// both dialects is quoted). Hosts generating `import`/`expose` lines +/// call this instead of quoting segments themselves. +// The export boundary converts an optional string only when owned. +#[allow(clippy::needless_pass_by_value)] +#[wasm_bindgen(js_name = spellReference)] +pub fn spell_reference_js(qualified_name: &str, dialect: Option) -> Result { + let dialect = parse_dialect(dialect.as_deref())?; + Ok(sysmlv2_syntax::name::respell_canonical( + dialect, + qualified_name, + )) +} + +/// `"sysml"` / `"kerml"` → the dialect; absent or empty → `None`. +fn parse_dialect(dialect: Option<&str>) -> Result, String> { + match dialect { + None | Some("") => Ok(None), + Some("sysml") => Ok(Some(sysmlv2_syntax::ast::Dialect::Sysml)), + Some("kerml") => Ok(Some(sysmlv2_syntax::ast::Dialect::Kerml)), + Some(d) => Err(format!("dialect must be \"sysml\" or \"kerml\", got {d:?}")), + } +} + /// The toolkit version this module was built from. +#[must_use] #[wasm_bindgen] pub fn version() -> String { env!("CARGO_PKG_VERSION").to_string() @@ -1854,11 +2448,9 @@ pub fn delta_cbor_between( Some(s) => serde_json::from_str(&s).map_err(|e| e.to_string())?, None => Vec::new(), }; - let opts = sysmlv2_cbor::DeltaOptions { - portable, - units, - ..Default::default() - }; + let opts = sysmlv2_cbor::DeltaOptions::new() + .with_portable(portable) + .with_units(units); if elide.unwrap_or(false) { sysmlv2_cbor::delta_compact_cbor_elided(&base, &target, &opts, &|_| None) .map_err(|e| e.to_string()) @@ -1875,6 +2467,7 @@ pub fn delta_cbor_between( /// payload. Kind codes are the `cbor_tables` constants (0 bool, /// 1 str, 2 str list, 3 ref, 4 ref list, 5 enum, 6 literal, /// 7 element id). +#[must_use] #[wasm_bindgen(js_name = codecTables)] pub fn codec_tables(full: bool) -> String { let set = if full { @@ -1935,14 +2528,20 @@ pub struct LspServer { inner: sysmlv2_lsp::PushServer, } +impl Default for LspServer { + fn default() -> LspServer { + LspServer::new() + } +} + #[wasm_bindgen] impl LspServer { /// The syntax-tier-only server (no standard library). /// NOTE: a fallible `#[wasm_bindgen(constructor)]` (Result return) /// leaves the JS object with a null pointer — keep the constructor /// infallible and use [`Self::with_library`] for the library shape. + #[must_use] #[wasm_bindgen(constructor)] - #[allow(clippy::new_without_default)] pub fn new() -> LspServer { LspServer { inner: sysmlv2_lsp::PushServer::new(), diff --git a/crates/sysmlv2-wasm/tests/api.rs b/crates/sysmlv2-wasm/tests/api.rs index 75a60b9..89dff95 100644 --- a/crates/sysmlv2-wasm/tests/api.rs +++ b/crates/sysmlv2-wasm/tests/api.rs @@ -6,7 +6,7 @@ use sysmlv2_wasm::{ Session, canonical_name_js, canonicalize_compact, check, graph_normalize_compact, - state_digest_of, version, + spell_reference_js, state_digest_of, version, }; fn sources(pairs: &[(&str, &str)]) -> String { @@ -19,6 +19,11 @@ fn sources(pairs: &[(&str, &str)]) -> String { .unwrap() } +/// A byte offset reported as a JSON number, as an index. +fn offset(v: &serde_json::Value) -> usize { + usize::try_from(v.as_u64().expect("offset is a number")).expect("offset indexes this host") +} + const FLASHLIGHT: &str = "package Flashlight {\n part def Body;\n part def Battery {\n attribute voltage = 3;\n }\n part flashlight {\n part body : Body;\n part battery : Battery;\n }\n}\n"; #[test] @@ -281,6 +286,50 @@ fn check_findings_shape() { ); } +/// A user root package named like a standard-library root: `check` +/// reports the collision at the user declaration, and `resolve` keeps +/// landing on the library package (the behavior the warning describes). +#[test] +fn check_reports_user_roots_shadowing_library_roots() { + let lib = sources(&[( + "MiniLib.sysml", + "standard library package Requirements { requirement def Base; }", + )]); + let user = sources(&[( + "shadow.sysml", + "package Requirements {\n requirement def Speed;\n}\n", + )]); + let findings = check(&user, Some(lib.clone()), None).unwrap(); + let findings: serde_json::Value = serde_json::from_str(&findings).unwrap(); + assert_eq!( + findings, + serde_json::json!([{ + "severity": "warning", + "stage": "referential", + "message": "root package `Requirements` shadows the standard library package \ + `Requirements`; references resolve to the library", + "unit": "shadow.sysml", + "line": 1, + "col": 9, + "endLine": 1, + "endCol": 9 + "Requirements".len(), + }]) + ); + // Without a library there is nothing to shadow. + let alone = check(&user, None, None).unwrap(); + assert_eq!( + serde_json::from_str::(&alone).unwrap(), + serde_json::json!([]) + ); + + let mut s = Session::from_sources(&user).unwrap(); + s.load_library_sources(&lib, None).unwrap(); + let pkg = s.resolve("Requirements").expect("the root name resolves"); + assert_eq!(s.metaclass(&pkg).unwrap(), "LibraryPackage"); + assert!(s.is_library_element(&pkg).unwrap()); + assert!(s.resolve("Requirements::Speed").is_none()); +} + #[test] fn version_matches_crate() { assert_eq!(version(), env!("CARGO_PKG_VERSION")); @@ -447,9 +496,9 @@ fn edit_batch_renames_and_reports_splices() { let mut cursor = 0usize; for sp in splices { assert_eq!(sp["unit"].as_str().unwrap(), "flashlight.sysml"); - replayed.push_str(&FLASHLIGHT[cursor..sp["start"].as_u64().unwrap() as usize]); + replayed.push_str(&FLASHLIGHT[cursor..offset(&sp["start"])]); replayed.push_str(sp["text"].as_str().unwrap()); - cursor = sp["end"].as_u64().unwrap() as usize; + cursor = offset(&sp["end"]); } replayed.push_str(&FLASHLIGHT[cursor..]); let post = s.source(0).unwrap(); @@ -688,10 +737,9 @@ fn value_source_reports_the_bound_expression() { // the declared name. let site: serde_json::Value = serde_json::from_str(&s.declaration_site(&v).unwrap().expect("v has a site")).unwrap(); - let unit = site["unit"].as_u64().unwrap() as usize; + let unit = offset(&site["unit"]); let src = s.source(unit).unwrap(); - let text = - &src[site["start"].as_u64().unwrap() as usize..site["end"].as_u64().unwrap() as usize]; + let text = &src[offset(&site["start"])..offset(&site["end"])]; assert_eq!(text, "v"); } @@ -804,9 +852,8 @@ fn lint_reports_configurable_findings_with_positions_and_fixes() { let fix = &unused["fix"]; assert_eq!(fix["deletes"], true); let edit = &fix["edits"].as_array().unwrap()[0]; - let unit = edit["unit"].as_u64().unwrap() as usize; - let cut = &s.source(unit).unwrap() - [edit["start"].as_u64().unwrap() as usize..edit["end"].as_u64().unwrap() as usize]; + let unit = offset(&edit["unit"]); + let cut = &s.source(unit).unwrap()[offset(&edit["start"])..offset(&edit["end"])]; assert_eq!(cut, "in radius : Real;"); assert_eq!(report["summary"]["warnings"], 2); assert_eq!(report["summary"]["errors"], 0); @@ -1005,10 +1052,11 @@ fn codec_tables_expose_the_wire_vocabulary() { fn foreign_payload_base_digests_and_applies_raw() { use sysmlv2_wasm::{delta_cbor_between, describe_cbor, state_digest_of}; // A payload produced elsewhere: a session under its own unit name, - // exported to compact JSON. The receiving session decodes it and - // must recognize it as a strict delta's base by its *content* — - // lifting it into a session re-derives ids, so only the raw digest - // can match. + // exported to compact JSON. The receiving session loads it keeping + // the document's ids (explicit ids), so the loaded session *is* the + // file's identity: its state digest equals the raw digest, and a + // strict delta recorded against the file applies to the session as + // well as to the caller-held base document. let producer = Session::from_sources(&sources(&[("v1.sysml", FLASHLIGHT)])).unwrap(); let base_json = producer.to_compact_json(); let target = Session::from_sources(&sources(&[( @@ -1028,23 +1076,21 @@ fn foreign_payload_base_digests_and_applies_raw() { let d: serde_json::Value = serde_json::from_str(&describe_cbor(&delta).unwrap()).unwrap(); let base_digest = d["delta"]["baseDigest"].as_str().unwrap(); - // Raw digest of the payload document = the delta's base digest; - // the session lift digests differently (ids re-derive). + // Raw digest of the payload document = the delta's base digest = the + // loaded session's digest. assert_eq!(state_digest_of(&base_json).unwrap(), base_digest); let receiver = Session::from_interchange_json(&base_json, None, None, None).unwrap(); - assert_ne!( + assert_eq!( receiver.state_digest(), base_digest, - "session lift is not the file's identity" + "a loaded payload keeps its ids, so the session is the file's identity" ); - // Strict apply: refused against the receiver's lifted model, clean - // against the caller-held base document. - let against_session = receiver.apply_delta_cbor(&delta, false); - assert!( - against_session.is_err(), - "lifted base diverges, strict apply refuses" - ); + // Strict apply: clean against the receiver's loaded model and + // against the caller-held base document alike. + let against_session: serde_json::Value = + serde_json::from_str(&receiver.apply_delta_cbor(&delta, false).unwrap()).unwrap(); + assert_eq!(against_session["report"]["baseMatched"], true); let applied: serde_json::Value = serde_json::from_str( &receiver .apply_delta_cbor_to(&delta, &base_json, false) @@ -1649,3 +1695,620 @@ fn render_view_accepts_plain_dom_parts_without_a_template_root() { "

Overview

A rendered view.

" ); } + +#[test] +fn anonymous_graph_elements_are_reachable_by_id() { + let source = "package P { action a; action b; succession first a then b; constraint { true } }"; + let mut s = Session::from_sources(&sources(&[("anonymous.sysml", source)])).unwrap(); + let graph: serde_json::Value = + serde_json::from_str(&s.to_graph(Some(r#"{"view":"tree"}"#.into())).unwrap()).unwrap(); + for kind in ["ConstraintUsage", "SuccessionAsUsage"] { + let node = graph["nodes"] + .as_array() + .unwrap() + .iter() + .find(|n| n["metaclass"] == kind) + .unwrap(); + let id = node["id"].as_str().unwrap(); + assert!(node.get("qname").is_none_or(serde_json::Value::is_null)); + assert!(s.resolve(&format!("@{id}")).is_none()); + let e = s.element_by_id(id).expect("graph ID resolves"); + assert_eq!(s.metaclass(&e).unwrap(), kind); + assert_eq!(s.element_id(&e).unwrap(), id); + assert_eq!(s.qualified_name(&e).unwrap(), None); + assert!(s.declaration_site(&e).unwrap().is_some()); + assert!(s.member_source(&format!("@{id}")).is_ok()); + } + assert_eq!(s.source(0).unwrap(), source); + for id in [ + "", + "not-an-id", + "P::a", + "00000000-0000-0000-0000-000000000000", + ] { + assert!(s.element_by_id(id).is_none()); + } + let a = s.resolve("P::a").unwrap(); + let id = s.element_id(&a).unwrap(); + let a_by_id = s.element_by_id(&id).unwrap(); + s.edit(r#"[{"op":"rename","target":"P::a","newName":"renamed"}]"#) + .unwrap(); + assert!(s.metaclass(&a_by_id).is_err()); + assert!(s.element_by_id(&id).is_none()); + let renamed = s.resolve("P::renamed").unwrap(); + let new_id = s.element_id(&renamed).unwrap(); + assert!(s.element_by_id(&new_id).is_some()); +} + +#[test] +fn id_lookup_preserves_library_read_only_and_handle_generation() { + let mut s = Session::from_sources(&sources(&[("main.sysml", "package P;")])).unwrap(); + let p = s.resolve("P").unwrap(); + let id = s.element_id(&p).unwrap(); + let old = s.element_by_id(&id).unwrap(); + s.load_library_sources( + &sources(&[( + "mini.kerml", + "standard library package Mini { class Thing; }", + )]), + None, + ) + .unwrap(); + assert!(s.metaclass(&old).is_err()); + assert!(s.element_by_id(&id).is_some()); + let lib = s.resolve("Mini::Thing").unwrap(); + let lib_id = s.element_id(&lib).unwrap(); + let found = s.element_by_id(&lib_id).unwrap(); + assert!(s.is_library_element(&found).unwrap()); + let before = s.units(); + let error = s + .edit(&serde_json::json!([{"op":"remove","target":format!("@{lib_id}")}]).to_string()) + .unwrap_err(); + assert!(error.contains("read-only"), "{error}"); + assert_eq!(s.units(), before); +} + +/// A stand-in for the standard `Views` library package, loaded as a +/// library so that `asElementTable` is a library element — referenced +/// by spelling, never by id, exactly as the shipped library is. +const VIEWS_LIBRARY: &str = "standard library package Views {\n rendering def Rendering;\n rendering def TabularRendering :> Rendering;\n rendering asElementTable : TabularRendering;\n}\n"; + +/// A matrix-view fixture over [`VIEWS_LIBRARY`]: the generated support +/// package, a model, and two views — one per tabular rendering — plus +/// a non-view. +fn matrix_view_session() -> Session { + let mut s = Session::from_sources(&matrix_view_sources()).unwrap(); + s.load_library_sources(&sources(&[("Views.sysml", VIEWS_LIBRARY)]), None) + .unwrap(); + s +} + +fn matrix_view_sources() -> String { + sources(&[ + ( + "matrix.sysml", + "package MatrixViews {\n import Views::*;\n metadata def MatrixConfig {\n attribute attributes[0..*];\n attribute relationship[0..1];\n }\n rendering def RelationshipMatrix :> TabularRendering;\n rendering asRelationshipMatrix : RelationshipMatrix;\n}\n", + ), + ( + "m.sysml", + "package M {\n part def A;\n part def B;\n part a : A;\n part b : B;\n part c {\n part d;\n }\n}\n", + ), + ( + "s.sysml", + "package S {\n import Views::*;\n import MatrixViews::*;\n view 'Part allocations' {\n @MatrixConfig { relationship = \"allocation\"; }\n expose M::a;\n expose M::b;\n view columns {\n expose M::c::**;\n }\n render asRelationshipMatrix;\n }\n view masses {\n @MatrixConfig { attributes = (\"mass\", \"voltage\"); }\n expose M::*;\n render asElementTable;\n }\n view nobody;\n part notAView;\n}\n", + ), + ]) +} + +fn exposed_names(info: &serde_json::Value) -> Vec<&str> { + info["exposed"] + .as_array() + .unwrap() + .iter() + .map(|e| e["qualifiedName"].as_str().unwrap()) + .collect() +} + +#[test] +fn view_info_reports_exposure_rendering_and_metadata() { + let mut s = matrix_view_session(); + let before = s.to_compact_json(); + let info: serde_json::Value = + serde_json::from_str(&s.view_info("S::'Part allocations'").unwrap()).unwrap(); + assert_eq!(info["qualifiedName"], "S::'Part allocations'"); + assert_eq!(info["rendering"], "asRelationshipMatrix"); + assert_eq!(exposed_names(&info), ["M::a", "M::b"]); + assert_eq!(info["exposed"][0]["metaclass"], "PartUsage"); + assert!(info["exposed"][0]["id"].as_str().unwrap().len() == 36); + assert_eq!(info["views"][0]["name"], "columns"); + assert_eq!( + info["views"][0]["qualifiedName"], + "S::'Part allocations'::columns" + ); + assert_eq!(info["metadata"][0]["type"], "MatrixViews::MatrixConfig"); + assert_eq!(info["metadata"][0]["values"]["relationship"], "allocation"); + // The recursive expose names its target and everything under it. + let columns: serde_json::Value = + serde_json::from_str(&s.view_info("S::'Part allocations'::columns").unwrap()).unwrap(); + assert_eq!(exposed_names(&columns), ["M::c", "M::c::d"]); + assert_eq!(columns["rendering"], serde_json::Value::Null); + assert!(columns["views"].as_array().unwrap().is_empty()); + let masses: serde_json::Value = + serde_json::from_str(&s.view_info("S::masses").unwrap()).unwrap(); + // The standard rendering is a library element: found by its spelling. + assert_eq!(masses["rendering"], "asElementTable"); + // The reported name is the model's canonical spelling, whatever the + // caller quoted. + assert_eq!(masses["qualifiedName"], "S::masses"); + let quoted: serde_json::Value = + serde_json::from_str(&s.view_info("S::'masses'").unwrap()).unwrap(); + assert_eq!(quoted["qualifiedName"], "S::masses"); + assert_eq!(quoted["id"], masses["id"]); + assert_eq!( + masses["metadata"][0]["values"]["attributes"], + serde_json::json!(["mass", "voltage"]) + ); + assert_eq!( + exposed_names(&masses), + ["M::A", "M::B", "M::a", "M::b", "M::c"] + ); + assert!(s.view_info("S::notAView").is_err()); + assert!(s.view_info("S::missing").is_err()); + assert_eq!(s.to_compact_json(), before, "reading a view writes nothing"); +} + +#[test] +fn view_directed_diagrams_show_the_exposure() { + let mut s = matrix_view_session(); + let graph: serde_json::Value = serde_json::from_str( + &s.to_graph(Some( + r#"{"view": "tree", "element": "S::'Part allocations'"}"#.into(), + )) + .unwrap(), + ) + .unwrap(); + let names: Vec<&str> = graph["nodes"] + .as_array() + .unwrap() + .iter() + .filter_map(|n| n["qname"].as_str()) + .collect(); + assert!( + names.contains(&"M::a") && names.contains(&"M::b"), + "{names:?}" + ); + assert!(!names.iter().any(|n| n.starts_with("S::")), "{names:?}"); + assert!(!names.contains(&"M::c"), "{names:?}"); + // A non-view element still scopes the diagram to its own subtree. + let graph: serde_json::Value = serde_json::from_str( + &s.to_graph(Some(r#"{"view": "tree", "element": "M::c"}"#.into())) + .unwrap(), + ) + .unwrap(); + let names: Vec<&str> = graph["nodes"] + .as_array() + .unwrap() + .iter() + .filter_map(|n| n["qname"].as_str()) + .collect(); + assert!( + names.contains(&"M::c") && names.contains(&"M::c::d"), + "{names:?}" + ); + let uml = s + .to_plantuml(Some(r#"{"element": "S::'Part allocations'"}"#.into())) + .unwrap(); + assert!(uml.starts_with("@startuml")); + assert!(!uml.contains("Part allocations"), "{uml}"); + // A view exposing nothing draws nothing — never the whole model. + let graph: serde_json::Value = serde_json::from_str( + &s.to_graph(Some(r#"{"view": "tree", "element": "S::nobody"}"#.into())) + .unwrap(), + ) + .unwrap(); + assert!(graph["nodes"].as_array().unwrap().is_empty(), "{graph}"); + let uml = s + .to_plantuml(Some(r#"{"element": "S::nobody"}"#.into())) + .unwrap(); + assert!(!uml.contains("M::a") && !uml.contains("\"a\""), "{uml}"); +} + +/// A reserved word used as a name: `qualifiedName` keeps the +/// specification's bare spelling, `referenceSpelling` and +/// `spellReference` quote it, and only the quoted form parses when a +/// host splices it into an `expose`. +#[test] +fn reference_spelling_re_parses_in_an_expose() { + const MODEL: &str = + "package 'part' {\n part def 'action';\n part 'view' : 'action';\n}\n"; + let mut s = Session::from_sources(&sources(&[("m.sysml", MODEL)])).unwrap(); + let view = s.resolve("'part'::'view'").expect("quoted lookup"); + assert_eq!( + s.qualified_name(&view).unwrap().as_deref(), + Some("part::view") + ); + assert_eq!( + s.reference_spelling(&view).unwrap().as_deref(), + Some("'part'::'view'") + ); + assert_eq!( + spell_reference_js("part::view", None).unwrap(), + "'part'::'view'" + ); + // The dialect selects the reserved set: neither word is KerML's. + assert_eq!( + spell_reference_js("part::view", Some("kerml".into())).unwrap(), + "part::view" + ); + assert_eq!( + spell_reference_js("'My Views'::x", None).unwrap(), + "'My Views'::x" + ); + assert!( + spell_reference_js("x", Some("cobol".into())) + .unwrap_err() + .contains("dialect") + ); + let expose = |target: &str| -> serde_json::Value { + let views = + format!("package Views {{\n view v {{\n expose {target};\n }}\n}}\n"); + let out = check( + &sources(&[("m.sysml", MODEL), ("v.sysml", &views)]), + None, + None, + ) + .unwrap(); + serde_json::from_str(&out).unwrap() + }; + assert_eq!(expose("'part'::'view'"), serde_json::json!([])); + let bare = expose("part::view"); + assert_eq!(bare[0]["severity"], "error", "{bare}"); + assert_eq!( + bare[0]["stage"], "parse", + "the bare form fails to parse: {bare}" + ); +} + +#[test] +fn derived_properties_by_specification_name() { + let mut s = Session::from_sources(&sources(&[("flashlight.sysml", FLASHLIGHT)])).unwrap(); + let flashlight = s.resolve("Flashlight::flashlight").unwrap(); + // A composition: element handles, and `{"@id"}` references as JSON. + let features = s.derived_elements(&flashlight, "ownedFeature").unwrap(); + assert_eq!(features.len(), 2); + let json: serde_json::Value = + serde_json::from_str(&s.derived(&flashlight, "ownedFeature").unwrap()).unwrap(); + assert_eq!(json.as_array().unwrap().len(), 2); + assert_eq!( + json[0]["@id"].as_str(), + Some(s.element_id(&features[0]).unwrap().as_str()) + ); + // A string and a null. + assert_eq!(s.derived(&flashlight, "name").unwrap(), "\"flashlight\""); + assert_eq!(s.derived(&flashlight, "shortName").unwrap(), "null"); + assert!(s.derived_elements(&flashlight, "name").unwrap().is_empty()); + // A reference-typed property: the typing's target as a handle and as JSON. + let battery = s.resolve("Flashlight::flashlight::battery").unwrap(); + let types = s.derived_elements(&battery, "type").unwrap(); + assert_eq!(types.len(), 1); + assert_eq!( + s.qualified_name(&types[0]).unwrap().as_deref(), + Some("Flashlight::Battery") + ); + // Fidelity and the owned side, without a model. + assert_eq!(Session::derives("PartUsage", "ownedFeature"), "exact"); + assert_eq!(Session::derives("PartUsage", "feature"), "passthrough"); + assert_eq!(Session::derives("PartUsage", "mayTimeVary"), "not-computed"); + assert_eq!( + Session::derives("PartUsage", "declaredName"), + "not-declared" + ); + assert!(Session::is_owned_property("PartUsage", "declaredName")); + assert!( + Session::computed_names() + .iter() + .any(|n| n == "owningNamespace") + ); + // A name the metaclass does not derive throws. + assert!(s.derived(&flashlight, "declaredName").is_err()); + // A name the toolkit does not compute yet throws too. + assert!(s.derived(&battery, "mayTimeVary").is_err()); + // A target outside the model: in the JSON, not among the handles. + let mut s = Session::from_sources(&sources(&[( + "m.sysml", + "package P { part w : Missing; part def A { part x; } part def B :> A; }", + )])) + .unwrap(); + let w = s.resolve("P::w").unwrap(); + let json: serde_json::Value = serde_json::from_str(&s.derived(&w, "type").unwrap()).unwrap(); + assert_eq!(json[0]["outside"], true); + assert_eq!(json[0]["spelling"], "Missing"); + assert!(json[0]["danglingId"].is_string()); + assert!(s.derived_elements(&w, "type").unwrap().is_empty()); + // The closure policy switches the inheritance-aware families, and + // survives an edit of the session. + let b = s.resolve("P::B").unwrap(); + assert_eq!(s.closure_policy(), "passthrough"); + assert!(s.derived_elements(&b, "feature").unwrap().is_empty()); + s.set_closure_policy("closure").unwrap(); + assert_eq!(s.closure_policy(), "closure"); + assert_eq!(s.derived_elements(&b, "feature").unwrap().len(), 1); + s.edit(r#"[{"op": "moveMember", "target": "P::w", "index": 0}]"#) + .expect("edit commits"); + assert_eq!(s.closure_policy(), "closure"); + let b = s.resolve("P::B").unwrap(); + assert_eq!(s.derived_elements(&b, "feature").unwrap().len(), 1); + assert!(s.set_closure_policy("nonsense").is_err()); + s.set_closure_policy("passthrough").unwrap(); +} + +/// A rename clashing with a sibling's name is dropped from the batch +/// and reported; the rest of the batch (an ancestor-qualified respell +/// included) still commits. +#[test] +fn edit_batch_drops_colliding_renames_and_reports_them() { + let src = "package 'A B' {\n part def X;\n part def x;\n}\npackage Q {\n part def other_def;\n part a : 'A B'::X;\n part b : 'A B'::x;\n}\n"; + let mut s = Session::from_sources(&sources(&[("ab.sysml", src)])).unwrap(); + let result = s + .edit( + &serde_json::json!([ + {"op": "rename", "target": "'A B'", "newName": "AB"}, + {"op": "rename", "target": "'A B'::x", "newName": "X"}, + {"op": "rename", "target": "Q::other_def", "newName": "OtherDef"}, + ]) + .to_string(), + ) + .expect("the batch commits without the clashing rename"); + let report: serde_json::Value = serde_json::from_str(&result).unwrap(); + let findings = report["findings"].as_array().unwrap(); + assert_eq!(findings.len(), 1, "{findings:?}"); + let f = findings[0].as_str().unwrap(); + assert!(f.contains("rename of `'A B'::x` to `X` skipped"), "{f}"); + assert!(f.contains("`'A B'::X` is already named `X`"), "{f}"); + let post = s.source(0).unwrap(); + assert!(post.contains("package AB {"), "{post}"); + assert!(post.contains("part def x;"), "{post}"); + assert!(post.contains("part a : AB::X;"), "{post}"); + assert!(post.contains("part b : AB::x;"), "{post}"); + assert!(post.contains("part def OtherDef;"), "{post}"); +} + +/// A session opened with its library reports the same check findings +/// as the free `check` over the same sources (minus the parse stage, +/// which `checkSyntax` carries) — one resolution instead of two. +#[test] +fn session_check_matches_free_check() { + use sysmlv2_wasm::check_syntax; + let lib = sources(&[( + "MiniLib.kerml", + "standard library package MiniLib { class Thing; datatype Num; }", + )]); + let user = sources(&[ + ( + "dangling.sysml", + "package Dangling { part def W; part w : Missing; attribute a : W; }", + ), + ( + "ctx.sysml", + "package Ctx { attribute def A { part p : Thing; } }", + ), + ]); + let free: serde_json::Value = + serde_json::from_str(&check(&user, Some(lib.clone()), None).unwrap()).unwrap(); + let mut s = Session::from_sources_with_library(&user, Some(lib), None).unwrap(); + let unresolved_before = s.unresolved_count(); + let session: serde_json::Value = serde_json::from_str(&s.check()).unwrap(); + assert_eq!(session, free, "session findings match the free check"); + let stages: Vec<&str> = free + .as_array() + .unwrap() + .iter() + .map(|f| f["stage"].as_str().unwrap()) + .collect(); + assert!( + stages.contains(&"referential") && stages.contains(&"semantic"), + "{stages:?}" + ); + // The syntax stages alone: a parse-broken unit's findings, no model. + let mixed = sources(&[ + ("bad.sysml", "part def {"), + ( + "ctx.sysml", + "package Ctx { attribute def A { part p : Thing; } }", + ), + ]); + let syntax: serde_json::Value = serde_json::from_str(&check_syntax(&mixed).unwrap()).unwrap(); + let stages: Vec<&str> = syntax + .as_array() + .unwrap() + .iter() + .map(|f| f["stage"].as_str().unwrap()) + .collect(); + assert!( + stages.iter().all(|s| *s == "parse" || *s == "context"), + "{stages:?}" + ); + assert!(stages.contains(&"parse"), "{stages:?}"); + // The session stays usable after checking: navigation and the + // unresolved count read the same model. + assert!(s.resolve("Dangling::w").is_some()); + assert!(unresolved_before >= 1); + assert_eq!( + s.unresolved_count(), + unresolved_before, + "checking drains nothing" + ); + // Without a library the resolution stages are skipped, as in `check`. + let mut bare = Session::from_sources(&user).unwrap(); + let bare: serde_json::Value = serde_json::from_str(&bare.check()).unwrap(); + let free_bare: serde_json::Value = + serde_json::from_str(&check(&user, None, None).unwrap()).unwrap(); + assert_eq!(bare, free_bare); +} + +/// Checking a session must not change what lint reports afterwards +/// (the import-visibility rule reads the resolver's import provenance). +#[test] +fn session_check_leaves_lint_findings_unchanged() { + let lib = sources(&[( + "MiniLib.kerml", + "standard library package MiniLib { class Thing; datatype Num; }", + )]); + let user = sources(&[( + "u.sysml", + "package U { import MiniLib::*; part def W; part w : Thing; attribute n : Num = 3; }", + )]); + let rules = |s: &mut Session| -> Vec { + let v: serde_json::Value = serde_json::from_str(&s.lint(None).unwrap()).unwrap(); + v["findings"] + .as_array() + .unwrap() + .iter() + .map(|f| f["rule"].as_str().unwrap().to_string()) + .collect() + }; + let mut fresh = Session::from_sources_with_library(&user, Some(lib.clone()), None).unwrap(); + let before = rules(&mut fresh); + let mut checked = Session::from_sources_with_library(&user, Some(lib), None).unwrap(); + let _ = checked.check(); + let after = rules(&mut checked); + assert!( + before.iter().any(|r| r == "import-visibility"), + "{before:?}" + ); + assert_eq!(after, before, "lint after check == lint without check"); +} + +#[test] +fn sources_with_an_empty_unit_name_are_refused_at_the_boundary() { + let bad = r#"[{"name": "ok.sysml", "text": "package A;"}, {"name": "", "text": "package B;"}]"#; + let err = Session::from_sources(bad).err().expect("refused"); + assert!(err.contains("source 1 has an empty name"), "{err}"); + assert!(check(bad, None, None).unwrap_err().contains("empty name")); + assert!( + sysmlv2_wasm::check_syntax(bad) + .unwrap_err() + .contains("empty name") + ); + assert!( + sysmlv2_wasm::lenient_sources(bad) + .unwrap_err() + .contains("empty name") + ); + // A library bundle is sources too. + let err = Session::from_sources_with_library( + &sources(&[("u.sysml", "package U;")]), + Some(bad.to_string()), + None, + ) + .err() + .expect("refused"); + assert!(err.contains("empty name"), "{err}"); +} + +#[test] +fn diagram_emitters_share_one_option_vocabulary() { + let mut s = Session::from_sources(&sources(&[ + ("flashlight.sysml", FLASHLIGHT), + ("extra.sysml", "package Extra { part def Case; }"), + ])) + .unwrap(); + // Unknown names are unknown on both paths, with the same message… + let uml = s + .to_plantuml(Some(r#"{"view": "nope"}"#.into())) + .unwrap_err(); + assert!(uml.contains("unknown view: nope"), "{uml}"); + assert_eq!( + s.to_graph(Some(r#"{"view": "nope"}"#.into())).unwrap_err(), + uml + ); + let uml = s + .to_plantuml(Some(r#"{"lineStyle": "curvy"}"#.into())) + .unwrap_err(); + assert!(uml.contains("unknown line style: curvy"), "{uml}"); + assert_eq!( + s.to_graph(Some(r#"{"lineStyle": "curvy"}"#.into())) + .unwrap_err(), + uml + ); + let uml = s + .to_plantuml(Some(r#"{"element": "No::Such"}"#.into())) + .unwrap_err(); + assert!(uml.contains("element not found: No::Such"), "{uml}"); + assert_eq!( + s.to_graph(Some(r#"{"element": "No::Such"}"#.into())) + .unwrap_err(), + uml + ); + let uml = s + .to_plantuml(Some(r#"{"roots": ["No::Such"]}"#.into())) + .unwrap_err(); + assert_eq!( + s.to_graph(Some(r#"{"roots": ["No::Such"]}"#.into())) + .unwrap_err(), + uml + ); + // …while a view the graph emitter lacks is a different refusal, + // named canonically whatever alias the caller wrote. + let err = s.to_graph(Some(r#"{"view": "seq"}"#.into())).unwrap_err(); + assert_eq!(err, "no structured-graph emitter for view: sequence"); + assert!(s.to_plantuml(Some(r#"{"view": "seq"}"#.into())).is_ok()); + // Every PlantUML option is accepted on the graph path, aliases included. + let g: serde_json::Value = serde_json::from_str( + &s.to_graph(Some( + r#"{"view": "ic", "horizontal": true, "lineStyle": "ortho", "stdColor": true, + "linkTemplate": "x://{file}:{line}", "showInherited": true, "roots": ["Extra"]}"# + .into(), + )) + .unwrap(), + ) + .unwrap(); + assert_eq!(g["view"], "interconnection"); + // `roots` scopes the graph exactly as it scopes the PlantUML. + let g: serde_json::Value = + serde_json::from_str(&s.to_graph(Some(r#"{"roots": ["Extra"]}"#.into())).unwrap()).unwrap(); + let labels: Vec<&str> = g["nodes"] + .as_array() + .unwrap() + .iter() + .filter_map(|n| n["label"].as_str()) + .collect(); + assert!( + labels.contains(&"Case") && !labels.contains(&"Battery"), + "{labels:?}" + ); + let uml = s + .to_plantuml(Some(r#"{"roots": ["Extra"]}"#.into())) + .unwrap(); + assert!(uml.contains("Case") && !uml.contains("Battery"), "{uml}"); +} + +#[test] +fn verify_positions_bindings_in_their_own_unit() { + // The bound feature is declared in one unit and the constraints + // that reference it in another: every position comes from its own + // unit's line index, and one report shares the indexes. + let defs = "package P {\n attribute def Real;\n\n attribute margin : Real = 1;\n}\n"; + let checks = "package Q {\n private import P::*;\n assert constraint short { margin >= 2 }\n assert constraint wide { margin <= 2 }\n}\n"; + let mut s = + Session::from_sources(&sources(&[("defs.sysml", defs), ("checks.sysml", checks)])).unwrap(); + let report: serde_json::Value = serde_json::from_str(&s.verify(None).unwrap()).unwrap(); + let constraints = report["constraints"].as_array().unwrap(); + assert_eq!(constraints.len(), 2); + let short = constraints.iter().find(|c| c["name"] == "short").unwrap(); + assert_eq!(short["unitName"], "checks.sysml"); + assert_eq!(short["line"], 3); + assert_eq!(short["status"], "violated"); + assert_eq!(short["detail"], "VIOLATED (with margin = 1)"); + let b = &short["bindings"].as_array().unwrap()[0]; + assert_eq!(b["feature"], "margin"); + assert_eq!(b["value"], "1"); + assert_eq!(b["unitName"], "defs.sysml"); + assert_eq!(b["line"], 4); + let wide = constraints.iter().find(|c| c["name"] == "wide").unwrap(); + assert_eq!(wide["status"], "satisfied"); + assert_eq!(wide["unitName"], "checks.sysml"); + assert_eq!(wide["line"], 4); + assert_eq!(report["summary"]["satisfied"], 1); + assert_eq!(report["summary"]["violated"], 1); +} diff --git a/crates/sysmlv2-wasm/tests/prepared_library.rs b/crates/sysmlv2-wasm/tests/prepared_library.rs new file mode 100644 index 0000000..968b072 --- /dev/null +++ b/crates/sysmlv2-wasm/tests/prepared_library.rs @@ -0,0 +1,178 @@ +//! Shared libraries preserve the source-library API's graph and edit behavior. +use sysmlv2_wasm::{PreparedLibrary, Session}; + +fn sources(units: &[(&str, &str)]) -> String { + serde_json::to_string( + &units + .iter() + .map(|(name, text)| serde_json::json!({"name":name,"text":text})) + .collect::>(), + ) + .unwrap() +} +fn parity(lib: &[(&str, &str)], users: &[(&str, &str)], snapshot: Option>) { + let library = sources(lib); + let users = sources(users); + let prepared = PreparedLibrary::new(&library, snapshot.clone()).unwrap(); + let mut cold = Session::from_sources_with_library(&users, Some(library), snapshot).unwrap(); + let mut warm = Session::from_sources_with_prepared_library(&users, &prepared).unwrap(); + for policy in ["passthrough", "closure", "closure-implied"] { + cold.set_closure_policy(policy).unwrap(); + warm.set_closure_policy(policy).unwrap(); + assert_eq!(cold.to_compact_json(), warm.to_compact_json()); + assert_eq!(cold.to_full_json(true), warm.to_full_json(true)); + assert_eq!(cold.check(), warm.check()); + assert_eq!(cold.units(), warm.units()); + for kind in ["Feature", "Class", "PartUsage"] { + let a = cold.elements_of_metaclass(kind); + let b = warm.elements_of_metaclass(kind); + assert_eq!(a.len(), b.len()); + for (a, b) in a.iter().zip(&b) { + for name in ["name", "qualifiedName", "type", "inheritedMembership"] { + assert_eq!(cold.derived(a, name), warm.derived(b, name)); + } + } + } + } +} + +#[test] +fn shared_library_preserves_graphs_diagnostics_closures_and_fallbacks() { + let lib = [( + "lib.KerML", + "package L { class A { feature x; } class B :> A { feature :>> x; } alias C for B; }", + )]; + for user in [ + "package U { private import L::*; feature a : C; feature x chains a.x; }", + "package U { private import L::*[true]; feature a : B; feature b : A; binding a.x = b.x; }", + "package L { class A; } package U { feature a : L::A; }", + "package U { feature x : Missing; }", + ] { + parity(&lib, &[("user.kerml", user)], None); + } + parity( + &[("lib.kerml", "package L { class A :> Later; }")], + &[( + "user.kerml", + "class Later { feature x; } package U { feature a : L::A; feature y chains a.x; }", + )], + None, + ); + parity( + &[( + "lib.kerml", + "package Other { class X { feature x; } } package L { class A :> X; }", + )], + &[( + "user.kerml", + "private import Other::*; package U { feature a : L::A; feature x chains a.x; }", + )], + None, + ); + parity( + &[("lib.kerml", "package L { feature f :> x; }")], + &[("user.kerml", "feature : L::f; feature x;")], + None, + ); + parity( + &[], + &[("user.sysml", "package U { part def A; part a : A; }")], + None, + ); + parity( + &[ + ("lib.KerML", "package L { class A; }"), + ("extra.sysml", "package Extra { part def B :> L::A; }"), + ], + &[("user.sysml", "package U { part b : Extra::B; }")], + None, + ); +} + +#[test] +fn prepared_sources_reject_stale_corrupt_and_truncated_recordings() { + let lib = [("lib.kerml", "package L { class A; class B :> A; }")]; + let mut model = sysmlv2_model::model::Model::new(); + for (name, text) in lib { + model.add_library_source(name, text); + } + model.record_library_cache(); + let _ = sysmlv2_model::json::ResolvedModel::build(&model); + let bytes = model.take_recorded_library_cache().unwrap().to_bytes(); + let user = [("user.sysml", "package U { part a : L::B; }")]; + let mut corrupt = bytes.clone(); + *corrupt.last_mut().unwrap() ^= 1; + for snapshot in [ + bytes.clone(), + bytes[..bytes.len() - 1].to_vec(), + corrupt, + vec![1, 2, 3], + ] { + parity(&lib, &user, Some(snapshot)); + } + parity( + &[( + "lib.kerml", + "package L { class A; class B { feature added; } }", + )], + &user, + Some(bytes.clone()), + ); + parity( + &[ + lib[0], + ("extra.sysml", "package Extra { part def C :> L::B; }"), + ], + &user, + Some(bytes), + ); +} + +#[test] +fn sessions_retain_shared_library_and_isolate_edits() { + let text = "package L { part def A; attribute value = 3; }"; + let library = PreparedLibrary::new(&sources(&[("lib.sysml", text)]), None).unwrap(); + let user = sources(&[( + "user.sysml", + "package U { part a : L::A; attribute n = L::value + 1; }", + )]); + let mut first = Session::from_sources_with_prepared_library(&user, &library).unwrap(); + let mut second = Session::from_sources_with_prepared_library(&user, &library).unwrap(); + let original = second.to_compact_json(); + drop(library); + assert_eq!(first.query("U::n").unwrap(), "4"); + first.set_closure_policy("closure").unwrap(); + first + .edit(r#"[{"op":"rename","target":"U::a","newName":"renamed"}]"#) + .unwrap(); + assert!(first.resolve("U::renamed").is_some()); + assert_eq!(first.closure_policy(), "closure"); + assert_eq!(second.to_compact_json(), original); + assert!(second.resolve("U::a").is_some()); + assert_eq!(second.query("U::n").unwrap(), "4"); +} + +#[test] +fn prepared_library_supports_interchange_and_attachment() { + let lib = sources(&[("lib.sysml", "package L { part def A; }")]); + let prepared = PreparedLibrary::new(&lib, None).unwrap(); + let user = sources(&[("user.sysml", "package U { part a : L::A; }")]); + let original = Session::from_sources_with_prepared_library(&user, &prepared).unwrap(); + let json = original.to_compact_json(); + let bytes = original.to_compact_cbor(); + let mut old_json = + Session::from_interchange_json(&json, Some(lib.clone()), None, None).unwrap(); + let mut new_json = + Session::from_interchange_json_with_prepared_library(&json, &prepared, None).unwrap(); + assert_eq!(old_json.to_compact_json(), new_json.to_compact_json()); + assert_eq!(old_json.check(), new_json.check()); + let old_cbor = Session::from_compact_cbor(&bytes, Some(lib), None, None).unwrap(); + let new_cbor = + Session::from_compact_cbor_with_prepared_library(&bytes, &prepared, None).unwrap(); + assert_eq!(old_cbor.to_compact_json(), new_cbor.to_compact_json()); + let mut attached = Session::from_sources(&user).unwrap(); + let stale = attached.resolve("U::a").unwrap(); + attached.load_prepared_library(&prepared).unwrap(); + assert!(attached.metaclass(&stale).is_err()); + assert_eq!(attached.to_compact_json(), original.to_compact_json()); +} diff --git a/crates/sysmlv2-wasm/tests/stack.rs b/crates/sysmlv2-wasm/tests/stack.rs new file mode 100644 index 0000000..facdd36 --- /dev/null +++ b/crates/sysmlv2-wasm/tests/stack.rs @@ -0,0 +1,214 @@ +//! The module's reserved stack against the depths the toolkit's recursive +//! passes bound themselves to. +//! +//! On the wasm target a bound the stack cannot hold is not a diagnostic +//! but a trap, so the reservation and the bounds have to agree. These +//! tests hold the reservation to the build that applies it, and run the +//! bounds within it. +//! +//! What no test here can do is observe the reservation a wasm link +//! actually applies: that needs the module built for the wasm target and +//! its stack pointer read out of the linked binary, and these tests run +//! on the host. The probes below therefore run the bounds inside a *host* +//! thread the size of the reservation — they answer "is this size enough +//! for the bounds", not "did the module get this size". The second +//! question is held by [`the_build_reserves_the_declared_stack`], which +//! pins that the build reads the size from the crate and passes it to the +//! linker for both artifacts; if that wiring is removed, the size the +//! probes work against is no longer the size the module gets. + +use sysmlv2_model::lift::MAX_LIFT_DEPTH; +use sysmlv2_syntax::parser::{MAX_NESTING, MAX_NESTING_STACK_BYTES, parse_source}; +use sysmlv2_wasm::WASM_STACK_BYTES; + +/// The linker's own default, which the reservation exists to replace. +const LINKER_DEFAULT_STACK_BYTES: usize = 1 << 20; + +/// The build applies the reservation the crate declares, reading it from +/// the crate rather than repeating it. +/// +/// This is the one test here that pins the reservation reaching a built +/// module; it does so through the build's wiring rather than by reading a +/// module, because building one is not something a unit test does. +#[test] +fn the_build_reserves_the_declared_stack() { + // A reservation at or below the linker's own default asks for + // nothing, and the flag below would be decoration. + const { + assert!(WASM_STACK_BYTES > LINKER_DEFAULT_STACK_BYTES); + } + let build = include_str!("../npm/build.mjs"); + assert!( + build.contains("WASM_STACK_BYTES: usize = (\\d+);"), + "the build script no longer reads the size from the crate" + ); + assert!( + build.contains("-C link-arg=-zstack-size=${stackSizeBytes}"), + "the build script no longer passes the size to the linker" + ); + assert_eq!( + build + .matches("-C link-arg=-zstack-size=${stackSizeBytes}") + .count(), + 2, + "both wasm artifacts — the module and the command-line binary — reserve it" + ); +} + +/// One level of the *lift* costs about twenty times as much unoptimized +/// as optimized, and its bound is reachable in single megabytes only +/// when optimized. The shipped module is always optimized, so an +/// unoptimized probe of that bound is given that much more room — which +/// means the unoptimized run of [`the_reserved_stack_holds_the_lift_bound`] +/// is not a gate on the reservation: it checks that the bound is +/// reachable at all, and the optimized run is what holds the size. +/// +/// The parser's bound needs no such allowance: its probe runs at the +/// reservation itself in either build (see +/// [`the_reserved_stack_holds_the_parser_bound`]). +const LIFT_PROFILE_FACTOR: usize = if cfg!(debug_assertions) { 20 } else { 1 }; + +/// Input past the parser's bound stops at it with a diagnostic, and +/// input up to it parses, both within a stack the size of the +/// reservation — in either build, so an unoptimized run gates the +/// reservation as much as an optimized one does. A host thread stands in +/// for the module's stack — see the note at the top of this file for what +/// that does and does not pin. +/// +/// Two shapes reach the bound: bodies nested to it, and nesting that also +/// carries an operator chain at every level. The first is the more +/// expensive of the two, and the second is the one a written model gets +/// near. +#[test] +fn the_reserved_stack_holds_the_parser_bound() { + // The reservation covers what the parser's own bound asks for. + const { + assert!(WASM_STACK_BYTES >= MAX_NESTING_STACK_BYTES); + } + std::thread::Builder::new() + .stack_size(WASM_STACK_BYTES) + .spawn(|| { + let levels = MAX_NESTING as usize; + let src = format!( + "package P {{ {}{} }}", + "part x { ".repeat(levels - 1), + "}".repeat(levels - 1) + ); + let parse = parse_source(&src); + assert!( + parse.diagnostics.is_empty(), + "{levels} levels should parse: {:#?}", + parse.diagnostics + ); + + let chain = (0..960) + .map(|i| format!("a{i} > 0")) + .collect::>() + .join(" and "); + let src = format!( + "package P {{ {}part y;{} }}", + format!("part x {{ attribute v = {chain}; ").repeat(60), + "}".repeat(60) + ); + let parse = parse_source(&src); + assert!( + parse.diagnostics.is_empty(), + "nesting carrying a full chain per level should parse: {:#?}", + parse.diagnostics + ); + + let src = format!( + "package P {{ {}{} }}", + "part x { ".repeat(10_000), + "}".repeat(10_000) + ); + let parse = parse_source(&src); + assert!( + parse + .diagnostics + .iter() + .any(|d| d.message.contains("nesting is too deep")), + "expected the bound to be reported, got {:?}", + parse.diagnostics.first().map(|d| d.message.clone()) + ); + }) + .unwrap() + .join() + .unwrap(); +} + +/// The lift's bound is reached within a stack the size of the +/// reservation too. On this host the lift moves a payload that could nest +/// deeply onto a stack of its own; the wasm target has no threads and +/// lifts in place, which is what the reservation is for, so the probe +/// runs the whole lift inside it — again on a host thread, see the note +/// at the top of this file. +/// +/// Only the optimized run gates the reservation here: an unoptimized +/// step costs about twenty times as much, so the probe is given that +/// much more room and could not detect an undersized reservation. See +/// [`LIFT_PROFILE_FACTOR`]. +#[test] +fn the_reserved_stack_holds_the_lift_bound() { + std::thread::Builder::new() + .stack_size(WASM_STACK_BYTES * LIFT_PROFILE_FACTOR) + .spawn(|| { + let depth = MAX_LIFT_DEPTH * 2; + let mut elements = Vec::new(); + for i in 0..depth { + // Ownership is spelled both ways round, as a payload + // spells it: the chain then has the one root it reads as. + let mut membership = serde_json::json!({ + "@id": format!("m{i}"), + "@type": "OwningMembership", + "ownedRelatedElement": [{ "@id": format!("p{i}") }], + }); + if i > 0 { + membership["owningRelatedElement"] = + serde_json::json!({ "@id": format!("p{}", i - 1) }); + } + elements.push(membership); + let owned = if i + 1 < depth { + serde_json::json!([{ "@id": format!("m{}", i + 1) }]) + } else { + serde_json::json!([]) + }; + elements.push(serde_json::json!({ + "@id": format!("p{i}"), + "@type": "PartUsage", + "declaredName": format!("p{i}"), + "owningRelationship": { "@id": format!("m{i}") }, + "ownedRelationship": owned, + })); + } + let Err(sysmlv2_model::lift::LiftError::Incomplete { errors }) = + sysmlv2_model::lift::from_compact_json_on_this_stack( + &serde_json::Value::Array(elements), + &std::collections::HashMap::new(), + ) + else { + panic!("an over-budget document must not return a partial AST") + }; + assert!( + errors + .iter() + .any(|e| e.contains("ownership nesting deeper than")), + "expected the bound to be reported, got {:?}", + errors + ); + // One report for the truncated subtree, not one per element + // past the bound. + assert_eq!( + errors + .iter() + .filter(|e| e.contains("ownership nesting deeper than")) + .count(), + 1, + "{:?}", + errors + ); + }) + .unwrap() + .join() + .unwrap(); +} diff --git a/editors/vscode/README.md b/editors/vscode/README.md index 16a0f41..c6ad2b1 100644 --- a/editors/vscode/README.md +++ b/editors/vscode/README.md @@ -3,7 +3,8 @@ Language support for the OMG SysML v2 and KerML textual notations, powered by the `sysmlv2` language server (`sysmlv2 lsp`). - **Exact, dialect-aware highlighting** via semantic tokens. Keywords in this language are contextual — `part` is a keyword in SysML and a legal name in KerML — so no TextMate grammar can classify them; the parser does, and this extension renders its verdict. The bundled TextMate grammar is a deliberately coarse fallback (notes, doc comments, strings, numbers) shown only until the server answers. -- **Live diagnostics** on every keystroke: parse errors with recovery (the file keeps working while broken) plus body-context validation. +- **Live diagnostics**: parse errors with recovery and body-context validation; a configured standard library enables semantic diagnostics. +- **Navigation and editing**: go to definition, references, completion, hover, rename, inlay hints, code lenses, and refactoring actions from the language server. Semantic features require library context. - **Outline / breadcrumbs / sticky scroll** from the document symbol tree, including anonymous members (`«part»`) and `: Type [mult]` details. - **Formatting** via the toolkit's idempotent, note-preserving formatter. @@ -19,6 +20,8 @@ Language support for the OMG SysML v2 and KerML textual notations, powered by th code --install-extension sysmlv2-*.vsix ``` +To enable semantic features, start VS Code from an environment with `SYSMLV2_LIB_DIR` set to an initialized `sysml.library` directory. The extension launches `sysmlv2 lsp` and inherits that environment; `sysmlv2.serverPath` controls only the executable. Other clients can pass `--lib /path/to/sysml.library` directly. + ## Other editors The server is plain LSP over stdio; any client works. diff --git a/editors/vscode/package.json b/editors/vscode/package.json index cc71445..8840cae 100644 --- a/editors/vscode/package.json +++ b/editors/vscode/package.json @@ -16,7 +16,7 @@ "url": "https://github.com/Open-MBEE/sysml-toolkit/issues" }, "engines": { - "vscode": "^1.85.0" + "vscode": "^1.91.0" }, "categories": [ "Programming Languages", @@ -73,7 +73,7 @@ } }, "dependencies": { - "vscode-languageclient": "^9.0.1" + "vscode-languageclient": "^10.1.1" }, "scripts": { "package": "vsce package" diff --git a/local-packages/README.md b/local-packages/README.md index 91c3bda..1b158e7 100644 --- a/local-packages/README.md +++ b/local-packages/README.md @@ -13,37 +13,17 @@ Every `.sysml` file here is a library the toolkit carries **ambiently**: `sysmlv Never edit the generated files: regenerate them. -## Reproducing the libraries +## Using and validating the libraries -The generator is the separate `websysml` repository (not yet published). It expects this toolkit checked out as a sibling directory named `sysmlv2` (or `SYSMLV2_ROOT` pointing at it) and writes into this directory. +The generated sources and provenance sidecars are included in this repository. No generator is needed to use them. Dataset revisions and per-element origins are recorded in the file headers and sidecars; do not edit generated sources by hand. The generation tool is not distributed with this repository. -Prerequisites: Node 22.3 or newer, the Rust toolchain with the `wasm32-unknown-unknown` target, and `wasm-pack` (the wasm crate's `npm/` folder installs one). +With the standard-library submodule initialized, validate the checked-in sources locally: -```bash -# 1. In this repository: the kernel the generator validates through — -# the nodejs wasm build and the standard-library bundle (once, and -# after toolkit changes). -node crates/sysmlv2-wasm/npm/build.mjs - -# 2. In the websysml checkout: the generator's pinned inputs (corpus -# packages, compiler, parser), then regenerate every library and -# sidecar into this directory. The generator refuses to write -# anything that is not strict-check-clean against the standard -# library or not formatter-idempotent. -npm ci -npm run generate - -# 3. Verify, as CI does: outputs current, tests green (in websysml) … -node src/cli.mjs generate --check -npm test - -# … and the CLI gates (in this repository). +```sh SYSMLV2_AMBIENT=off cargo run --release -p sysmlv2-cli -- check --strict --lib spec-refs/SysML-v2-Release/sysml.library local-packages/Web.sysml local-packages/Template.sysml local-packages/Svelte.sysml local-packages/WebApp.sysml local-packages/SvelteKit.sysml cargo run --release -p sysmlv2-cli -- fmt --check local-packages/Web.sysml local-packages/Template.sysml local-packages/Svelte.sysml local-packages/WebApp.sysml local-packages/SvelteKit.sysml ``` -`SYSMLV2_AMBIENT=off` keeps the toolkit's built-in copies out of a check, so a regenerated file can be validated as a candidate (and so `sysmlv2` can run against a bare standard library when wanted). The generator's own tests do the same through a core-only kernel bundle. - -To take a newer corpus or compiler, bump the exact version in the generator's `package.json`, run `npm install` there, regenerate, and review the diff: the goldens in the generator's `test/` directory and the sidecars make every change visible. The library headers name the dataset revisions they were generated from. +Both commands pass clean. Two earlier candidate-validation failures are closed — the `Base::Anything` attribute typings, and an operation repeating a name inherited through a mixin, which the generator now leaves to the inherited declaration and records in the sidecar's omission ledger. Do not suppress a check or patch generated files by hand: correct the generator, then regenerate sources and provenance together. Library-mode loading suppresses library diagnostics, so ordinary consumers never see a candidate-validation failure. -The generator's README documents the pipeline, scope, options, and the document/template import commands. +`SYSMLV2_AMBIENT=off` keeps the toolkit’s built-in copies out of a check, so these files are validated as candidates. It also allows analysis against a bare standard library. diff --git a/local-packages/Svelte.provenance.json b/local-packages/Svelte.provenance.json index eb23d3d..750fc46 100644 --- a/local-packages/Svelte.provenance.json +++ b/local-packages/Svelte.provenance.json @@ -1,12 +1,12 @@ { "generator": { "name": "@sysml/web", - "version": "0.5.5-rc.1" + "version": "0.8.0" }, "dataset": { "svelte (declarations)": "5.57.0" }, - "kernel": "0.5.5-rc.1", + "kernel": "0.8.0", "library": "Svelte", "elements": { "Svelte::Svelte::AnimateDirective": { diff --git a/local-packages/SvelteKit.provenance.json b/local-packages/SvelteKit.provenance.json index 06860b8..4c39d1e 100644 --- a/local-packages/SvelteKit.provenance.json +++ b/local-packages/SvelteKit.provenance.json @@ -1,10 +1,10 @@ { "generator": { "name": "@sysml/web", - "version": "0.5.5-rc.1" + "version": "0.8.0" }, "dataset": {}, - "kernel": "0.5.5-rc.1", + "kernel": "0.8.0", "library": "SvelteKit", "elements": { "SvelteKit::SvelteKit::BoundaryViolation": { diff --git a/local-packages/Template.provenance.json b/local-packages/Template.provenance.json index 9ade188..18c502b 100644 --- a/local-packages/Template.provenance.json +++ b/local-packages/Template.provenance.json @@ -1,12 +1,12 @@ { "generator": { "name": "@sysml/web", - "version": "0.5.5-rc.1" + "version": "0.8.0" }, "dataset": { "svelte (declarations)": "5.57.0" }, - "kernel": "0.5.5-rc.1", + "kernel": "0.8.0", "library": "Template", "elements": { "Template::Template::Attribute": { diff --git a/local-packages/Web.provenance.json b/local-packages/Web.provenance.json index 10452c9..e6e32c8 100644 --- a/local-packages/Web.provenance.json +++ b/local-packages/Web.provenance.json @@ -1,13 +1,13 @@ { "generator": { "name": "@sysml/web", - "version": "0.5.5-rc.1" + "version": "0.8.0" }, "dataset": { "@webref/idl": "3.83.0", "@webref/elements": "2.8.0" }, - "kernel": "0.5.5-rc.1", + "kernel": "0.8.0", "library": "Web", "elements": { "Web::DOM::AbstractRange": { @@ -14483,22 +14483,6 @@ "wrapper:HTMLOptionsCollection" ] }, - "Web::HTML::HTMLSelectElement::remove": { - "spec": "html", - "interface": "HTMLSelectElement", - "member": "remove", - "url": "https://html.spec.whatwg.org/multipage/#dom-htmlselectelement-remove", - "kind": "operation", - "params": [ - { - "name": "index", - "type": "Integer", - "multiplicity": "[0..1]", - "optional": true - } - ], - "overloads": 2 - }, "Web::HTML::HTMLSelectElement::reportValidity": { "spec": "html", "interface": "HTMLSelectElement", @@ -18227,6 +18211,9 @@ "reason": "record", "idlType": "DOMStringMap" }, + "Web::HTML::HTMLSelectElement::remove": { + "reason": "inherited-member:ChildNode" + }, "Web::HTML::OffscreenCanvas::convertToBlob": { "reason": "external-type:Blob" }, diff --git a/local-packages/Web.sysml b/local-packages/Web.sysml index a429bd7..206ab2d 100644 --- a/local-packages/Web.sysml +++ b/local-packages/Web.sysml @@ -7,7 +7,9 @@ library package Web { readonly -> constant; tree-node references (Node/Attr and their collections) are derived navigation the toolkit constructs from ownership; mixins are abstract definitions with multiple specialization; operations are nested action definitions (in parameters, out result; Promise -> T, recorded async; - overloads merged); callbacks are action definitions; record is an entry attribute definition. + overloads merged; an operation repeating the name of an inherited one is left to the inherited + declaration and recorded in the sidecar); callbacks are action definitions; record is an + entry attribute definition. Element kinds fix localName once and specialize the element's interface. Provenance: the sidecar. */ @@ -430,7 +432,7 @@ library package Web { constant attribute slotAssignment : SlotAssignmentMode; constant attribute clonable : Boolean; derived ref part host : Element; - attribute innerHTML : Base::Anything; + attribute innerHTML : Base::DataValue; action def setHTML { in html : String; in options : HTML::SetHTMLOptions[0..1]; @@ -481,8 +483,8 @@ library package Web { derived ref part shadowRoot : ShadowRoot[0..1]; constant ref part customElementRegistry : HTML::CustomElementRegistry[0..1]; attribute 'part' : String[0..*] ordered; - attribute innerHTML : Base::Anything; - attribute outerHTML : Base::Anything; + attribute innerHTML : Base::DataValue; + attribute outerHTML : Base::DataValue; action def hasAttributes { out result : Boolean; } @@ -1021,7 +1023,7 @@ library package Web { attribute lang : String; attribute translate : Boolean; attribute dir : String; - attribute hidden : Base::Anything[0..1]; + attribute hidden : Base::DataValue[0..1]; attribute inert : Boolean; attribute accessKey : String; constant attribute accessKeyLabel : String; @@ -1217,7 +1219,7 @@ library package Web { part def HTMLIFrameElement :> HTMLElement { attribute src : String; - attribute srcdoc : Base::Anything; + attribute srcdoc : Base::DataValue; attribute name : String; attribute sandbox : String[0..*] ordered; attribute allow : String; @@ -1329,7 +1331,7 @@ library package Web { abstract part def HTMLMediaElement :> HTMLElement { constant ref part error : MediaError[0..1]; attribute src : String; - attribute srcObject : Base::Anything[0..1]; + attribute srcObject : Base::DataValue[0..1]; constant attribute currentSrc : String; attribute crossOrigin : String[0..1]; constant attribute NETWORK_EMPTY : Natural = 0; @@ -1571,9 +1573,6 @@ library package Web { in element : HTMLElement; in before : Base::Anything[0..1]; } - action def remove { - in index : Integer[0..1]; - } action def checkValidity { out result : Boolean; } @@ -1992,7 +1991,7 @@ library package Web { attribute type : String; attribute defaultValue : String; attribute value : String; - attribute valueAsDate : Base::Anything[0..1]; + attribute valueAsDate : Base::DataValue[0..1]; attribute valueAsNumber : Real; attribute width : Natural; constant attribute willValidate : Boolean; @@ -2042,11 +2041,11 @@ library package Web { } attribute def SetHTMLOptions { - attribute sanitizer : Base::Anything[0..1] default = "default"; + attribute sanitizer : Base::DataValue[0..1] default = "default"; } attribute def SetHTMLUnsafeOptions { - attribute sanitizer : Base::Anything[0..1]; + attribute sanitizer : Base::DataValue[0..1]; attribute runScripts : Boolean[0..1] default = false; } diff --git a/local-packages/WebApp.provenance.json b/local-packages/WebApp.provenance.json index ab24625..f628131 100644 --- a/local-packages/WebApp.provenance.json +++ b/local-packages/WebApp.provenance.json @@ -1,10 +1,10 @@ { "generator": { "name": "@sysml/web", - "version": "0.5.5-rc.1" + "version": "0.8.0" }, "dataset": {}, - "kernel": "0.5.5-rc.1", + "kernel": "0.8.0", "library": "WebApp", "elements": { "WebApp::WebApp::Application": { diff --git a/spec-refs/README.md b/spec-refs/README.md index 5079f34..d554b33 100644 --- a/spec-refs/README.md +++ b/spec-refs/README.md @@ -1,16 +1,19 @@ # Specification references and test corpus -Reference material vendored for grammar fidelity and corpus testing. None of it is compiled into the library. +Reference material vendored for grammar fidelity and corpus testing. The reference files are development/test inputs, not runtime dependencies. Checked-in Rust tables are generated from the schemas and XMI; the optional WASM package bundles standard-library sources and a resolution snapshot during its build. + +Current corpus pins: `SysML-v2-Release` at `de1070ae8e79c21532b8004fc663d47b35d0e9fa`, and `apollo-11-sysml-v2` at `6e9c93fe7d80c5ca3534bb14b10ab374a643ef2d`. The official gate covers 94 library units and 251 user files (345 total). See also the [external static-rule fixtures](../crates/sysmlv2-parser/tests/fixtures/opensysml/README.md), whose provenance and contracts are checked in separately. | Path | What | Source | License | |---|---|---|---| -| `KerML.xtext` | Normative KerML structural grammar | [SysML-v2-Pilot-Implementation](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation) `org.omg.kerml.xtext` (master, fetched 2026-07-08; metamodel 20250201) | EPL-2.0 | +| `KerML.xtext` | Normative KerML structural grammar | [SysML-v2-Pilot-Implementation](https://github.com/Systems-Modeling/SysML-v2-Pilot-Implementation) `org.omg.kerml.xtext` (master; metamodel 20250201) | EPL-2.0 | | `KerMLExpressions.xtext` | Normative terminals + expression grammar (shared by both dialects) | same, `org.omg.kerml.expressions.xtext` | EPL-2.0 | | `SysML.xtext` | Normative SysML v2 textual-notation grammar | same, `org.omg.sysml.xtext` | EPL-2.0 | | `SysML.schema.json` | Normative abstract-syntax JSON schema (drives the full-form property catalog + validation gates) | https://www.omg.org/spec/SysML/20250201/SysML.json | OMG spec file | | `KerML.schema.json` | Normative KerML abstract-syntax JSON schema | https://www.omg.org/spec/KerML/20250201/KerML.json | OMG spec file | -| `KerML.xmi` | Normative KerML metamodel XMI — the authoritative owned-vs-derived property split (`isDerived`), defaults, and multiplicities per metaclass (drives the property-audit gate via `tools/xmi_props.py`) | https://www.omg.org/spec/KerML/20250201/KerML.xmi (fetched 2026-07-16) | OMG spec file | -| `SysML.xmi` | Normative SysML v2 metamodel XMI (93 classes generalizing into `KerML.xmi` by href) | https://www.omg.org/spec/SysML/20250201/SysML.xmi (fetched 2026-07-16) | OMG spec file | +| `KerML.xmi` | Normative KerML metamodel XMI — the authoritative owned-vs-derived property split (`isDerived`), defaults, and multiplicities per metaclass (drives the property-audit gate via `tools/xmi_props.py`) | https://www.omg.org/spec/KerML/20250201/KerML.xmi | OMG spec file | +| `SysML.xmi` | Normative SysML v2 metamodel XMI (93 classes generalizing into `KerML.xmi` by href) | https://www.omg.org/spec/SysML/20250201/SysML.xmi | OMG spec file | +| `derived-properties.json`, `derived-properties.md` | Generated census of the metamodel's 279 derived property names (declaring metaclasses, type, multiplicity, OCL rule, computation class, emitter status) — output of `tools/derived_census.py`, regenerate rather than edit | this repository | Apache-2.0 | | `SysML-v2-Release/` | Test corpus: `sysml.library/` (standard + domain + kernel libraries), `sysml/src/{examples,training,validation}` — git submodule; a sparse, blob-filtered checkout of those four directories is enough (`git submodule update --init --filter=blob:none spec-refs/SysML-v2-Release`, then `git -C spec-refs/SysML-v2-Release sparse-checkout set sysml.library sysml/src/examples sysml/src/training sysml/src/validation`) — the corpus gates read only them | [SysML-v2-Release](https://github.com/Systems-Modeling/SysML-v2-Release) | LGPL-3.0 | | `apollo-11-sysml-v2/` | External validation corpus: Airbus Central R&T's Apollo 11 mission model (28 files, five-layer CoSMA framework) — git submodule, the first substantial model independent of the OMG pilot lineage; gates in `tests/apollo.rs` skip when uninitialized | [airbus/apollo-11-sysml-v2](https://github.com/airbus/apollo-11-sysml-v2) | MPL-2.0 | diff --git a/spec-refs/derived-correspondence.json b/spec-refs/derived-correspondence.json new file mode 100644 index 0000000..ebb49c5 --- /dev/null +++ b/spec-refs/derived-correspondence.json @@ -0,0 +1,136567 @@ +{ + "generator": "cargo run --example derived_correspondence", + "note": "key on `fidelity` (not-computed / passthrough / exact), never on corpus fill rate; `fidelityUnderClosure` is the fidelity with ClosurePolicy::Closure in force", + "rows": [ + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "AcceptActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "payloadArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "AcceptActionUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "payloadParameter", + "shape": "required-reference", + "type": "ReferenceUsage" + }, + { + "metaclass": "AcceptActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AcceptActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "receiverArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ActionDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ActorMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedActorParameter", + "shape": "required-reference", + "type": "PartUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ParameterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberParameter", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ActorMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ActorMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AllocationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "allocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionEnd", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "metaclass": "AllocationDefinition", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AllocationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "allocationDefinition", + "shape": "array", + "type": "AllocationDefinition" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionDefinition", + "shape": "array", + "type": "AssociationStructure" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AllocationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AllocationUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AllocationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "CalculationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "calculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AnalysisCaseDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "AnalysisCaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "resultExpression", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnalysisCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "analysisCaseDefinition", + "shape": "nullable", + "type": "AnalysisCaseDefinition" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "caseDefinition", + "shape": "nullable", + "type": "CaseDefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "AnalysisCaseUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "AnalysisCaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "resultExpression", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AnnotatingElement", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AnnotatingElement", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "annotatedElement", + "shape": "required-reference" + }, + { + "declaredOn": "Annotation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "annotatingElement", + "shape": "required-reference", + "type": "AnnotatingElement" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Annotation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedAnnotatingElement", + "shape": "nullable", + "type": "AnnotatingElement" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Annotation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatedElement", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Annotation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingElement", + "shape": "nullable", + "type": "AnnotatingElement" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Annotation", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AssertConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "assertedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isNegated", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "AssertConstraintUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssertConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "AssignmentActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AssignmentActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referent", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AssignmentActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "targetArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "AssignmentActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "valueExpression", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssignmentActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Association", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Association", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Association", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Association", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Association", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Association", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Association", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Association", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Association", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Association", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Association", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Association", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Association", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "metaclass": "Association", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Association", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "metaclass": "AssociationStructure", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AttributeDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AttributeUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "attributeDefinition", + "shape": "array", + "type": "DataType" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "AttributeUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "AttributeUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "AttributeUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "AttributeUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Behavior", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "BindingConnector", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "BindingConnectorAsUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BindingConnectorAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "BooleanExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "BooleanExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "BooleanExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "CalculationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "calculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "CalculationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CalculationDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "CalculationUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CalculationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "CalculationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "calculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "CaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CaseDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "caseDefinition", + "shape": "nullable", + "type": "CaseDefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "CaseUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Class", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Class", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Class", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Class", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Class", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Class", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Class", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Class", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Class", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Class", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Classifier", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "operator", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CollectExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CollectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "body", + "shape": "scalar" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "locale", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Comment", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Comment", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConcernDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ConcernDefinition", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConcernUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "concernDefinition", + "shape": "nullable", + "type": "ConcernDefinition" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ConcernUsage", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "requirementDefinition", + "shape": "nullable", + "type": "RequirementDefinition" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "PortDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "conjugatedPortDefinition", + "shape": "nullable", + "type": "ConjugatedPortDefinition" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ConjugatedPortDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "originalPortDefinition", + "shape": "required-reference", + "type": "PortDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "ConjugatedPortDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedPortConjugator", + "shape": "required-reference", + "type": "PortConjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConjugatedPortDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "conjugatedPortDefinition", + "shape": "required-reference" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "FeatureTyping", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "ConjugatedPortTyping", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "portDefinition", + "shape": "required-reference", + "type": "PortDefinition" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConjugatedPortTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "type", + "shape": "required-reference" + }, + { + "metaclass": "ConjugatedPortTyping", + "owned": true, + "property": "typedFeature", + "shape": "required-reference" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "conjugatedType", + "shape": "required-reference" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "originalType", + "shape": "required-reference" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Conjugation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Conjugation", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Conjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionEnd", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "metaclass": "ConnectionDefinition", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionDefinition", + "shape": "array", + "type": "AssociationStructure" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ConnectionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ConnectionUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConnectionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Connector", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Connector", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConstraintDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConstraintDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ConstraintUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ConstructorExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ConstructorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "crossedFeature", + "shape": "required-reference" + }, + { + "declaredOn": "CrossSubsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "crossingFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Subsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "subsettedFeature", + "shape": "required-reference" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "subsettingFeature", + "shape": "required-reference" + }, + { + "metaclass": "CrossSubsetting", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "CrossSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "DataType", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DataType", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "DecisionNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "DecisionNode", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "DecisionNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Definition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Definition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "client", + "shape": "array" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "supplier", + "shape": "array" + }, + { + "metaclass": "Dependency", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Dependency", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "differencingType", + "shape": "required-reference" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Differencing", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Differencing", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Differencing", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "typeDifferenced", + "shape": "required-reference", + "type": "Type" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "disjoiningType", + "shape": "required-reference" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Disjoining", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Disjoining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Disjoining", + "owned": true, + "property": "typeDisjoined", + "shape": "required-reference" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "body", + "shape": "scalar" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "declaredOn": "Documentation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "documentedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "locale", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Documentation", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "ElementFilterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "condition", + "shape": "required-reference", + "type": "Expression" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ElementFilterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ElementFilterMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "EndFeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EndFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "EndFeatureMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "EnumerationDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "enumeratedValue", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "EnumerationDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AttributeUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "attributeDefinition", + "shape": "array", + "type": "DataType" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "EnumerationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "enumerationDefinition", + "shape": "required-reference", + "type": "EnumerationDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "AttributeUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "EnumerationUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "EnumerationUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "eventOccurrence", + "shape": "required-reference", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "metaclass": "EventOccurrenceUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "EventOccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "doAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "entryAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "eventOccurrence", + "shape": "required-reference", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "ExhibitStateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "exhibitedState", + "shape": "required-reference", + "type": "StateUsage" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "exitAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isParallel", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "PerformActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "performedAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "metaclass": "ExhibitStateUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stateDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ExhibitStateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Expression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Expression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Expression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Feature", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Feature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "operator", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureChainExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureChainExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "targetFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChainExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "chainingFeature", + "shape": "required-reference" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "FeatureChaining", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureChained", + "shape": "required-reference", + "type": "Feature" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FeatureChaining", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "featureInverted", + "shape": "required-reference" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "invertingFeature", + "shape": "required-reference" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "FeatureInverting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FeatureInverting", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureInverting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "FeatureMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureReferenceExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureReferenceExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referent", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureReferenceExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "FeatureTyping", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "type", + "shape": "required-reference" + }, + { + "metaclass": "FeatureTyping", + "owned": true, + "property": "typedFeature", + "shape": "required-reference" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "FeatureValue", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureWithValue", + "shape": "required-reference", + "type": "Feature" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "isDefault", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "isInitial", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "FeatureValue", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FeatureValue", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "value", + "shape": "required-reference", + "type": "Expression" + }, + { + "metaclass": "FeatureValue", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..2", + "ordered": true, + "owned": false, + "property": "flowEnd", + "shape": "array", + "type": "FlowEnd" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "interaction", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "payloadFeature", + "shape": "nullable", + "type": "PayloadFeature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "payloadType", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceOutputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Flow", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "targetInputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Flow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "FlowDefinition", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "flowEnd", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "metaclass": "FlowDefinition", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FlowEnd", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowEnd", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "FlowUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "flowDefinition", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..2", + "ordered": true, + "owned": false, + "property": "flowEnd", + "shape": "array", + "type": "FlowEnd" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "interaction", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "FlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "payloadFeature", + "shape": "nullable", + "type": "PayloadFeature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "payloadType", + "shape": "array", + "type": "Classifier" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceOutputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "FlowUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "targetInputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "LoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "bodyAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ForLoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "loopVariable", + "shape": "required-reference", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ForLoopActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ForLoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "seqArgument", + "shape": "required-reference", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ForkNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ForkNode", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ForkNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "FramedConcernMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "required-reference", + "type": "ConcernUsage" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FramedConcernMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedConcern", + "shape": "required-reference", + "type": "ConcernUsage" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "FramedConcernMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "FramedConcernMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "Function", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Function", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Function", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Function", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Function", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Function", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Function", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Function", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Function", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Function", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Function", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "IfActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "elseAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "IfActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ifArgument", + "shape": "required-reference", + "type": "Expression" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "IfActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "IfActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "thenAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IfActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "caseDefinition", + "shape": "nullable", + "type": "CaseDefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "eventOccurrence", + "shape": "required-reference", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "UseCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "includedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "PerformActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "performedAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "metaclass": "IncludeUseCaseUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "UseCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "useCaseDefinition", + "shape": "nullable", + "type": "UseCaseDefinition" + }, + { + "declaredOn": "IncludeUseCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "useCaseIncluded", + "shape": "required-reference", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IncludeUseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "operator", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "IndexExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "IndexExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "metaclass": "Interaction", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "associationEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionEnd", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InterfaceDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "interfaceEnd", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "sourceType", + "shape": "nullable", + "type": "Type" + }, + { + "metaclass": "InterfaceDefinition", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Association", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "targetType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConnectionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectionDefinition", + "shape": "array", + "type": "AssociationStructure" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InterfaceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "interfaceDefinition", + "shape": "array", + "type": "InterfaceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "InterfaceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "InterfaceUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "intersectingType", + "shape": "required-reference" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Intersecting", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Intersecting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Intersecting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "typeIntersected", + "shape": "required-reference", + "type": "Type" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Invariant", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isNegated", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Invariant", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Invariant", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "InvocationExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "InvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ItemDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ItemUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "metaclass": "ItemUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ItemUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "JoinNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "JoinNode", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "JoinNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Package", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "filterCondition", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "isStandard", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LibraryPackage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LibraryPackage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralBoolean", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralBoolean", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralBoolean", + "owned": true, + "property": "value", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralInfinity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralInfinity", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInfinity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralInteger", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralInteger", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralInteger", + "owned": true, + "property": "value", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralRational", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralRational", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralRational", + "owned": true, + "property": "value", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "LiteralString", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "LiteralString", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "LiteralString", + "owned": true, + "property": "value", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Membership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Membership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "importedMembership", + "shape": "required-reference" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "isImportAll", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "isRecursive", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "MembershipExpose", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "importedMembership", + "shape": "required-reference" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "isImportAll", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "isRecursive", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MembershipImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "MembershipImport", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "MergeNode", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "MergeNode", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MergeNode", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Metaclass", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Metaclass", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MetadataAccessExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "MetadataAccessExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataAccessExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MetadataDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "MetadataFeature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "metaclass", + "shape": "nullable", + "type": "Metaclass" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MetadataFeature", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "MetadataUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "MetadataFeature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "metaclass", + "shape": "nullable", + "type": "Metaclass" + }, + { + "declaredOn": "MetadataUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "metadataDefinition", + "shape": "nullable", + "type": "Metaclass" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "metaclass": "MetadataUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MetadataUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Multiplicity", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Multiplicity", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "MultiplicityRange", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "1..2", + "ordered": true, + "owned": false, + "property": "bound", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "MultiplicityRange", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "lowerBound", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "MultiplicityRange", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "MultiplicityRange", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "MultiplicityRange", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "upperBound", + "shape": "required-reference", + "type": "Expression" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Namespace", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Namespace", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "importedNamespace", + "shape": "required-reference" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "isImportAll", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "isRecursive", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceExpose", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "NamespaceExpose", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Import", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "importedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "importedNamespace", + "shape": "required-reference" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "isImportAll", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "isRecursive", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NamespaceImport", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "NamespaceImport", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "NullExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "NullExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "NullExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ObjectiveMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedObjectiveRequirement", + "shape": "required-reference", + "type": "RequirementUsage" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ObjectiveMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ObjectiveMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "OccurrenceDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "metaclass": "OccurrenceUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "operator", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "OperatorExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OperatorExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "OwningMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "OwningMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "Package", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Package", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Package", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Package", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Package", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "filterCondition", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Package", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Package", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Package", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Package", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ParameterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberParameter", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ParameterMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PartDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "PartUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PartUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PayloadFeature", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PayloadFeature", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "eventOccurrence", + "shape": "required-reference", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "EventOccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "PerformActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "performedAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "metaclass": "PerformActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PerformActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "PortConjugation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "conjugatedPortDefinition", + "shape": "required-reference", + "type": "ConjugatedPortDefinition" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "conjugatedType", + "shape": "required-reference" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "originalPortDefinition", + "shape": "required-reference" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "originalType", + "shape": "required-reference" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Conjugation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "PortConjugation", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortConjugation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "PortDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "conjugatedPortDefinition", + "shape": "nullable", + "type": "ConjugatedPortDefinition" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PortDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "PortUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PortUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "portDefinition", + "shape": "array", + "type": "PortDefinition" + }, + { + "metaclass": "PortUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "PortUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Predicate", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Predicate", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Predicate", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Subsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "redefinedFeature", + "shape": "required-reference" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "redefiningFeature", + "shape": "required-reference" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "subsettedFeature", + "shape": "required-reference" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "subsettingFeature", + "shape": "required-reference" + }, + { + "metaclass": "Redefinition", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Redefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Subsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "referencedFeature", + "shape": "required-reference" + }, + { + "declaredOn": "ReferenceSubsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencingFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "subsettedFeature", + "shape": "required-reference" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "subsettingFeature", + "shape": "required-reference" + }, + { + "metaclass": "ReferenceSubsetting", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceSubsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "ReferenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ReferenceUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RenderingDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RenderingDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "rendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "RenderingUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RenderingUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "renderingDefinition", + "shape": "nullable", + "type": "RenderingDefinition" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RenderingUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementConstraintMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "RequirementConstraintMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "RequirementDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementDefinition", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementUsage", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "requirementDefinition", + "shape": "nullable", + "type": "RequirementDefinition" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "RequirementVerificationMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedRequirement", + "shape": "required-reference", + "type": "RequirementUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementConstraintMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "RequirementVerificationMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "RequirementVerificationMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "verifiedRequirement", + "shape": "required-reference", + "type": "RequirementUsage" + }, + { + "metaclass": "RequirementVerificationMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "ResultExpressionMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedResultExpression", + "shape": "required-reference", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ResultExpressionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ResultExpressionMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ParameterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberParameter", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ReturnParameterMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ReturnParameterMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AssertConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "assertedConstraint", + "shape": "required-reference", + "type": "ConstraintUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isNegated", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SatisfyRequirementUsage", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "requirementDefinition", + "shape": "nullable", + "type": "RequirementDefinition" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "SatisfyRequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "satisfiedRequirement", + "shape": "required-reference", + "type": "RequirementUsage" + }, + { + "declaredOn": "SatisfyRequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "satisfyingFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SatisfyRequirementUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "operator", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SelectExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SelectExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "SendActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "payloadArgument", + "shape": "required-reference", + "type": "Expression" + }, + { + "metaclass": "SendActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "SendActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "receiverArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "SendActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "senderArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SendActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "Specialization", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ParameterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberParameter", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "StakeholderMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedStakeholderParameter", + "shape": "required-reference", + "type": "PartUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StakeholderMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "StakeholderMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "StateDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "doAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "StateDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "entryAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "StateDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "exitAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isParallel", + "shape": "nullable" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "StateDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "StateDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "state", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "StateSubactionMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "action", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateSubactionMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "StateSubactionMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "doAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "entryAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "exitAction", + "shape": "nullable", + "type": "ActionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isParallel", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "StateUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "StateUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stateDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "StateUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "Step", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Step", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Step", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Step", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Step", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Step", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Step", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Step", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Structure", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Structure", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Subclassification", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningClassifier", + "shape": "nullable", + "type": "Classifier" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "subclassifier", + "shape": "required-reference" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "superclassifier", + "shape": "required-reference" + }, + { + "metaclass": "Subclassification", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subclassification", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ParameterMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberParameter", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "SubjectMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedSubjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SubjectMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "SubjectMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "general", + "shape": "required-reference" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Subsetting", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Specialization", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "specific", + "shape": "required-reference" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "subsettedFeature", + "shape": "required-reference" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "subsettingFeature", + "shape": "required-reference" + }, + { + "metaclass": "Subsetting", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Subsetting", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Succession", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Succession", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "SuccessionAsUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionAsUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionAsUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..2", + "ordered": true, + "owned": false, + "property": "flowEnd", + "shape": "array", + "type": "FlowEnd" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "interaction", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "payloadFeature", + "shape": "nullable", + "type": "PayloadFeature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "payloadType", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceOutputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionFlow", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "targetInputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlow", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "association", + "shape": "array", + "type": "Association" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "connectorEnd", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "defaultFeaturingType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "FlowUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "flowDefinition", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..2", + "ordered": true, + "owned": false, + "property": "flowEnd", + "shape": "array", + "type": "FlowEnd" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "interaction", + "shape": "array", + "type": "Interaction" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "payloadFeature", + "shape": "nullable", + "type": "PayloadFeature" + }, + { + "declaredOn": "Flow", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "payloadType", + "shape": "array", + "type": "Classifier" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "sourceOutputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "SuccessionFlowUsage", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Connector", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "targetFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Flow", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "targetInputFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "SuccessionFlowUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "TerminateActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "TerminateActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "TerminateActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "terminatedOccurrenceArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TerminateActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "1..*", + "ordered": true, + "owned": false, + "property": "annotatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "annotation", + "shape": "array", + "type": "Annotation" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "body", + "shape": "scalar" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "language", + "shape": "scalar" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotatingRelationship", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "AnnotatingElement", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningAnnotatingRelationship", + "shape": "nullable", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TextualRepresentation", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "TextualRepresentation", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "representedElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "TransitionFeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionFeatureMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "transitionFeature", + "shape": "required-reference", + "type": "Step" + }, + { + "metaclass": "TransitionFeatureMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "effectAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "guardExpression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "TransitionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "source", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "succession", + "shape": "required-reference", + "type": "Succession" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "target", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "TransitionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "triggerAction", + "shape": "array", + "type": "AcceptActionUsage" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "argument", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "InstantiationExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "instantiatedType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "kind", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TriggerInvocationExpression", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TriggerInvocationExpression", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Type", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Type", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Type", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Type", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Type", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Type", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Type", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "metaclass": "Type", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Type", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Type", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "featureOfType", + "shape": "required-reference" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "featuringType", + "shape": "required-reference" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "TypeFeaturing", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureOfType", + "shape": "nullable", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "TypeFeaturing", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Unioning", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Unioning", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "typeUnioned", + "shape": "required-reference", + "type": "Type" + }, + { + "metaclass": "Unioning", + "owned": true, + "property": "unioningType", + "shape": "required-reference" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "Usage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "Usage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "Usage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "CalculationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "calculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "UseCaseDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "includedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "UseCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "UseCaseDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "caseDefinition", + "shape": "nullable", + "type": "CaseDefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "UseCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "includedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "UseCaseUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "UseCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "useCaseDefinition", + "shape": "nullable", + "type": "UseCaseDefinition" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "VariantMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedVariantUsage", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VariantMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "VariantMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "declaredOn": "ActionDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "action", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "CalculationDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "calculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "VerificationCaseDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "CaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "VerificationCaseDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "verifiedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "CalculationUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "calculationDefinition", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "caseDefinition", + "shape": "nullable", + "type": "CaseDefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": true, + "owned": false, + "property": "objectiveRequirement", + "shape": "nullable", + "type": "RequirementUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "VerificationCaseUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "CaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "VerificationCaseUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "verificationCaseDefinition", + "shape": "nullable", + "type": "VerificationCaseDefinition" + }, + { + "declaredOn": "VerificationCaseUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "verifiedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ViewDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ViewDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "satisfiedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ViewDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "view", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "ViewDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "viewCondition", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "ViewDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "viewRendering", + "shape": "nullable", + "type": "RenderingUsage" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "isImplied", + "shape": "nullable" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "memberElement", + "shape": "required-reference" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "memberElementId", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "memberName", + "shape": "nullable" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "memberShortName", + "shape": "nullable" + }, + { + "declaredOn": "Membership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "membershipOwningNamespace", + "shape": "required-reference", + "type": "Namespace" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElement", + "shape": "required-reference", + "type": "Element" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberElementId", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedMemberFeature", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "OwningMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedMemberShortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "ownedRelatedElement", + "shape": "array" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "ViewRenderingMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "ownedRendering", + "shape": "required-reference", + "type": "RenderingUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "owningRelatedElement", + "shape": "nullable" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "FeatureMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "required-reference", + "type": "Type" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ViewRenderingMembership", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "referencedRendering", + "shape": "required-reference", + "type": "RenderingUsage" + }, + { + "declaredOn": "Relationship", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "relatedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "source", + "shape": "array" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "target", + "shape": "array" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewRenderingMembership", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "metaclass": "ViewRenderingMembership", + "owned": true, + "property": "visibility", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "ViewUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "exposedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "ItemUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "itemDefinition", + "shape": "array", + "type": "Structure" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ViewUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "PartUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "partDefinition", + "shape": "array", + "type": "PartDefinition" + }, + { + "metaclass": "ViewUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "ViewUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "satisfiedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ViewUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "viewCondition", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "ViewUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "viewDefinition", + "shape": "nullable", + "type": "ViewDefinition" + }, + { + "declaredOn": "ViewUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "viewRendering", + "shape": "nullable", + "type": "RenderingUsage" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "expression", + "shape": "array", + "type": "Expression" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ViewpointDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Classifier", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubclassification", + "shape": "array", + "type": "Subclassification" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ViewpointDefinition", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Function", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Behavior", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "step", + "shape": "array", + "type": "Step" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementDefinition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Definition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Definition", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ViewpointDefinition", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointDefinition", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "viewpointStakeholder", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actorParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "assumedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "ConstraintUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "constraintDefinition", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "framedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Expression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "function", + "shape": "nullable", + "type": "Function" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "passthrough", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isModelLevelEvaluable", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "BooleanExpression", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "predicate", + "shape": "nullable", + "type": "Predicate" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "metaclass": "ViewpointUsage", + "owned": true, + "property": "reqId", + "shape": "nullable" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "requiredConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "requirementDefinition", + "shape": "nullable", + "type": "RequirementDefinition" + }, + { + "declaredOn": "Expression", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "result", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "stakeholderParameter", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "subjectParameter", + "shape": "required-reference", + "type": "Usage" + }, + { + "declaredOn": "RequirementUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "text", + "shape": "array", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "ViewpointUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "viewpointDefinition", + "shape": "nullable", + "type": "ViewpointDefinition" + }, + { + "declaredOn": "ViewpointUsage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "viewpointStakeholder", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "ActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "actionDefinition", + "shape": "array", + "type": "Behavior" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "aliasIds", + "shape": "array" + }, + { + "declaredOn": "Step", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "behavior", + "shape": "array", + "type": "Behavior" + }, + { + "declaredOn": "LoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "bodyAction", + "shape": "required-reference", + "type": "ActionUsage" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "chainingFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "crossFeature", + "shape": "nullable", + "type": "Feature" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "declaredName", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "declaredShortName", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "definition", + "shape": "array", + "type": "Classifier" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "differencingType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "directedUsage", + "shape": "array", + "type": "Usage" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "direction", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "documentation", + "shape": "array", + "type": "Documentation" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "elementId", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "endFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "endOwningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "feature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "featureTarget", + "shape": "required-reference", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "featuringType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "importedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "individualDefinition", + "shape": "nullable", + "type": "OccurrenceDefinition" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "inheritedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "input", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "intersectingType", + "shape": "array", + "type": "Type" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isAbstract", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isComposite", + "shape": "nullable" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isConjugated", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isConstant", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isDerived", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isEnd", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isImpliedIncluded", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isIndividual", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isLibraryElement", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isOrdered", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isPortion", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "isReference", + "shape": "nullable", + "type": "Boolean" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isSufficient", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isUnique", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isVariable", + "shape": "nullable" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "isVariation", + "shape": "nullable" + }, + { + "declaredOn": "Usage", + "fidelity": "not-computed", + "fidelityUnderClosure": "not-computed", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "mayTimeVary", + "shape": "nullable", + "type": "Boolean" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "member", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "membership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "multiplicity", + "shape": "nullable", + "type": "Multiplicity" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "name", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAction", + "shape": "array", + "type": "ActionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAllocation", + "shape": "array", + "type": "AllocationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAnalysisCase", + "shape": "array", + "type": "AnalysisCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedAttribute", + "shape": "array", + "type": "AttributeUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCalculation", + "shape": "array", + "type": "CalculationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedCase", + "shape": "array", + "type": "CaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedConcern", + "shape": "array", + "type": "ConcernUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConnection", + "shape": "array", + "type": "ConnectorAsUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedConstraint", + "shape": "array", + "type": "ConstraintUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedEnumeration", + "shape": "array", + "type": "EnumerationUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedFlow", + "shape": "array", + "type": "FlowUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedInterface", + "shape": "array", + "type": "InterfaceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedItem", + "shape": "array", + "type": "ItemUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedMetadata", + "shape": "array", + "type": "MetadataUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedOccurrence", + "shape": "array", + "type": "OccurrenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPart", + "shape": "array", + "type": "PartUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedPort", + "shape": "array", + "type": "PortUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedReference", + "shape": "array", + "type": "ReferenceUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRendering", + "shape": "array", + "type": "RenderingUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedRequirement", + "shape": "array", + "type": "RequirementUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedState", + "shape": "array", + "type": "StateUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "nestedTransition", + "shape": "array", + "type": "TransitionUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUsage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedUseCase", + "shape": "array", + "type": "UseCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedVerificationCase", + "shape": "array", + "type": "VerificationCaseUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedView", + "shape": "array", + "type": "ViewUsage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "nestedViewpoint", + "shape": "array", + "type": "ViewpointUsage" + }, + { + "declaredOn": "OccurrenceUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "occurrenceDefinition", + "shape": "array", + "type": "Class" + }, + { + "declaredOn": "Type", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "output", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedAnnotation", + "shape": "array", + "type": "Annotation" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedConjugator", + "shape": "nullable", + "type": "Conjugation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedCrossSubsetting", + "shape": "nullable", + "type": "CrossSubsetting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedDifferencing", + "shape": "array", + "type": "Differencing" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedDisjoining", + "shape": "array", + "type": "Disjoining" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedElement", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedEndFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeature", + "shape": "array", + "type": "Feature" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureChaining", + "shape": "array", + "type": "FeatureChaining" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedFeatureInverting", + "shape": "array", + "type": "FeatureInverting" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedFeatureMembership", + "shape": "array", + "type": "FeatureMembership" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedImport", + "shape": "array", + "type": "Import" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedIntersecting", + "shape": "array", + "type": "Intersecting" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMember", + "shape": "array", + "type": "Element" + }, + { + "declaredOn": "Namespace", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedMembership", + "shape": "array", + "type": "Membership" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedRedefinition", + "shape": "array", + "type": "Redefinition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "ownedReferenceSubsetting", + "shape": "nullable", + "type": "ReferenceSubsetting" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "ownedRelationship", + "shape": "array" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedSpecialization", + "shape": "array", + "type": "Specialization" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "ownedSubsetting", + "shape": "array", + "type": "Subsetting" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTypeFeaturing", + "shape": "array", + "type": "TypeFeaturing" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedTyping", + "shape": "array", + "type": "FeatureTyping" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "ownedUnioning", + "shape": "array", + "type": "Unioning" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owner", + "shape": "nullable", + "type": "Element" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningDefinition", + "shape": "nullable", + "type": "Definition" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningFeatureMembership", + "shape": "nullable", + "type": "FeatureMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningMembership", + "shape": "nullable", + "type": "OwningMembership" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningNamespace", + "shape": "nullable", + "type": "Namespace" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "owningRelationship", + "shape": "nullable" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningType", + "shape": "nullable", + "type": "Type" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "owningUsage", + "shape": "nullable", + "type": "Usage" + }, + { + "declaredOn": "Step", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "parameter", + "shape": "array", + "type": "Feature" + }, + { + "metaclass": "WhileLoopActionUsage", + "owned": true, + "property": "portionKind", + "shape": "nullable" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "qualifiedName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "shortName", + "shape": "nullable", + "type": "String" + }, + { + "declaredOn": "Element", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "textualRepresentation", + "shape": "array", + "type": "TextualRepresentation" + }, + { + "declaredOn": "Feature", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "type", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "Type", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "unioningType", + "shape": "array", + "type": "Type" + }, + { + "declaredOn": "WhileLoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..1", + "ordered": false, + "owned": false, + "property": "untilArgument", + "shape": "nullable", + "type": "Expression" + }, + { + "declaredOn": "Usage", + "fidelity": "passthrough", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": true, + "owned": false, + "property": "usage", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variant", + "shape": "array", + "type": "Usage" + }, + { + "declaredOn": "Usage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "0..*", + "ordered": false, + "owned": false, + "property": "variantMembership", + "shape": "array", + "type": "VariantMembership" + }, + { + "declaredOn": "WhileLoopActionUsage", + "fidelity": "exact", + "fidelityUnderClosure": "exact", + "metaclass": "WhileLoopActionUsage", + "multiplicity": "1..1", + "ordered": false, + "owned": false, + "property": "whileArgument", + "shape": "required-reference", + "type": "Expression" + } + ], + "source": "the interchange schema catalog (SysML.schema.json 20250201) joined with spec-refs/derived-properties.json" +} diff --git a/spec-refs/derived-properties.json b/spec-refs/derived-properties.json new file mode 100644 index 0000000..d18d566 --- /dev/null +++ b/spec-refs/derived-properties.json @@ -0,0 +1,10104 @@ +{ + "source": "spec-refs/{KerML,SysML}.xmi 20250201", + "generator": "tools/derived_census.py", + "properties": [ + { + "name": "action", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "StateSubactionMembership", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The ActionUsage that is the ownedMemberFeature of this StateSubactionMembership.", + "doc_refs": [ + "ActionUsage", + "StateSubactionMembership", + "ownedMemberFeature" + ], + "corpus_elements": 56, + "corpus_nonempty": 56, + "class": "structural" + }, + { + "metaclass": "ActionDefinition", + "type": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "step", + "usage" + ], + "redefines": [], + "doc": "The ActionUsages that are steps in this ActionDefinition, which define the actions that specify the behavior of the ActionDefinition.", + "doc_refs": [ + "ActionDefinition", + "ActionUsages", + "steps" + ], + "corpus_elements": 201, + "corpus_nonempty": 32, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 9, + "also_owned_elsewhere": false, + "rules": { + "ActionDefinition": "action = usage->selectByKind(ActionUsage)" + }, + "corpus_elements": 257, + "corpus_nonempty": 88 + }, + { + "name": "actionDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ActionUsage", + "type": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "behavior", + "occurrenceDefinition" + ], + "doc": "The Behaviors that are the types of this ActionUsage. Nominally, these would be ActionDefinitions, but other kinds of Kernel Behaviors are also allowed, to permit use of Behaviors from the Kernel Model Libraries.", + "doc_refs": [ + "ActionDefinitions", + "ActionUsage", + "Behaviors", + "types" + ], + "corpus_elements": 1124, + "corpus_nonempty": 273, + "class": "structural" + } + ], + "concrete_carriers": 24, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 1124, + "corpus_nonempty": 273 + }, + { + "name": "actorParameter", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this RequirementUsage that represent actors involved in the requirement.", + "doc_refs": [ + "RequirementUsage", + "parameters" + ], + "corpus_elements": 171, + "corpus_nonempty": 0, + "class": "inheritance-aware" + }, + { + "metaclass": "RequirementDefinition", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this RequirementDefinition that represent actors involved in the requirement.", + "doc_refs": [ + "RequirementDefinition", + "parameters" + ], + "corpus_elements": 37, + "corpus_nonempty": 0, + "class": "inheritance-aware" + }, + { + "metaclass": "CaseUsage", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this CaseUsage that represent actors involved in the case.", + "doc_refs": [ + "CaseUsage", + "parameters" + ], + "corpus_elements": 65, + "corpus_nonempty": 15, + "class": "inheritance-aware" + }, + { + "metaclass": "CaseDefinition", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this CaseDefinition that represent actors involved in the case.", + "doc_refs": [ + "CaseDefinition", + "parameters" + ], + "corpus_elements": 30, + "corpus_nonempty": 7, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 16, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "actorParameter = featureMembership-> selectByKind(ActorMembership). ownedActorParameter", + "RequirementDefinition": "actorParameter = featureMembership-> selectByKind(ActorMembership). ownedActorParameter", + "CaseUsage": "actorParameter = featureMembership-> selectByKind(ActorMembership). ownedActorParameter", + "CaseDefinition": "actorParameter = featureMembership-> selectByKind(ActorMembership). ownedActorParameter" + }, + "corpus_elements": 303, + "corpus_nonempty": 22 + }, + { + "name": "allocation", + "class": "inheritance-aware", + "status": "absent", + "declaring": [ + { + "metaclass": "AllocationDefinition", + "type": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "usage" + ], + "redefines": [], + "doc": "The AllocationUsages that refine the allocation mapping defined by this AllocationDefinition.", + "doc_refs": [ + "AllocationDefinition", + "AllocationUsages" + ], + "corpus_elements": 5, + "corpus_nonempty": 0, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "AllocationDefinition": "allocation = usage->selectAsKind(AllocationUsage)" + }, + "corpus_elements": 5, + "corpus_nonempty": 0 + }, + { + "name": "allocationDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AllocationUsage", + "type": "AllocationDefinition", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "connectionDefinition" + ], + "doc": "The AllocationDefinitions that are the types of this AllocationUsage.", + "doc_refs": [ + "AllocationDefinitions", + "AllocationUsage" + ], + "corpus_elements": 18, + "corpus_nonempty": 5, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 18, + "corpus_nonempty": 5 + }, + { + "name": "analysisCaseDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AnalysisCaseUsage", + "type": "AnalysisCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "caseDefinition" + ], + "doc": "The AnalysisCaseDefinition that is the definition of this AnalysisCaseUsage.", + "doc_refs": [ + "AnalysisCaseDefinition", + "AnalysisCaseUsage", + "definition" + ], + "corpus_elements": 26, + "corpus_nonempty": 24, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 26, + "corpus_nonempty": 24 + }, + { + "name": "annotatedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AnnotatingElement", + "type": "Element", + "multiplicity": "1..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Elements that are annotated by this AnnotatingElement. If annotation is not empty, these are the annotatedElements of the annotations. If annotation is empty, then it is the owningNamespace of the AnnotatingElement.", + "doc_refs": [ + "AnnotatingElement", + "Elements", + "annotatedElements", + "annotation", + "annotations", + "owningNamespace" + ], + "corpus_elements": 632, + "corpus_nonempty": 632, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": true, + "rules": { + "AnnotatingElement": "annotatedElement = if annotation->notEmpty() then annotation.annotatedElement else Sequence{owningNamespace} endif" + }, + "corpus_elements": 632, + "corpus_nonempty": 632 + }, + { + "name": "annotatingElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Annotation", + "type": "AnnotatingElement", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "source" + ], + "doc": "The AnnotatingElement that annotates the annotatedElement of this Annotation. This is always either the ownedAnnotatingElement or the owningAnnotatingElement.", + "doc_refs": [ + "AnnotatingElement", + "Annotation", + "annotatedElement", + "ownedAnnotatingElement", + "owningAnnotatingElement" + ], + "corpus_elements": 19, + "corpus_nonempty": 19, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "Annotation": "annotatingElement = if ownedAnnotatingElement <> null then ownedAnnotatingElement else owningAnnotatingElement endif" + }, + "corpus_elements": 19, + "corpus_nonempty": 19 + }, + { + "name": "annotation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AnnotatingElement", + "type": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "sourceRelationship" + ], + "redefines": [], + "doc": "The Annotations that relate this AnnotatingElement to its annotatedElements. This includes the owningAnnotatingRelationship (if any) followed by all the ownedAnnotatingRelationshps.", + "doc_refs": [ + "AnnotatingElement", + "Annotations", + "annotatedElements", + "ownedAnnotatingRelationshps", + "owningAnnotatingRelationship" + ], + "corpus_elements": 632, + "corpus_nonempty": 16, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": { + "AnnotatingElement": "annotation = if owningAnnotatingRelationship = null then ownedAnnotatingRelationship else owningAnnotatingRelationship->prepend(owningAnnotatingRelationship) endif" + }, + "corpus_elements": 632, + "corpus_nonempty": 16 + }, + { + "name": "argument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "InstantiationExpression", + "type": "Expression", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Expressions whose results are bound to features of the instantiatedType. The arguments are ordered consistent with the order of the features, though they may not be one-to-one with all the features. Note. The derivation of argument is given in the concrete subclasses of InstantiationExpression.", + "doc_refs": [ + "Expressions", + "InstantiationExpression", + "argument", + "arguments", + "features", + "instantiatedType", + "results" + ], + "corpus_elements": 1605, + "corpus_nonempty": 1585, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 8, + "also_owned_elsewhere": false, + "rules": { + "InvocationExpression": "instantiatedType.input->collect(inp | ownedFeatures->select(redefines(inp)).valuation-> select(v | v <> null).value )", + "ConstructorExpression": "instantiatedType.feature->collect(f | result.ownedFeatures->select(redefines(f)).valuation-> select(v | v <> null).value )" + }, + "corpus_elements": 1605, + "corpus_nonempty": 1585 + }, + { + "name": "assertedConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AssertConstraintUsage", + "type": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ConstraintUsage to be performed by the AssertConstraintUsage. It is the referenceFeature of the ownedReferenceSubsetting for the AssertConstraintUsage, if there is one, and, otherwise, the AssertConstraintUsage itself.", + "doc_refs": [ + "AssertConstraintUsage", + "ConstraintUsage", + "ownedReferenceSubsetting", + "referenceFeature" + ], + "corpus_elements": 69, + "corpus_nonempty": 22, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "AssertConstraintUsage": "assertedConstraint = if referencedFeatureTarget() = null then self else if referencedFeatureTarget().oclIsKindOf(ConstraintUsage) then referencedFeatureTarget().oclAsType(ConstraintUsage) else null endif endif" + }, + "corpus_elements": 69, + "corpus_nonempty": 22 + }, + { + "name": "association", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Connector", + "type": "Association", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "type" + ], + "doc": "The Associations that type the Connector.", + "doc_refs": [ + "Associations", + "Connector" + ], + "corpus_elements": 689, + "corpus_nonempty": 63, + "class": "structural" + } + ], + "concrete_carriers": 12, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 689, + "corpus_nonempty": 63 + }, + { + "name": "associationEnd", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Association", + "type": "Feature", + "multiplicity": "0..*", + "ordered": false, + "subsets": [], + "redefines": [ + "endFeature" + ], + "doc": "The features of the Association that identify the things that can be related by it. A concrete Association must have at least two associationEnds. When it has exactly two, the Association is called a binary Association.", + "doc_refs": [ + "Association", + "associationEnds", + "features" + ], + "corpus_elements": 50, + "corpus_nonempty": 46, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 50, + "corpus_nonempty": 46 + }, + { + "name": "assumedConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The owned ConstraintUsages that represent assumptions of this RequirementUsage, derived as the ownedConstraints of the RequirementConstraintMemberships of the RequirementUsage with kind = assumption.", + "doc_refs": [ + "ConstraintUsages", + "RequirementConstraintMemberships", + "RequirementUsage", + "assumption", + "kind", + "ownedConstraints" + ], + "corpus_elements": 171, + "corpus_nonempty": 17, + "class": "structural" + }, + { + "metaclass": "RequirementDefinition", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The owned ConstraintUsages that represent assumptions of this RequirementDefinition, which are the ownedConstraints of the RequirementConstraintMemberships of the RequirementDefinition with kind = assumption.", + "doc_refs": [ + "ConstraintUsages", + "RequirementConstraintMemberships", + "RequirementDefinition", + "ownedConstraints" + ], + "corpus_elements": 37, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "assumedConstraint = ownedFeatureMembership-> selectByKind(RequirementConstraintMembership)-> select(kind = RequirementConstraintKind::assumption). ownedConstraint", + "RequirementDefinition": "assumedConstraint = ownedFeatureMembership-> selectByKind(RequirementConstraintMembership)-> select(kind = RequirementConstraintKind::assumption). ownedConstraint" + }, + "corpus_elements": 208, + "corpus_nonempty": 19 + }, + { + "name": "attributeDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AttributeUsage", + "type": "DataType", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "definition" + ], + "doc": "The DataTypes that are the types of this AttributeUsage. Nominally, these are AttributeDefinitions, but other kinds of kernel DataTypes are also allowed, to permit use of DataTypes from the Kernel Model Libraries.", + "doc_refs": [ + "AttributeDefinitions", + "AttributeUsage", + "DataTypes" + ], + "corpus_elements": 869, + "corpus_nonempty": 778, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 869, + "corpus_nonempty": 778 + }, + { + "name": "behavior", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Step", + "type": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "type" + ], + "redefines": [], + "doc": "The Behaviors that type this Step.", + "doc_refs": [ + "Behaviors", + "Step" + ], + "corpus_elements": 6120, + "corpus_nonempty": 400, + "class": "structural" + } + ], + "concrete_carriers": 53, + "also_owned_elsewhere": false, + "rules": { + "Step": "behavior = type->selectByKind(Behavior)" + }, + "corpus_elements": 6120, + "corpus_nonempty": 400 + }, + { + "name": "bodyAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "LoopActionUsage", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage to be performed repeatedly by the LoopActionUsage. It is the second parameter of the LoopActionUsage.", + "doc_refs": [ + "ActionUsage", + "LoopActionUsage", + "parameter" + ], + "corpus_elements": 8, + "corpus_nonempty": 5, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "LoopActionUsage": "bodyAction = let parameter : Feature = inputParameter(2) in if parameter <> null and parameter.oclIsKindOf(Action) then parameter.oclAsType(Action) else null endif " + }, + "corpus_elements": 8, + "corpus_nonempty": 5 + }, + { + "name": "bound", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MultiplicityRange", + "type": "Expression", + "multiplicity": "1..2", + "ordered": true, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The owned Expressions of the MultiplicityRange whose results provide its bounds. These must be the first ownedMembers of the MultiplicityRange.", + "doc_refs": [ + "Expressions", + "MultiplicityRange", + "ownedMembers" + ], + "corpus_elements": 576, + "corpus_nonempty": 576, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "MultiplicityRange": "bound = if upperBound = null then Sequence{} else if lowerBound = null then Sequence{upperBound} else Sequence{lowerBound, upperBound} endif endif" + }, + "corpus_elements": 576, + "corpus_nonempty": 576 + }, + { + "name": "calculation", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "CalculationDefinition", + "type": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "action", + "expression" + ], + "redefines": [], + "doc": "The actions of this CalculationDefinition that are CalculationUsages.", + "doc_refs": [ + "CalculationDefinition", + "CalculationUsages", + "actions" + ], + "corpus_elements": 69, + "corpus_nonempty": 6, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 5, + "also_owned_elsewhere": false, + "rules": { + "CalculationDefinition": "calculation = action->selectByKind(CalculationUsage)" + }, + "corpus_elements": 69, + "corpus_nonempty": 6 + }, + { + "name": "calculationDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "CalculationUsage", + "type": "Function", + "multiplicity": "0..1", + "ordered": true, + "subsets": [], + "redefines": [ + "actionDefinition", + "function" + ], + "doc": "The Function that is the type of this CalculationUsage. Nominally, this would be a CalculationDefinition, but a kernel Function is also allowed, to permit use of Functions from the Kernel Model Libraries.", + "doc_refs": [ + "CalculationDefinition", + "CalculationUsage", + "Function", + "Functions", + "type" + ], + "corpus_elements": 96, + "corpus_nonempty": 68, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 96, + "corpus_nonempty": 68 + }, + { + "name": "caseDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "CaseUsage", + "type": "CaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "calculationDefinition" + ], + "doc": "The CaseDefinition that is the type of this CaseUsage.", + "doc_refs": [], + "corpus_elements": 65, + "corpus_nonempty": 44, + "class": "structural" + } + ], + "concrete_carriers": 5, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 65, + "corpus_nonempty": 44 + }, + { + "name": "chainingFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Feature that are chained together to determine the values of this Feature, derived from the chainingFeatures of the ownedFeatureChainings of this Feature, in the same order. The values of a Feature with chainingFeatures are the same as values of the last Feature in the chain, which can be found by starting with the values of the first Feature (for each instance of the domain of the original Feature), then using each of those as domain instances to find the values of the second Feature in chainingFeatures, and so on, to values of the last Feature.", + "doc_refs": [ + "Feature", + "chainingFeatures", + "ownedFeatureChainings" + ], + "corpus_elements": 16951, + "corpus_nonempty": 588, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": true, + "rules": { + "Feature": "chainingFeature = ownedFeatureChaining.chainingFeature" + }, + "corpus_elements": 16951, + "corpus_nonempty": 588 + }, + { + "name": "concernDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConcernUsage", + "type": "ConcernDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "requirementDefinition" + ], + "doc": "The ConcernDefinition that is the single type of this ConcernUsage.", + "doc_refs": [], + "corpus_elements": 11, + "corpus_nonempty": 3, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 11, + "corpus_nonempty": 3 + }, + { + "name": "condition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ElementFilterMembership", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberElement" + ], + "doc": "The model-level evaluable Boolean-valued Expression used to filter the imported members of the membershipOwningNamespace of this ElementFilterMembership.", + "doc_refs": [ + "Boolean", + "ElementFilterMembership", + "Expression", + "members", + "membershipOwningNamespace" + ], + "corpus_elements": 26, + "corpus_nonempty": 26, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 26, + "corpus_nonempty": 26 + }, + { + "name": "conjugatedPortDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "PortConjugation", + "type": "ConjugatedPortDefinition", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "owningType" + ], + "doc": "The ConjugatedPortDefinition that is conjugate to the originalPortDefinition.", + "doc_refs": [ + "ConjugatedPortDefinition", + "originalPortDefinition" + ], + "corpus_elements": 91, + "corpus_nonempty": 91, + "class": "structural" + }, + { + "metaclass": "PortDefinition", + "type": "ConjugatedPortDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The that is conjugate to this PortDefinition.", + "doc_refs": [ + "PortDefinition" + ], + "corpus_elements": 182, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": true, + "rules": { + "PortDefinition": "conjugatedPortDefinition = let conjugatedPortDefinitions : OrderedSet(ConjugatedPortDefinition) = ownedMember->selectByKind(ConjugatedPortDefinition) in if conjugatedPortDefinitions->isEmpty() then null else conjugatedPortDefinitions->first() endif" + }, + "corpus_elements": 273, + "corpus_nonempty": 182 + }, + { + "name": "connectionDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConnectionUsage", + "type": "AssociationStructure", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "itemDefinition" + ], + "redefines": [ + "association" + ], + "doc": "The AssociationStructures that are the types of this ConnectionUsage. Nominally, these are , but other kinds of Kernel AssociationStructures are also allowed, to permit use of AssociationStructures from the Kernel Model Libraries", + "doc_refs": [ + "AssociationStructures", + "ConnectionUsage" + ], + "corpus_elements": 127, + "corpus_nonempty": 52, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 127, + "corpus_nonempty": 52 + }, + { + "name": "connectionEnd", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "ConnectionDefinition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "associationEnd" + ], + "doc": "The Usages that define the things related by the ConnectionDefinition.", + "doc_refs": [ + "ConnectionDefinition", + "Usages" + ], + "corpus_elements": 48, + "corpus_nonempty": 45, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 48, + "corpus_nonempty": 45 + }, + { + "name": "connectorEnd", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Connector", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "endFeature" + ], + "doc": "The endFeatures of a Connector, which redefine the endFeatures of the associations of the Connector. The connectorEnds determine via ReferenceSubsetting Relationships which Features are related by the Connector.", + "doc_refs": [ + "Connector", + "Features", + "ReferenceSubsetting", + "Relationships", + "associations", + "connectorEnds", + "endFeatures" + ], + "corpus_elements": 689, + "corpus_nonempty": 670, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 12, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 689, + "corpus_nonempty": 670 + }, + { + "name": "constraintDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConstraintUsage", + "type": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "predicate" + ], + "doc": "The (single) Predicate that is the type of this ConstraintUsage. Nominally, this will be a ConstraintDefinition, but other kinds of Predicates are also allowed, to permit use of Predicates from the Kernel Model Libraries.", + "doc_refs": [ + "ConstraintDefinition", + "ConstraintUsage", + "Predicate", + "Predicates" + ], + "corpus_elements": 291, + "corpus_nonempty": 127, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 291, + "corpus_nonempty": 127 + }, + { + "name": "crossFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Feature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The second chainingFeature of the crossedFeature of the ownedCrossSubsetting of this Feature, if it has one. Semantically, the values of the crossFeature of an end Feature must include all values of the end Feature obtained when navigating from values of the other end Features of the same owningType.", + "doc_refs": [ + "Feature", + "Features", + "chainingFeature", + "crossFeature", + "crossedFeature", + "ownedCrossSubsetting", + "owningType" + ], + "corpus_elements": 16951, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "crossFeature = if ownedCrossSubsetting = null then null else let chainingFeatures: Sequence(Feature) = ownedCrossSubsetting.crossedFeature.chainingFeature in if chainingFeatures->size() < 2 then null else chainingFeatures->at(2) endif" + }, + "corpus_elements": 16951, + "corpus_nonempty": 2 + }, + { + "name": "crossingFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "CrossSubsetting", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "owningFeature", + "subsettingFeature" + ], + "doc": "The end Feature that owns this CrossSubsetting relationship and is also its subsettingFeature.", + "doc_refs": [ + "CrossSubsetting", + "Feature" + ], + "corpus_elements": 2, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 2, + "corpus_nonempty": 2 + }, + { + "name": "defaultFeaturingType", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Connector", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The innermost Type that is a common direct or indirect featuringType of the relatedFeatures, such that, if it exists and was the featuringType of this Connector, the Connector would satisfy the checkConnectorTypeFeaturing constraint.", + "doc_refs": [ + "Connector", + "Type", + "checkConnectorTypeFeaturing", + "featuringType", + "relatedFeatures" + ], + "corpus_elements": 689, + "corpus_nonempty": 475, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 12, + "also_owned_elsewhere": false, + "rules": { + "Connector": "let commonFeaturingTypes : OrderedSet(Type) = relatedFeature->closure(featuringType)->select(t | relatedFeature->forAll(f | f.isFeaturedWithin(t)) ) in let nearestCommonFeaturingTypes : OrderedSet(Type) = commonFeaturingTypes->reject(t1 | commonFeaturingTypes->exists(t2 | t2 <> t1 and t2->closure(featuringType)->contains(t1) )) in if nearestCommonFeaturingTypes->isEmpty() then null else nearestCommonFeaturingTypes->first() endif" + }, + "corpus_elements": 689, + "corpus_nonempty": 475 + }, + { + "name": "definition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "type" + ], + "doc": "The Classifiers that are the types of this Usage. Nominally, these are Definitions, but other kinds of Kernel Classifiers are also allowed, to permit use of Classifiers from the Kernel Model Libraries.", + "doc_refs": [ + "Classifiers", + "Definitions", + "Usage" + ], + "corpus_elements": 8045, + "corpus_nonempty": 4244, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 8045, + "corpus_nonempty": 4244 + }, + { + "name": "differencingType", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The interpretations of a Type with differencingTypes are asserted to be those of the first of those Types, but not including those of the remaining Types. For example, a Classifier might be the difference of a Classifier for people and another for people of a particular nationality, leaving people who are not of that nationality. Similarly, a feature of people might be the difference between a feature for their children and a Classifier for people of a particular sex, identifying their children not of that sex (because the interpretations of the children Feature that identify those of that sex are also interpretations of the Classifier for that sex).", + "doc_refs": [ + "Classifier", + "Feature", + "Type", + "Types", + "differencingTypes" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": true, + "rules": { + "Type": "differencingType = ownedDifferencing.differencingType" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "directedFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "The features of this Type that have a non-null direction.", + "doc_refs": [ + "Type", + "direction", + "features" + ], + "corpus_elements": 18305, + "corpus_nonempty": 2635, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "directedFeature = feature->select(f | directionOf(f) <> null)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 2635 + }, + { + "name": "directedUsage", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "directedFeature", + "usage" + ], + "redefines": [], + "doc": "The usages of this Usage that are directedFeatures.", + "doc_refs": [ + "Usage", + "directedFeatures", + "usages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 570, + "class": "inheritance-aware" + }, + { + "metaclass": "Definition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "directedFeature", + "usage" + ], + "redefines": [], + "doc": "The usages of this Definition that are directedFeatures.", + "doc_refs": [ + "Definition", + "directedFeatures", + "usages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 188, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 73, + "also_owned_elsewhere": false, + "rules": { + "Usage": "directedUsage = directedFeature->selectByKind(Usage)", + "Definition": "directedUsage = directedFeature->selectByKind(Usage)" + }, + "corpus_elements": 9399, + "corpus_nonempty": 758 + }, + { + "name": "doAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "StateUsage", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateUsage to be performed while in the state defined by the StateDefinition. It is the owned ActionUsage related to the StateUsage by a StateSubactionMembership with kind = do.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership", + "StateUsage" + ], + "corpus_elements": 160, + "corpus_nonempty": 17, + "class": "structural" + }, + { + "metaclass": "StateDefinition", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateDefinition to be performed while in the state defined by the StateDefinition. It is the owned ActionUsage related to the StateDefinition by a StateSubactionMembership with kind = do.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership" + ], + "corpus_elements": 17, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "StateUsage": "doAction = let doMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::do) in if doMemberships->isEmpty() then null else doMemberships->at(1) endif", + "StateDefinition": "doAction = let doMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::do) in if doMemberships->isEmpty() then null else doMemberships->at(1) endif" + }, + "corpus_elements": 177, + "corpus_nonempty": 18 + }, + { + "name": "documentation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "Documentation", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "annotatingElement", + "ownedElement" + ], + "redefines": [], + "doc": "The Documentation owned by this Element.", + "doc_refs": [], + "corpus_elements": 52148, + "corpus_nonempty": 156, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "documentation = ownedElement->selectByKind(Documentation)" + }, + "corpus_elements": 52148, + "corpus_nonempty": 156 + }, + { + "name": "documentedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Documentation", + "type": "Element", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owner" + ], + "redefines": [ + "annotatedElement" + ], + "doc": "The Element that is documented by this Documentation.", + "doc_refs": [ + "Documentation", + "Element" + ], + "corpus_elements": 157, + "corpus_nonempty": 157, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 157, + "corpus_nonempty": 157 + }, + { + "name": "effectAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "ActionUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "The ActionUsages that define the effects of this TransitionUsage, which are the ownedFeatures of the TransitionUsage related to it by TransitionFeatureMemberships with kind = effect, which must all be ActionUsages.", + "doc_refs": [ + "ActionUsages", + "TransitionFeatureMemberships", + "TransitionUsage", + "ownedFeatures" + ], + "corpus_elements": 111, + "corpus_nonempty": 20, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "TransitionUsage": "triggerAction = ownedFeatureMembership-> selectByKind(TransitionFeatureMembership)-> select(kind = TransitionFeatureKind::trigger).transitionFeatures-> selectByKind(AcceptActionUsage)" + }, + "corpus_elements": 111, + "corpus_nonempty": 20 + }, + { + "name": "elseAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "IfActionUsage", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage that is to be performed if the result of the ifArgument is false. It is the (optional) third parameter of the IfActionUsage.", + "doc_refs": [ + "ActionUsage", + "IfActionUsage", + "ifArgument", + "parameter" + ], + "corpus_elements": 4, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "IfActionUsage": "elseAction = let parameter : Feature = inputParameter(3) in if parameter <> null and parameter.oclIsKindOf(ActionUsage) then parameter.oclAsType(ActionUsage) else null endif" + }, + "corpus_elements": 4, + "corpus_nonempty": 2 + }, + { + "name": "endFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "All features of this Type with isEnd = true.", + "doc_refs": [ + "Type", + "features" + ], + "corpus_elements": 18305, + "corpus_nonempty": 716, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "endFeature = feature->select(isEnd)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 716 + }, + { + "name": "endOwningType", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "owningType", + "typeWithEndFeature" + ], + "redefines": [], + "doc": "The Type that is related to this Feature by an EndFeatureMembership in which the Feature is an ownedMemberFeature.", + "doc_refs": [ + "EndFeatureMembership", + "Feature", + "Type", + "ownedMemberFeature" + ], + "corpus_elements": 16951, + "corpus_nonempty": 1420, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 16951, + "corpus_nonempty": 1420 + }, + { + "name": "entryAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "StateUsage", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateUsage to be performed on entry to the state defined by the StateDefinition. It is the owned ActionUsage related to the StateUsage by a StateSubactionMembership with kind = entry.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership", + "StateUsage" + ], + "corpus_elements": 160, + "corpus_nonempty": 29, + "class": "structural" + }, + { + "metaclass": "StateDefinition", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateDefinition to be performed on entry to the state defined by the StateDefinition. It is the owned ActionUsage related to the StateDefinition by a StateSubactionMembership with kind = entry.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership" + ], + "corpus_elements": 17, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "StateUsage": "entryAction = let entryMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::entry) in if entryMemberships->isEmpty() then null else entryMemberships->at(1) endif", + "StateDefinition": "entryAction = let entryMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::entry) in if entryMemberships->isEmpty() then null else entryMemberships->at(1) endif" + }, + "corpus_elements": 177, + "corpus_nonempty": 31 + }, + { + "name": "enumeratedValue", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "EnumerationDefinition", + "type": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "variant" + ], + "doc": "EnumerationUsages of this EnumerationDefinitionthat have distinct, fixed values. Each enumeratedValue specifies one of the allowed instances of the EnumerationDefinition.", + "doc_refs": [ + "EnumerationDefinition", + "EnumerationUsages", + "enumeratedValue" + ], + "corpus_elements": 19, + "corpus_nonempty": 18, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 19, + "corpus_nonempty": 18 + }, + { + "name": "enumerationDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "EnumerationUsage", + "type": "EnumerationDefinition", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "attributeDefinition" + ], + "doc": "The single EnumerationDefinition that is the type of this EnumerationUsage.", + "doc_refs": [], + "corpus_elements": 55, + "corpus_nonempty": 54, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 55, + "corpus_nonempty": 54 + }, + { + "name": "eventOccurrence", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "EventOccurrenceUsage", + "type": "OccurrenceUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The OccurrenceUsage referenced as an event by this EventOccurrenceUsage. It is the referenceFeature of the ownedReferenceSubsetting for the EventOccurrenceUsage, if there is one, and, otherwise, the EventOccurrenceUsage itself.", + "doc_refs": [ + "EventOccurrenceUsage", + "OccurrenceUsage", + "ownedReferenceSubsetting", + "referenceFeature" + ], + "corpus_elements": 324, + "corpus_nonempty": 184, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "EventOccurrenceUsage": "eventOccurrence = if referencedFeatureTarget() = null then self else if referencedFeatureTarget().oclIsKindOf(OccurrenceUsage) then referencedFeatureTarget().oclAsType(OccurrenceUsage) else null endif endif" + }, + "corpus_elements": 324, + "corpus_nonempty": 184 + }, + { + "name": "exhibitedState", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ExhibitStateUsage", + "type": "StateUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "performedAction" + ], + "doc": "The StateUsage to be exhibited by the ExhibitStateUsage. It is the performedAction of the ExhibitStateUsage considered as a PerformActionUsage, which must be a StateUsage.", + "doc_refs": [ + "ExhibitStateUsage", + "PerformActionUsage", + "StateUsage", + "performedAction" + ], + "corpus_elements": 29, + "corpus_nonempty": 10, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 29, + "corpus_nonempty": 10 + }, + { + "name": "exitAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "StateUsage", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateUsage to be performed on exit to the state defined by the StateDefinition. It is the owned ActionUsage related to the StateUsage by a StateSubactionMembership with kind = exit.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership", + "StateUsage" + ], + "corpus_elements": 160, + "corpus_nonempty": 6, + "class": "structural" + }, + { + "metaclass": "StateDefinition", + "type": "ActionUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage of this StateDefinition to be performed on exit to the state defined by the StateDefinition. It is the owned ActionUsage related to the StateDefinition by a StateSubactionMembership with kind = exit.", + "doc_refs": [ + "ActionUsage", + "StateDefinition", + "StateSubactionMembership" + ], + "corpus_elements": 17, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "StateUsage": "exitAction = let exitMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::exit) in if exitMemberships->isEmpty() then null else exitMemberships->at(1) endif", + "StateDefinition": "exitAction = let exitMemberships : Sequence(StateSubactionMembership) = ownedMembership-> selectByKind(StateSubactionMembership)-> select(kind = StateSubactionKind::exit) in if exitMemberships->isEmpty() then null else exitMemberships->at(1) endif" + }, + "corpus_elements": 177, + "corpus_nonempty": 7 + }, + { + "name": "exposedElement", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewUsage", + "type": "Element", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Elements that are exposed by this ViewUsage, which are those memberElements of the imported Memberships from all the Expose Relationships that meet all the owned and inherited viewConditions.", + "doc_refs": [ + "Elements", + "Expose", + "Memberships", + "Relationships", + "ViewUsage", + "memberElements", + "viewConditions" + ], + "corpus_elements": 12, + "corpus_nonempty": 5, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "ViewUsage": "exposedElement = ownedImport->selectByKind(Expose). importedMemberships(Set{}).memberElement-> select(elm | includeAsExposed(elm))-> asOrderedSet()" + }, + "corpus_elements": 12, + "corpus_nonempty": 5 + }, + { + "name": "expression", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Function", + "type": "Expression", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "step" + ], + "redefines": [], + "doc": "The Expressions that are steps in the calculation of the result of this Function.", + "doc_refs": [ + "Expressions", + "Function", + "result", + "steps" + ], + "corpus_elements": 127, + "corpus_nonempty": 56, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 11, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 127, + "corpus_nonempty": 56 + }, + { + "name": "feature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The ownedMemberFeatures of the featureMemberships of this Type.", + "doc_refs": [ + "Type", + "featureMemberships", + "ownedMemberFeatures" + ], + "corpus_elements": 18305, + "corpus_nonempty": 4942, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "feature = featureMembership.ownedMemberFeature" + }, + "corpus_elements": 18305, + "corpus_nonempty": 4942 + }, + { + "name": "featureChained", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureChaining", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "The Feature whose values are partly determined by values of the chainingFeature, as described in Feature::chainingFeature.", + "doc_refs": [ + "Feature", + "chainingFeature" + ], + "corpus_elements": 1331, + "corpus_nonempty": 1331, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 1331, + "corpus_nonempty": 1331 + }, + { + "name": "featureMembership", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The FeatureMemberships for features of this Type, which include all ownedFeatureMemberships and those inheritedMemberships that are FeatureMemberships (but does not include any importedMemberships).", + "doc_refs": [ + "FeatureMemberships", + "Type", + "features", + "importedMemberships", + "inheritedMemberships", + "ownedFeatureMemberships" + ], + "corpus_elements": 18305, + "corpus_nonempty": 4942, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "featureMembership = ownedFeatureMembership->union( inheritedMembership->selectByKind(FeatureMembership))" + }, + "corpus_elements": 18305, + "corpus_nonempty": 4942 + }, + { + "name": "featureTarget", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The last of the chainingFeatures of this Feature, if it has any. Otherwise, this Feature itself.", + "doc_refs": [ + "Feature", + "chainingFeatures" + ], + "corpus_elements": 16951, + "corpus_nonempty": 588, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "featureTarget = if chainingFeature->isEmpty() then self else chainingFeature->last() endif" + }, + "corpus_elements": 16951, + "corpus_nonempty": 588 + }, + { + "name": "featureWithValue", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureValue", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "membershipOwningNamespace" + ], + "redefines": [], + "doc": "The Feature to be provided a value.", + "doc_refs": [], + "corpus_elements": 3825, + "corpus_nonempty": 3825, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 3825, + "corpus_nonempty": 3825 + }, + { + "name": "featuringType", + "class": "closure", + "status": "absent", + "declaring": [ + { + "metaclass": "Feature", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "Types that feature this Feature, such that any instance in the domain of the Feature must be classified by all of these Types, including at least all the featuringTypes of its typeFeaturings. If the Feature is chained, then the featuringTypes of the first Feature in the chain are also featuringTypes of the chained Feature.", + "doc_refs": [ + "Feature", + "Types", + "featuringTypes", + "typeFeaturings" + ], + "corpus_elements": 16951, + "corpus_nonempty": 0, + "class": "closure" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": true, + "rules": { + "Feature": "featuringType = let featuringTypes : OrderedSet(Type) = featuring.type->asOrderedSet() in if chainingFeature->isEmpty() then featuringTypes else featuringTypes-> union(chainingFeature->first().featuringType)-> asOrderedSet() endif" + }, + "corpus_elements": 16951, + "corpus_nonempty": 0 + }, + { + "name": "filterCondition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Package", + "type": "Expression", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The model-level evaluable Boolean-valued Expression used to filter the members of this Package, which are owned by the Package are via ElementFilterMemberships.", + "doc_refs": [ + "ElementFilterMemberships", + "Expression", + "Package", + "members" + ], + "corpus_elements": 481, + "corpus_nonempty": 20, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "Package": "filterCondition = ownedMembership-> selectByKind(ElementFilterMembership).condition" + }, + "corpus_elements": 481, + "corpus_nonempty": 20 + }, + { + "name": "flowDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FlowUsage", + "type": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "actionDefinition", + "interaction" + ], + "doc": "The Interactions that are the types of this FlowUsage. Nominally, these are FlowDefinitions, but other kinds of Kernel Interactions are also allowed, to permit use of Interactions from the Kernel Model Libraries.", + "doc_refs": [ + "FlowDefinitions", + "FlowUsage", + "Interactions", + "types" + ], + "corpus_elements": 142, + "corpus_nonempty": 8, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 142, + "corpus_nonempty": 8 + }, + { + "name": "flowEnd", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "FlowEnd", + "multiplicity": "0..2", + "ordered": true, + "subsets": [ + "connectorEnd" + ], + "redefines": [], + "doc": "The connectorEnds of this Flow that are FlowEnds.", + "doc_refs": [ + "Flow", + "FlowEnds", + "connectorEnds" + ], + "corpus_elements": 142, + "corpus_nonempty": 122, + "class": "inheritance-aware" + }, + { + "metaclass": "FlowDefinition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [], + "redefines": [ + "associationEnd" + ], + "doc": "The Usages that define the things related by the FlowDefinition.", + "doc_refs": [ + "FlowDefinition", + "Usages" + ], + "corpus_elements": 2, + "corpus_nonempty": 0, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 5, + "also_owned_elsewhere": false, + "rules": { + "Flow": "flowEnd = connectorEnd->selectByKind(FlowEnd)" + }, + "corpus_elements": 144, + "corpus_nonempty": 122 + }, + { + "name": "framedConcern", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "requiredConstraint" + ], + "redefines": [], + "doc": "The ConcernUsages framed by this RequirementUsage, which are the ownedConcerns of all FramedConcernMemberships of the RequirementUsage.", + "doc_refs": [ + "ConcernUsages", + "FramedConcernMemberships", + "RequirementUsage", + "ownedConcerns" + ], + "corpus_elements": 171, + "corpus_nonempty": 3, + "class": "inheritance-aware" + }, + { + "metaclass": "RequirementDefinition", + "type": "ConcernUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "requiredConstraint" + ], + "redefines": [], + "doc": "The ConcernUsages framed by this RequirementDefinition, which are the ownedConcerns of all FramedConcernMemberships of the RequirementDefinition.", + "doc_refs": [ + "ConcernUsages", + "FramedConcernMemberships", + "RequirementDefinition", + "ownedConcerns" + ], + "corpus_elements": 37, + "corpus_nonempty": 2, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "framedConcern = featureMembership-> selectByKind(FramedConcernMembership). ownedConcern", + "RequirementDefinition": "framedConcern = featureMembership-> selectByKind(FramedConcernMembership). ownedConcern" + }, + "corpus_elements": 208, + "corpus_nonempty": 5 + }, + { + "name": "function", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Expression", + "type": "Function", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "behavior" + ], + "doc": "The Function that types this Expression.", + "doc_refs": [ + "Expression", + "Function" + ], + "corpus_elements": 5092, + "corpus_nonempty": 195, + "class": "structural" + } + ], + "concrete_carriers": 32, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 5092, + "corpus_nonempty": 195 + }, + { + "name": "guardExpression", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "Expression", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The Expressions that define the guards of this TransitionUsage, which are the ownedFeatures of the TransitionUsage related to it by TransitionFeatureMemberships with kind = guard, which must all be Expressions.", + "doc_refs": [ + "Expressions", + "TransitionFeatureMemberships", + "TransitionUsage", + "ownedFeatures" + ], + "corpus_elements": 111, + "corpus_nonempty": 21, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "TransitionUsage": "guardExpression = ownedFeatureMembership-> selectByKind(TransitionFeatureMembership)-> select(kind = TransitionFeatureKind::trigger).transitionFeature-> selectByKind(Expression)" + }, + "corpus_elements": 111, + "corpus_nonempty": 21 + }, + { + "name": "ifArgument", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "IfActionUsage", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose result determines whether the thenAction or (optionally) the elseAction is performed. It is the first parameter of the IfActionUsage.", + "doc_refs": [ + "Expression", + "IfActionUsage", + "elseAction", + "thenAction" + ], + "corpus_elements": 4, + "corpus_nonempty": 4, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "IfActionUsage": "ifArgument = let parameter : Feature = inputParameter(1) in if parameter <> null and parameter.oclIsKindOf(Expression) then parameter.oclAsType(Expression) else null endif" + }, + "corpus_elements": 4, + "corpus_nonempty": 4 + }, + { + "name": "importOwningNamespace", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Import", + "type": "Namespace", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "The Namespace into which Memberships are imported by this Import, which must be the owningRelatedElement of the Import.", + "doc_refs": [ + "owningRelatedElement" + ], + "corpus_elements": 566, + "corpus_nonempty": 566, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 566, + "corpus_nonempty": 566 + }, + { + "name": "importedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Import", + "type": "Element", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The effectively imported Element for this Import. For a MembershipImport, this is the memberElement of the importedMembership. For a NamespaceImport, it is the importedNamespace.", + "doc_refs": [ + "Element", + "MembershipImport", + "NamespaceImport", + "importedMembership", + "importedNamespace", + "memberElement" + ], + "corpus_elements": 566, + "corpus_nonempty": 566, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "NamespaceImport": "importedElement = importedNamespace", + "MembershipImport": "importedElement = importedMembership.memberElement" + }, + "corpus_elements": 566, + "corpus_nonempty": 566 + }, + { + "name": "importedMembership", + "class": "closure", + "status": "absent", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Membership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "membership" + ], + "redefines": [], + "doc": "The Memberships in this Namespace that result from the ownedImports of this Namespace.", + "doc_refs": [ + "Memberships", + "Namespace", + "ownedImports" + ], + "corpus_elements": 19037, + "corpus_nonempty": 0, + "class": "closure" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": true, + "rules": { + "Namespace": "importedMembership = importedMemberships(Set{})" + }, + "corpus_elements": 19037, + "corpus_nonempty": 0 + }, + { + "name": "includedUseCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "UseCaseUsage", + "type": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The UseCaseUsages that are included by this UseCaseUse, which are the useCaseIncludeds of the IncludeUseCaseUsages owned by this UseCaseUsage.", + "doc_refs": [ + "IncludeUseCaseUsages", + "UseCaseUsages", + "UseCaseUse", + "useCaseIncludeds" + ], + "corpus_elements": 32, + "corpus_nonempty": 5, + "class": "structural" + }, + { + "metaclass": "UseCaseDefinition", + "type": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The UseCaseUsages that are included by this UseCaseDefinition, which are the useCaseIncludeds of the IncludeUseCaseUsages owned by this UseCaseDefinition.", + "doc_refs": [ + "IncludeUseCaseUsages", + "UseCaseDefinition", + "UseCaseUsages", + "useCaseIncludeds" + ], + "corpus_elements": 8, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "UseCaseUsage": "includedUseCase = ownedUseCase-> selectByKind(IncludeUseCaseUsage). useCaseIncluded", + "UseCaseDefinition": "includedUseCase = ownedUseCase-> selectByKind(IncludeUseCaseUsage). useCaseIncluded" + }, + "corpus_elements": 40, + "corpus_nonempty": 7 + }, + { + "name": "individualDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OccurrenceUsage", + "type": "OccurrenceDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "occurrenceDefinition" + ], + "redefines": [], + "doc": "The at most one occurrenceDefinition that has isIndividual = true.", + "doc_refs": [ + "occurrenceDefinition" + ], + "corpus_elements": 3627, + "corpus_nonempty": 61, + "class": "structural" + } + ], + "concrete_carriers": 41, + "also_owned_elsewhere": false, + "rules": { + "OccurrenceUsage": "individualDefinition = let individualDefinitions : OrderedSet(OccurrenceDefinition) = occurrenceDefinition-> selectByKind(OccurrenceDefinition)-> select(isIndividual) in if individualDefinitions->isEmpty() then null else individualDefinitions->first() endif" + }, + "corpus_elements": 3627, + "corpus_nonempty": 61 + }, + { + "name": "inheritedFeature", + "class": "closure", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "All the memberFeatures of the inheritedMemberships of this Type that are FeatureMemberships.", + "doc_refs": [ + "FeatureMemberships", + "Type", + "inheritedMemberships", + "memberFeatures" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "closure" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "inheritedFeature = inheritedMemberships-> selectByKind(FeatureMembership).memberFeature" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "inheritedMembership", + "class": "closure", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Membership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "membership" + ], + "redefines": [], + "doc": "All Memberships inherited by this Type via Specialization or Conjugation. These are included in the derived union for the memberships of the Type.", + "doc_refs": [ + "Conjugation", + "Memberships", + "Specialization", + "Type", + "memberships" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "closure" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "inheritedMembership = inheritedMemberships(Set{}, Set{}, false)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "input", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "directedFeature" + ], + "redefines": [], + "doc": "All features related to this Type by FeatureMemberships that have direction in or inout.", + "doc_refs": [ + "FeatureMemberships", + "Type", + "direction", + "features", + "in", + "inout" + ], + "corpus_elements": 18305, + "corpus_nonempty": 2414, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "input = feature->select(f | let direction: FeatureDirectionKind = directionOf(f) in direction = FeatureDirectionKind::_'in' or direction = FeatureDirectionKind::inout)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 2414 + }, + { + "name": "instantiatedType", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "InstantiationExpression", + "type": "Type", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Type that is being instantiated.", + "doc_refs": [ + "Type" + ], + "corpus_elements": 1605, + "corpus_nonempty": 1605, + "class": "structural" + } + ], + "concrete_carriers": 8, + "also_owned_elsewhere": false, + "rules": { + "InstantiationExpression": "instantiatedType = instantiatedType()" + }, + "corpus_elements": 1605, + "corpus_nonempty": 1605 + }, + { + "name": "interaction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "Interaction", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "association", + "behavior" + ], + "doc": "The Interactions that type this Flow. Interactions are both Associations and Behaviors, which can type Connectors and Steps, respectively.", + "doc_refs": [ + "Associations", + "Behaviors", + "Connectors", + "Flow", + "Interactions", + "Steps" + ], + "corpus_elements": 142, + "corpus_nonempty": 8, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 142, + "corpus_nonempty": 8 + }, + { + "name": "interfaceDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "InterfaceUsage", + "type": "InterfaceDefinition", + "multiplicity": "0..*", + "ordered": false, + "subsets": [], + "redefines": [ + "connectionDefinition" + ], + "doc": "The InterfaceDefinitions that type this InterfaceUsage.", + "doc_refs": [ + "InterfaceDefinitions", + "InterfaceUsage" + ], + "corpus_elements": 37, + "corpus_nonempty": 28, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 37, + "corpus_nonempty": 28 + }, + { + "name": "interfaceEnd", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "InterfaceDefinition", + "type": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "connectionEnd" + ], + "doc": "The PortUsages that are the connectionEnds of this InterfaceDefinition.", + "doc_refs": [ + "InterfaceDefinition", + "PortUsages", + "connectionEnds" + ], + "corpus_elements": 17, + "corpus_nonempty": 17, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 17, + "corpus_nonempty": 17 + }, + { + "name": "intersectingType", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The interpretations of a Type with intersectingTypes are asserted to be those in common among the intersectingTypes, which are the Types derived from the intersectingType of the ownedIntersectings of this Type. For example, a Classifier might be an intersection of Classifiers for people of a particular sex and of a particular nationality. Similarly, a feature for people's children of a particular sex might be the intersection of a Feature for their children and a Classifier for people of that sex (because the interpretations of the children Feature that identify those of that sex are also interpretations of the Classifier for that sex).", + "doc_refs": [ + "Classifier", + "Classifiers", + "Feature", + "Type", + "Types", + "intersectingType", + "intersectingTypes", + "ownedIntersectings" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": true, + "rules": { + "Type": "intersectingType = ownedIntersecting.intersectingType" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "isConjugated", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "Indicates whether this Type has an ownedConjugator.", + "doc_refs": [ + "Type", + "ownedConjugator" + ], + "corpus_elements": 18305, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 18305, + "corpus_nonempty": 91 + }, + { + "name": "isLibraryElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "Whether this Element is contained in the ownership tree of a library model.", + "doc_refs": [], + "corpus_elements": 52148, + "corpus_nonempty": 1093, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "isLibraryElement = libraryNamespace() <> null " + }, + "corpus_elements": 52148, + "corpus_nonempty": 1093 + }, + { + "name": "isModelLevelEvaluable", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Expression", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "Whether this Expression meets the constraints necessary to be evaluated at model level, that is, using metadata within the model.", + "doc_refs": [ + "Expression" + ], + "corpus_elements": 5092, + "corpus_nonempty": 2441, + "class": "structural" + }, + { + "metaclass": "Function", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "Whether this Function can be used as the function of a model-level evaluable InvocationExpression. Certain Functions from the Kernel Functions Library are considered to have isModelLevelEvaluable = true. For all other Functions it is false. Note: See the specification of the KerML concrete syntax notation for Expressions for an identification of which library Functions are model-level evaluable.", + "doc_refs": [ + "Expressions", + "Function", + "Functions", + "InvocationExpression", + "false", + "function" + ], + "corpus_elements": 127, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 43, + "also_owned_elsewhere": false, + "rules": { + "LiteralExpression": "isModelLevelEvaluable = true", + "Expression": "isModelLevelEvaluable = modelLevelEvaluable(Set(Element){})" + }, + "corpus_elements": 5219, + "corpus_nonempty": 2441 + }, + { + "name": "isReference", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "EventOccurrenceUsage", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "isReference" + ], + "doc": "Always true for an EventOccurrenceUsage.", + "doc_refs": [ + "EventOccurrenceUsage" + ], + "corpus_elements": 324, + "corpus_nonempty": 324, + "class": "structural" + }, + { + "metaclass": "Usage", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "Whether this Usage is a referential Usage, that is, it has isComposite = false.", + "doc_refs": [ + "Usage" + ], + "corpus_elements": 8045, + "corpus_nonempty": 5766, + "class": "structural" + }, + { + "metaclass": "ReferenceUsage", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "isReference" + ], + "doc": "Always true for a ReferenceUsage.", + "doc_refs": [ + "ReferenceUsage", + "true" + ], + "corpus_elements": 3074, + "corpus_nonempty": 2844, + "class": "structural" + }, + { + "metaclass": "AttributeUsage", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "isReference" + ], + "doc": "Always true for an AttributeUsage.", + "doc_refs": [ + "AttributeUsage" + ], + "corpus_elements": 869, + "corpus_nonempty": 869, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "isReference = not isComposite" + }, + "corpus_elements": 8045, + "corpus_nonempty": 5766 + }, + { + "name": "itemDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ItemUsage", + "type": "Structure", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "occurrenceDefinition" + ], + "redefines": [], + "doc": "The Structures that are the definitions of this ItemUsage. Nominally, these are ItemDefinitions, but other kinds of Kernel Structures are also allowed, to permit use of Structures from the Kernel Library.", + "doc_refs": [ + "definitions" + ], + "corpus_elements": 1605, + "corpus_nonempty": 1125, + "class": "structural" + } + ], + "concrete_carriers": 8, + "also_owned_elsewhere": false, + "rules": { + "ItemUsage": "itemDefinition = occurrenceDefinition->selectByKind(Structure)" + }, + "corpus_elements": 1605, + "corpus_nonempty": 1125 + }, + { + "name": "loopVariable", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ForLoopActionUsage", + "type": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ownedFeature of this ForLoopActionUsage that acts as the loop variable, which is assigned the successive values of the input sequence on each iteration. It is the ownedFeature that redefines ForLoopAction::var.", + "doc_refs": [ + "ownedFeature" + ], + "corpus_elements": 3, + "corpus_nonempty": 3, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "ForLoopActionUsage": "loopVariable = if ownedFeature->isEmpty() or not ownedFeature->first().oclIsKindOf(ReferenceUsage) then null else ownedFeature->first().oclAsType(ReferenceUsage) endif" + }, + "corpus_elements": 3, + "corpus_nonempty": 3 + }, + { + "name": "lowerBound", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MultiplicityRange", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "bound" + ], + "redefines": [], + "doc": "The Expression whose result provides the lower bound of the MultiplicityRange. If no lowerBound Expression is given, then the lower bound shall have the same value as the upper bound, unless the upper bound is unbounded (*), in which case the lower bound shall be 0.", + "doc_refs": [ + "Expression", + "MultiplicityRange", + "lowerBound" + ], + "corpus_elements": 576, + "corpus_nonempty": 116, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "MultiplicityRange": "lowerBound = let ownedExpressions : Sequence(Expression) = ownedMember->selectByKind(Expression) in if ownedExpressions->size() < 2 then null else ownedExpressions->first() endif" + }, + "corpus_elements": 576, + "corpus_nonempty": 116 + }, + { + "name": "mayTimeVary", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Boolean", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "isVariable" + ], + "doc": "Whether this Usage may be time varying (that is, whether it is featured by the snapshots of its owningType, rather than being featured by the owningType itself). However, if isConstant is also true, then the value of the Usage is nevertheless constant over the entire duration of an instance of its owningType (that is, it has the same value on all snapshots). The property mayTimeVary redefines the KerML property Feature::isVariable, making it derived. The property isConstant is inherited from Feature.", + "doc_refs": [ + "Feature", + "Usage", + "isConstant", + "mayTimeVary", + "owningType" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1212, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "mayTimeVary = owningType <> null and owningType.specializesFromLibrary('Occurrences::Occurrence') and not ( isPortion or specializesFromLibrary('Links::SelfLink') or specializesFromLibrary('Occurrences::HappensLink') or isComposite and specializesFromLibrary('Actions::Action') )" + }, + "corpus_elements": 8045, + "corpus_nonempty": 1212 + }, + { + "name": "member", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Element", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The set of all member Elements of this Namespace, which are the memberElements of all memberships of the Namespace.", + "doc_refs": [ + "Elements", + "Namespace", + "memberElements", + "memberships" + ], + "corpus_elements": 19037, + "corpus_nonempty": 12491, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": false, + "rules": { + "Namespace": "member = membership.memberElement" + }, + "corpus_elements": 19037, + "corpus_nonempty": 12491 + }, + { + "name": "memberElementId", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Membership", + "type": "String", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The elementId of the memberElement.", + "doc_refs": [ + "elementId", + "memberElement" + ], + "corpus_elements": 21066, + "corpus_nonempty": 21066, + "class": "structural" + } + ], + "concrete_carriers": 20, + "also_owned_elsewhere": false, + "rules": { + "Membership": "memberElementId = memberElement.elementId" + }, + "corpus_elements": 21066, + "corpus_nonempty": 21066 + }, + { + "name": "membership", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Membership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "All Memberships in this Namespace, including (at least) the union of ownedMemberships and importedMemberships.", + "doc_refs": [ + "Memberships", + "Namespace", + "importedMemberships", + "ownedMemberships" + ], + "corpus_elements": 19037, + "corpus_nonempty": 12491, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 19037, + "corpus_nonempty": 12491 + }, + { + "name": "membershipOwningNamespace", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Membership", + "type": "Namespace", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "membershipNamespace", + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "The Namespace of which the memberElement becomes a member due to this Membership.", + "doc_refs": [ + "Membership", + "Namespace", + "member", + "memberElement" + ], + "corpus_elements": 21066, + "corpus_nonempty": 21066, + "class": "structural" + } + ], + "concrete_carriers": 20, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 21066, + "corpus_nonempty": 21066 + }, + { + "name": "metaclass", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MetadataFeature", + "type": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "type" + ], + "redefines": [], + "doc": "The type of this MetadataFeature, which must be a Metaclass.", + "doc_refs": [ + "Metaclass", + "MetadataFeature", + "type" + ], + "corpus_elements": 179, + "corpus_nonempty": 179, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "MetadataFeature": "metaclass = let metaclassTypes : Sequence(Type) = type->selectByKind(Metaclass) in if metaclassTypes->isEmpty() then null else metaClassTypes->first() endif" + }, + "corpus_elements": 179, + "corpus_nonempty": 179 + }, + { + "name": "metadataDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MetadataUsage", + "type": "Metaclass", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "itemDefinition", + "metaclass" + ], + "doc": "The MetadataDefinition that is the definition of this MetadataUsage.", + "doc_refs": [ + "MetadataDefinition", + "MetadataUsage", + "definition" + ], + "corpus_elements": 179, + "corpus_nonempty": 179, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 179, + "corpus_nonempty": 179 + }, + { + "name": "multiplicity", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Multiplicity", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "An ownedMember of this Type that is a Multiplicity, which constraints the cardinality of the Type. If there is no such ownedMember, then the cardinality of this Type is constrained by all the Multiplicity constraints applicable to any direct supertypes.", + "doc_refs": [ + "Multiplicity", + "Type", + "ownedMember" + ], + "corpus_elements": 18305, + "corpus_nonempty": 576, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "multiplicity = let ownedMultiplicities: Sequence(Multiplicity) = ownedMember->selectByKind(Multiplicity) in if ownedMultiplicities->isEmpty() then null else ownedMultiplicities->first() endif" + }, + "corpus_elements": 18305, + "corpus_nonempty": 576 + }, + { + "name": "name", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "String", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The name to be used for this Element during name resolution within its owningNamespace. This is derived using the effectiveName() operation. By default, it is the same as the declaredName, but this is overridden for certain kinds of Elements to compute a name even when the declaredName is null.", + "doc_refs": [ + "Element", + "Elements", + "declaredName", + "name", + "owningNamespace" + ], + "corpus_elements": 52148, + "corpus_nonempty": 9724, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "name = effectiveName()" + }, + "corpus_elements": 52148, + "corpus_nonempty": 9724 + }, + { + "name": "nestedAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedOccurrence" + ], + "redefines": [], + "doc": "The ActionUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "ActionUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 379, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedAction = nestedUsage->selectByKind(ActionUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 379 + }, + { + "name": "nestedAllocation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedConnection" + ], + "redefines": [], + "doc": "The AllocationUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "AllocationUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 9, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedAllocation = nestedUsage->selectByKind(AllocationUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 9 + }, + { + "name": "nestedAnalysisCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedCase" + ], + "redefines": [], + "doc": "The AnalysisCaseUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "AnalysisCaseUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 7, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedAnalysisCase = nestedUsage->selectByKind(AnalysisCaseUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 7 + }, + { + "name": "nestedAttribute", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The code>AttributeUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 217, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedAttribute = nestedUsage->selectByKind(AttributeUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 217 + }, + { + "name": "nestedCalculation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedAction" + ], + "redefines": [], + "doc": "The CalculationUsage that are nestedUsages of this Usage.", + "doc_refs": [ + "CalculationUsage", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 27, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedCalculation = nestedUsage->selectByKind(CalculationUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 27 + }, + { + "name": "nestedCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedCalculation" + ], + "redefines": [], + "doc": "The CaseUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "CaseUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 14, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedCase = nestedUsage->selectByKind(CaseUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 14 + }, + { + "name": "nestedConcern", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "nestedRequirement" + ], + "redefines": [], + "doc": "The ConcernUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "ConcernUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 3, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedConcern = nestedUsage->selectByKind(ConcernUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 3 + }, + { + "name": "nestedConnection", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The ConnectorAsUsages that are nestedUsages of this Usage. Note that this list includes BindingConnectorAsUsages, SuccessionAsUsages, and FlowConnectionUsages because these are ConnectorAsUsages even though they are not ConnectionUsages.", + "doc_refs": [ + "BindingConnectorAsUsages", + "ConnectionUsages", + "ConnectorAsUsages", + "FlowConnectionUsages", + "SuccessionAsUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 169, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedConnection = nestedUsage->selectByKind(ConnectorAsUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 169 + }, + { + "name": "nestedConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedOccurrence" + ], + "redefines": [], + "doc": "The ConstraintUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "ConstraintUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 113, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedConstraint = nestedUsage->selectByKind(ConstraintUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 113 + }, + { + "name": "nestedEnumeration", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Usage", + "type": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedAttribute" + ], + "redefines": [], + "doc": "The code>EnumerationUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "ownedNested = nestedUsage->selectByKind(EnumerationUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 0 + }, + { + "name": "nestedFlow", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Usage", + "type": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "nestedConnection" + ], + "redefines": [], + "doc": "The code>FlowUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedFlow = nestedUsage->selectByKind(FlowConnectionUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 0 + }, + { + "name": "nestedInterface", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedConnection" + ], + "redefines": [], + "doc": "The InterfaceUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "InterfaceUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1290, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedInterface = nestedUsage->selectByKind(ReferenceUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 1290 + }, + { + "name": "nestedItem", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedOccurrence" + ], + "redefines": [], + "doc": "The ItemUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "ItemUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 407, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedItem = nestedUsage->selectByKind(ItemUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 407 + }, + { + "name": "nestedMetadata", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Usage", + "type": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedItem" + ], + "redefines": [], + "doc": "The MetadataUsages that are nestedUsages of this of this Usage.", + "doc_refs": [ + "MetadataUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedMetadata = nestedUsage->selectByKind(MetadataUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 0 + }, + { + "name": "nestedOccurrence", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The OccurrenceUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "OccurrenceUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1004, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedOccurrence = nestedUsage->selectByKind(OccurrenceUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 1004 + }, + { + "name": "nestedPart", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedItem" + ], + "redefines": [], + "doc": "The PartUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "PartUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 342, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedPart = nestedUsage->selectByKind(PartUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 342 + }, + { + "name": "nestedPort", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The PortUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "PortUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 154, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedPort = nestedUsage->selectByKind(PortUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 154 + }, + { + "name": "nestedReference", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The ReferenceUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "ReferenceUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1290, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedReference = nestedUsage->selectByKind(ReferenceUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 1290 + }, + { + "name": "nestedRendering", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedPart" + ], + "redefines": [], + "doc": "The RenderingUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "RenderingUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 8, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedRendering = nestedUsage->selectByKind(RenderingUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 8 + }, + { + "name": "nestedRequirement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedConstraint" + ], + "redefines": [], + "doc": "The RequirementUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "RequirementUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 57, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedRequirement = nestedUsage->selectByKind(RequirementUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 57 + }, + { + "name": "nestedState", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedAction" + ], + "redefines": [], + "doc": "The StateUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "StateUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 64, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedState = nestedUsage->selectByKind(StateUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 64 + }, + { + "name": "nestedTransition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "nestedUsage" + ], + "redefines": [], + "doc": "The TransitionUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "TransitionUsages", + "Usage", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 32, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedTransition = nestedUsage->selectByKind(TransitionUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 32 + }, + { + "name": "nestedUsage", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature", + "usage" + ], + "redefines": [], + "doc": "The Usages that are ownedFeatures of this Usage.", + "doc_refs": [ + "Usage", + "Usages", + "ownedFeatures" + ], + "corpus_elements": 8045, + "corpus_nonempty": 2207, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedUsage = ownedFeature->selectByKind(Usage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 2207 + }, + { + "name": "nestedUseCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedCase" + ], + "redefines": [], + "doc": "The UseCaseUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "UseCaseUsages", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 6, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedUseCase = nestedUsage->selectByKind(UseCaseUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 6 + }, + { + "name": "nestedVerificationCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedCase" + ], + "redefines": [], + "doc": "The VerificationCaseUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "VerificationCaseUsages", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedVerificationCase = nestedUsage->selectByKind(VerificationCaseUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 1 + }, + { + "name": "nestedView", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedPart" + ], + "redefines": [], + "doc": "The ViewUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "ViewUsages", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 3, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedView = nestedUsage->selectByKind(ViewUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 3 + }, + { + "name": "nestedViewpoint", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Usage", + "type": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedRequirement" + ], + "redefines": [], + "doc": "The ViewpointUsages that are nestedUsages of this Usage.", + "doc_refs": [ + "Usage", + "ViewpointUsages", + "nestedUsages" + ], + "corpus_elements": 8045, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": { + "Usage": "nestedViewpoint = nestedUsage->selectByKind(ViewpointUsage)" + }, + "corpus_elements": 8045, + "corpus_nonempty": 0 + }, + { + "name": "objectiveRequirement", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "CaseUsage", + "type": "RequirementUsage", + "multiplicity": "0..1", + "ordered": true, + "subsets": [ + "usage" + ], + "redefines": [], + "doc": "The RequirementUsage representing the objective of this CaseUsage.", + "doc_refs": [ + "CaseUsage", + "RequirementUsage" + ], + "corpus_elements": 65, + "corpus_nonempty": 9, + "class": "inheritance-aware" + }, + { + "metaclass": "CaseDefinition", + "type": "RequirementUsage", + "multiplicity": "0..1", + "ordered": true, + "subsets": [ + "usage" + ], + "redefines": [], + "doc": "The RequirementUsage representing the objective of this CaseDefinition.", + "doc_refs": [ + "CaseDefinition", + "RequirementUsage" + ], + "corpus_elements": 30, + "corpus_nonempty": 17, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 9, + "also_owned_elsewhere": false, + "rules": { + "CaseUsage": "objectiveRequirement = let objectives: OrderedSet(RequirementUsage) = featureMembership-> selectByKind(ObjectiveMembership). ownedRequirement in if objectives->isEmpty() then null else objectives->first().ownedObjectiveRequirement endif", + "CaseDefinition": "objectiveRequirement = let objectives: OrderedSet(RequirementUsage) = featureMembership-> selectByKind(ObjectiveMembership). ownedRequirement in if objectives->isEmpty() then null else objectives->first().ownedObjectiveRequirement endif" + }, + "corpus_elements": 95, + "corpus_nonempty": 26 + }, + { + "name": "occurrenceDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OccurrenceUsage", + "type": "Class", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "definition" + ], + "doc": "The Classes that are the types of this OccurrenceUsage. Nominally, these are OccurrenceDefinitions, but other kinds of kernel Classes are also allowed, to permit use of Classes from the Kernel Model Libraries.", + "doc_refs": [ + "Classes", + "OccurrenceDefinitions", + "OccurrenceUsage" + ], + "corpus_elements": 3627, + "corpus_nonempty": 1918, + "class": "structural" + } + ], + "concrete_carriers": 41, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 3627, + "corpus_nonempty": 1918 + }, + { + "name": "originalPortDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConjugatedPortDefinition", + "type": "PortDefinition", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "owningNamespace" + ], + "doc": "The original PortDefinition for this ConjugatedPortDefinition, which is the owningNamespace of the ConjugatedPortDefinition.", + "doc_refs": [ + "ConjugatedPortDefinition", + "PortDefinition", + "owningNamespace" + ], + "corpus_elements": 91, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": true, + "rules": {}, + "corpus_elements": 91, + "corpus_nonempty": 91 + }, + { + "name": "output", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "directedFeature" + ], + "redefines": [], + "doc": "All features related to this Type by FeatureMemberships that have direction out or inout.", + "doc_refs": [ + "FeatureMemberships", + "Type", + "direction", + "features", + "inout", + "out" + ], + "corpus_elements": 18305, + "corpus_nonempty": 584, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "output = feature->select(f | let direction: FeatureDirectionKind = directionOf(f) in direction = FeatureDirectionKind::out or direction = FeatureDirectionKind::inout)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 584 + }, + { + "name": "ownedAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ActionUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedOccurrence" + ], + "redefines": [], + "doc": "The ActionUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "ActionUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 73, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedAction = ownedUsage->selectByKind(ActionUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 73 + }, + { + "name": "ownedActorParameter", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ActorMembership", + "type": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberParameter" + ], + "doc": "The PartUsage specifying the actor.", + "doc_refs": [ + "PartUsage" + ], + "corpus_elements": 42, + "corpus_nonempty": 42, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 42, + "corpus_nonempty": 42 + }, + { + "name": "ownedAllocation", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Definition", + "type": "AllocationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedConnection" + ], + "redefines": [], + "doc": "The AllocationUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "AllocationUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedAllocation = ownedUsage->selectByKind(AllocationUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 0 + }, + { + "name": "ownedAnalysisCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "AnalysisCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedCase" + ], + "redefines": [], + "doc": "The AnalysisCaseUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "AnalysisCaseUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedAnalysisCase = ownedUsage->selectByKind(AnalysisCaseUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 2 + }, + { + "name": "ownedAnnotatingElement", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "Annotation", + "type": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "annotatingElement", + "ownedRelatedElement" + ], + "redefines": [], + "doc": "The annotatingElement of this Annotation, when it is an ownedRelatedElement.", + "doc_refs": [ + "Annotation", + "annotatingElement", + "ownedRelatedElement" + ], + "corpus_elements": 19, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "Annotation": "ownedAnnotatingElement = let ownedAnnotatingElements : Sequence(AnnotatingElement) = ownedRelatedElement->selectByKind(AnnotatingElement) in if ownedAnnotatingElements->isEmpty() then null else ownedAnnotatingElements->first() endif" + }, + "corpus_elements": 19, + "corpus_nonempty": 0 + }, + { + "name": "ownedAnnotatingRelationship", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AnnotatingElement", + "type": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "annotation", + "ownedRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this AnnotatingElement that are Annotations, for which this AnnotatingElement is the annotatingElement.", + "doc_refs": [ + "AnnotatingElement", + "Annotations", + "annotatingElement", + "ownedRelationships" + ], + "corpus_elements": 632, + "corpus_nonempty": 16, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": { + "AnnotatingElement": "ownedAnnotatingRelationship = ownedRelationship-> selectByKind(Annotation)-> select(a | a.annotatedElement <> self)" + }, + "corpus_elements": 632, + "corpus_nonempty": 16 + }, + { + "name": "ownedAnnotation", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "Element", + "type": "Annotation", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "annotation", + "ownedRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Element that are Annotations, for which this Element is the annotatedElement.", + "doc_refs": [ + "Annotations", + "Element", + "annotatedElement", + "ownedRelationships" + ], + "corpus_elements": 52148, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "ownedAnnotation = ownedRelationship-> selectByKind(Annotation)-> select(a | a.annotatedElement = self)" + }, + "corpus_elements": 52148, + "corpus_nonempty": 0 + }, + { + "name": "ownedAttribute", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "AttributeUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The AttributeUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "AttributeUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 219, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedAttribute = ownedUsage->selectByKind(AttributeUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 219 + }, + { + "name": "ownedCalculation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "CalculationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedAction" + ], + "redefines": [], + "doc": "The CalculationUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "CalculationUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 7, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedCalculation = ownedUsage->selectByKind(CalculationUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 7 + }, + { + "name": "ownedCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "CaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedCalculation" + ], + "redefines": [], + "doc": "The code>CaseUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 5, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedCase = ownedUsage->selectByKind(CaseUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 5 + }, + { + "name": "ownedConcern", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FramedConcernMembership", + "type": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedConstraint" + ], + "doc": "The ConcernUsage that is the ownedConstraint of this FramedConcernMembership.", + "doc_refs": [ + "ConcernUsage", + "FramedConcernMembership", + "ownedConstraint" + ], + "corpus_elements": 6, + "corpus_nonempty": 6, + "class": "structural" + }, + { + "metaclass": "Definition", + "type": "ConcernUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedRequirement" + ], + "redefines": [], + "doc": "The ConcernUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "ConcernUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 27, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedConcern = ownedUsage->selectByKind(ConcernUsage)" + }, + "corpus_elements": 1360, + "corpus_nonempty": 8 + }, + { + "name": "ownedConjugator", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Conjugation", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "conjugator", + "ownedRelationship" + ], + "redefines": [], + "doc": "A Conjugation owned by this Type for which the Type is the originalType.", + "doc_refs": [ + "Conjugation", + "Type", + "originalType" + ], + "corpus_elements": 18305, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedConjugator = let ownedConjugators: Sequence(Conjugator) = ownedRelationship->selectByKind(Conjugation) in if ownedConjugators->isEmpty() then null else ownedConjugators->at(1) endif" + }, + "corpus_elements": 18305, + "corpus_nonempty": 91 + }, + { + "name": "ownedConnection", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ConnectorAsUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The ConnectorAsUsages that are ownedUsages of this Definition. Note that this list includes BindingConnectorAsUsages, SuccessionAsUsages, and FlowUsages because these are ConnectorAsUsages even though they are not ConnectionUsages.", + "doc_refs": [ + "BindingConnectorAsUsages", + "ConnectionUsages", + "ConnectorAsUsages", + "Definition", + "FlowUsages", + "SuccessionAsUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 42, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedConnection = ownedUsage->selectByKind(ConnectorAsUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 42 + }, + { + "name": "ownedConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementConstraintMembership", + "type": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The ConstraintUsage that is the ownedMemberFeature of this RequirementConstraintMembership.", + "doc_refs": [ + "ConstraintUsage", + "RequirementConstraintMembership", + "ownedMemberFeature" + ], + "corpus_elements": 66, + "corpus_nonempty": 66, + "class": "structural" + }, + { + "metaclass": "Definition", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedOccurrence" + ], + "redefines": [], + "doc": "The ConstraintUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "ConstraintUsages", + "Definition", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 61, + "class": "structural" + } + ], + "concrete_carriers": 29, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedConstraint = ownedUsage->selectByKind(ConstraintUsage)" + }, + "corpus_elements": 1420, + "corpus_nonempty": 127 + }, + { + "name": "ownedCrossSubsetting", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "CrossSubsetting", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedSubsetting" + ], + "redefines": [], + "doc": "The one ownedSubsetting of this Feature, if any, that is a CrossSubsetting}, for which the Feature is the crossingFeature.", + "doc_refs": [ + "Feature", + "crossingFeature", + "ownedSubsetting" + ], + "corpus_elements": 16951, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedCrossSubsetting = let crossSubsettings: Sequence(CrossSubsetting) = ownedSubsetting->selectByKind(CrossSubsetting) in if crossSubsettings->isEmpty() then null else crossSubsettings->first() endif" + }, + "corpus_elements": 16951, + "corpus_nonempty": 2 + }, + { + "name": "ownedDifferencing", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Differencing", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Type that are Differencings, having this Type as their typeDifferenced.", + "doc_refs": [ + "Differencings", + "Type", + "ownedRelationships", + "typeDifferenced" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedDifferencing = ownedRelationship->selectByKind(Differencing)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "ownedDisjoining", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "Type", + "type": "Disjoining", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "disjoiningTypeDisjoining", + "ownedRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Type that are Disjoinings, for which the Type is the typeDisjoined Type.", + "doc_refs": [ + "Disjoinings", + "Type", + "ownedRelationships", + "typeDisjoined" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedDisjoining = ownedRelationship->selectByKind(Disjoining)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "ownedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "Element", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Elements owned by this Element, derived as the ownedRelatedElements of the ownedRelationships of this Element.", + "doc_refs": [], + "corpus_elements": 52148, + "corpus_nonempty": 11182, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "ownedElement = ownedRelationship.ownedRelatedElement" + }, + "corpus_elements": 52148, + "corpus_nonempty": 11182 + }, + { + "name": "ownedEndFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "endFeature", + "ownedFeature" + ], + "redefines": [], + "doc": "All endFeatures of this Type that are ownedFeatures.", + "doc_refs": [ + "Type", + "endFeatures", + "ownedFeatures" + ], + "corpus_elements": 18305, + "corpus_nonempty": 716, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedEndFeature = ownedFeature->select(isEnd)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 716 + }, + { + "name": "ownedEnumeration", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Definition", + "type": "EnumerationUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedAttribute" + ], + "redefines": [], + "doc": "The EnumerationUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "EnumerationUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedEnumeration = ownedUsage->selectByKind(EnumerationUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 0 + }, + { + "name": "ownedFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The ownedMemberFeatures of the ownedFeatureMemberships of this Type.", + "doc_refs": [ + "Type", + "ownedFeatureMemberships", + "ownedMemberFeatures" + ], + "corpus_elements": 18305, + "corpus_nonempty": 4942, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedFeature = ownedFeatureMembership.ownedMemberFeature" + }, + "corpus_elements": 18305, + "corpus_nonempty": 4942 + }, + { + "name": "ownedFeatureChaining", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "FeatureChaining", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Feature that are FeatureChainings, for which the Feature will be the featureChained.", + "doc_refs": [ + "Feature", + "FeatureChainings", + "featureChained", + "ownedRelationships" + ], + "corpus_elements": 16951, + "corpus_nonempty": 588, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedFeatureChaining = ownedRelationship->selectByKind(FeatureChaining)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 588 + }, + { + "name": "ownedFeatureInverting", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Feature", + "type": "FeatureInverting", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "invertingFeatureInverting", + "ownedRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Feature that are FeatureInvertings and for which the Feature is the featureInverted.", + "doc_refs": [ + "Feature", + "FeatureInvertings", + "featureInverted", + "ownedRelationships" + ], + "corpus_elements": 16951, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedFeatureInverting = ownedRelationship->selectByKind(FeatureInverting)-> select(fi | fi.featureInverted = self)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 0 + }, + { + "name": "ownedFeatureMembership", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "FeatureMembership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "featureMembership", + "ownedMembership" + ], + "redefines": [], + "doc": "The ownedMemberships of this Type that are FeatureMemberships, for which the Type is the owningType. Each such FeatureMembership identifies an ownedFeature of the Type.", + "doc_refs": [ + "FeatureMembership", + "FeatureMemberships", + "Type", + "ownedFeature", + "ownedMemberships", + "owningType" + ], + "corpus_elements": 18305, + "corpus_nonempty": 4942, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedFeatureMembership = ownedRelationship->selectByKind(FeatureMembership)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 4942 + }, + { + "name": "ownedFlow", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Definition", + "type": "FlowUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedConnection" + ], + "redefines": [], + "doc": "The FlowUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "FlowUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedFlow = ownedUsage->selectByKind(FlowConnectionUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 0 + }, + { + "name": "ownedImport", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Import", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Namespace that are Imports, for which the Namespace is the importOwningNamespace.", + "doc_refs": [ + "Imports", + "Namespace", + "importOwningNamespace", + "ownedRelationships" + ], + "corpus_elements": 19037, + "corpus_nonempty": 279, + "class": "structural" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": false, + "rules": { + "Namespace": "ownedImport = ownedRelationship->selectByKind(Import)" + }, + "corpus_elements": 19037, + "corpus_nonempty": 279 + }, + { + "name": "ownedInterface", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "InterfaceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedConnection" + ], + "redefines": [], + "doc": "The InterfaceUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "InterfaceUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 265, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedInterface = ownedUsage->selectByKind(ReferenceUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 265 + }, + { + "name": "ownedIntersecting", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Intersecting", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Type that are Intersectings, have the Type as their typeIntersected.", + "doc_refs": [ + "Intersectings", + "Type", + "ownedRelationships", + "typeIntersected" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedRelationship->selectByKind(Intersecting)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "ownedItem", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ItemUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedOccurrence" + ], + "redefines": [], + "doc": "The ItemUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "ItemUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 151, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedItem = ownedUsage->selectByKind(ItemUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 151 + }, + { + "name": "ownedMember", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Element", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The owned members of this Namespace, which are the ownedMemberElements of the ownedMemberships of the Namespace.", + "doc_refs": [ + "Namespace", + "members", + "ownedMemberElements", + "ownedMemberships" + ], + "corpus_elements": 19037, + "corpus_nonempty": 10764, + "class": "structural" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": false, + "rules": { + "Namespace": "ownedMember = ownedMembership->selectByKind(OwningMembership).ownedMemberElement" + }, + "corpus_elements": 19037, + "corpus_nonempty": 10764 + }, + { + "name": "ownedMemberElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OwningMembership", + "type": "Element", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "ownedRelatedElement" + ], + "redefines": [ + "memberElement" + ], + "doc": "The Element that becomes an ownedMember of the membershipOwningNamespace due to this OwningMembership.", + "doc_refs": [ + "Element", + "OwningMembership", + "membershipOwningNamespace", + "ownedMember" + ], + "corpus_elements": 18728, + "corpus_nonempty": 18728, + "class": "structural" + } + ], + "concrete_carriers": 19, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 18728, + "corpus_nonempty": 18728 + }, + { + "name": "ownedMemberElementId", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OwningMembership", + "type": "String", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "memberElementId" + ], + "doc": "The elementId of the ownedMemberElement.", + "doc_refs": [ + "elementId", + "ownedMemberElement" + ], + "corpus_elements": 18728, + "corpus_nonempty": 18728, + "class": "structural" + } + ], + "concrete_carriers": 19, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 18728, + "corpus_nonempty": 18728 + }, + { + "name": "ownedMemberFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureMembership", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberElement" + ], + "doc": "The Feature that this FeatureMembership relates to its owningType, making it an ownedFeature of the owningType.", + "doc_refs": [ + "Feature", + "FeatureMembership", + "ownedFeature", + "owningType" + ], + "corpus_elements": 10203, + "corpus_nonempty": 10203, + "class": "structural" + }, + { + "metaclass": "EndFeatureMembership", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "", + "doc_refs": [], + "corpus_elements": 1420, + "corpus_nonempty": 1420, + "class": "structural" + } + ], + "concrete_carriers": 15, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 10203, + "corpus_nonempty": 10203 + }, + { + "name": "ownedMemberName", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OwningMembership", + "type": "String", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "memberName" + ], + "doc": "The name of the ownedMemberElement.", + "doc_refs": [ + "name", + "ownedMemberElement" + ], + "corpus_elements": 18728, + "corpus_nonempty": 9230, + "class": "structural" + } + ], + "concrete_carriers": 19, + "also_owned_elsewhere": false, + "rules": { + "OwningMembership": "ownedMemberName = ownedMemberElement.name" + }, + "corpus_elements": 18728, + "corpus_nonempty": 9230 + }, + { + "name": "ownedMemberParameter", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ParameterMembership", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The Feature that is identified as a parameter by this ParameterMembership.", + "doc_refs": [ + "Feature", + "ParameterMembership", + "parameter" + ], + "corpus_elements": 3432, + "corpus_nonempty": 3432, + "class": "structural" + } + ], + "concrete_carriers": 5, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 3432, + "corpus_nonempty": 3432 + }, + { + "name": "ownedMemberShortName", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "OwningMembership", + "type": "String", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "memberShortName" + ], + "doc": "The shortName of the ownedMemberElement.", + "doc_refs": [ + "ownedMemberElement", + "shortName" + ], + "corpus_elements": 18728, + "corpus_nonempty": 75, + "class": "structural" + } + ], + "concrete_carriers": 19, + "also_owned_elsewhere": false, + "rules": { + "OwningMembership": "ownedMemberShortName = ownedMemberElement.shortName" + }, + "corpus_elements": 18728, + "corpus_nonempty": 75 + }, + { + "name": "ownedMembership", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Namespace", + "type": "Membership", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "membership", + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Namespace that are Memberships, for which the Namespace is the membershipOwningNamespace.", + "doc_refs": [ + "Memberships", + "Namespace", + "membershipOwningNamespace", + "ownedRelationships" + ], + "corpus_elements": 19037, + "corpus_nonempty": 12491, + "class": "structural" + } + ], + "concrete_carriers": 120, + "also_owned_elsewhere": false, + "rules": { + "Namespace": "ownedMembership = ownedRelationship->selectByKind(Membership)" + }, + "corpus_elements": 19037, + "corpus_nonempty": 12491 + }, + { + "name": "ownedMetadata", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Definition", + "type": "MetadataUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedItem" + ], + "redefines": [], + "doc": "The MetadataUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "MetadataUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedMetadata = ownedUsage->selectByKind(MetadataUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 0 + }, + { + "name": "ownedObjectiveRequirement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ObjectiveMembership", + "type": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The RequirementUsage that is the ownedMemberFeature of this RequirementUsage.", + "doc_refs": [ + "ownedMemberFeature" + ], + "corpus_elements": 26, + "corpus_nonempty": 26, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 26, + "corpus_nonempty": 26 + }, + { + "name": "ownedOccurrence", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "OccurrenceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The OccurrenceUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "OccurrenceUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 301, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedOccurrence = ownedUsage->selectByKind(OccurrenceUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 301 + }, + { + "name": "ownedPart", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedItem" + ], + "redefines": [], + "doc": "The PartUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "PartUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 107, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedPart = ownedUsage->selectByKind(PartUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 107 + }, + { + "name": "ownedPort", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "PortUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The PortUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "PortUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 76, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedPort = ownedUsage->selectByKind(PortUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 76 + }, + { + "name": "ownedPortConjugator", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConjugatedPortDefinition", + "type": "PortConjugation", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedConjugator" + ], + "doc": "The PortConjugation that is the ownedConjugator of this ConjugatedPortDefinition, linking it to its originalPortDefinition.", + "doc_refs": [ + "ConjugatedPortDefinition", + "PortConjugation", + "originalPortDefinition", + "ownedConjugator" + ], + "corpus_elements": 91, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 91, + "corpus_nonempty": 91 + }, + { + "name": "ownedRedefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Redefinition", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedSubsetting" + ], + "redefines": [], + "doc": "The ownedSubsettings of this Feature that are Redefinitions, for which the Feature is the redefiningFeature.", + "doc_refs": [ + "Feature", + "Redefinitions", + "ownedSubsettings", + "redefiningFeature" + ], + "corpus_elements": 16951, + "corpus_nonempty": 1294, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedRedefinition = ownedSubsetting->selectByKind(Redefinition)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 1294 + }, + { + "name": "ownedReference", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ReferenceUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The ReferenceUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "ReferenceUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 265, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedReference = ownedUsage->selectByKind(ReferenceUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 265 + }, + { + "name": "ownedReferenceSubsetting", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "ReferenceSubsetting", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedSubsetting" + ], + "redefines": [], + "doc": "The one ownedSubsetting of this Feature, if any, that is a ReferenceSubsetting, for which the Feature is the referencingFeature.", + "doc_refs": [ + "Feature", + "ReferenceSubsetting", + "ownedSubsetting", + "referencingFeature" + ], + "corpus_elements": 16951, + "corpus_nonempty": 1164, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedReferenceSubsetting = let referenceSubsettings : OrderedSet(ReferenceSubsetting) = ownedSubsetting->selectByKind(ReferenceSubsetting) in if referenceSubsettings->isEmpty() then null else referenceSubsettings->first() endif" + }, + "corpus_elements": 16951, + "corpus_nonempty": 1164 + }, + { + "name": "ownedRendering", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedPart" + ], + "redefines": [], + "doc": "The RenderingUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "RenderingUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 3, + "class": "structural" + }, + { + "metaclass": "ViewRenderingMembership", + "type": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The owned RenderingUsage that is either itself the referencedRendering or subsets the referencedRendering.", + "doc_refs": [ + "RenderingUsage", + "referencedRendering" + ], + "corpus_elements": 11, + "corpus_nonempty": 11, + "class": "structural" + } + ], + "concrete_carriers": 27, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedRendering = ownedUsage->selectByKind(RenderingUsage)" + }, + "corpus_elements": 1365, + "corpus_nonempty": 14 + }, + { + "name": "ownedRequirement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedConstraint" + ], + "redefines": [], + "doc": "The RequirementUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "RequirementUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 23, + "class": "structural" + }, + { + "metaclass": "RequirementVerificationMembership", + "type": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedConstraint" + ], + "doc": "The owned RequirementUsage that acts as the ownedConstraint for this RequirementVerificationMembership. This will either be the verifiedRequirement, or it will subset the verifiedRequirement.", + "doc_refs": [ + "RequirementUsage", + "RequirementVerificationMembership", + "ownedConstraint", + "verifiedRequirement" + ], + "corpus_elements": 6, + "corpus_nonempty": 6, + "class": "structural" + } + ], + "concrete_carriers": 27, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedRequirement = ownedUsage->selectByKind(RequirementUsage)" + }, + "corpus_elements": 1360, + "corpus_nonempty": 29 + }, + { + "name": "ownedResultExpression", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ResultExpressionMembership", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The Expression that provides the result for the owner of the ResultExpressionMembership.", + "doc_refs": [ + "Expression", + "ResultExpressionMembership" + ], + "corpus_elements": 105, + "corpus_nonempty": 105, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 105, + "corpus_nonempty": 105 + }, + { + "name": "ownedSpecialization", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Type", + "type": "Specialization", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "specialization" + ], + "redefines": [], + "doc": "The ownedRelationships of this Type that are Specializations, for which the Type is the specific Type.", + "doc_refs": [ + "Specializations", + "Type", + "ownedRelationships", + "specific" + ], + "corpus_elements": 18305, + "corpus_nonempty": 7923, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedSpecialization = ownedRelationship->selectByKind(Specialization)-> select(s | s.special = self) " + }, + "corpus_elements": 18305, + "corpus_nonempty": 7923 + }, + { + "name": "ownedStakeholderParameter", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "StakeholderMembership", + "type": "PartUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberParameter" + ], + "doc": "The PartUsage specifying the stakeholder.", + "doc_refs": [ + "PartUsage" + ], + "corpus_elements": 7, + "corpus_nonempty": 7, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 7, + "corpus_nonempty": 7 + }, + { + "name": "ownedState", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedAction" + ], + "redefines": [], + "doc": "The StateUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "StateUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 19, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedState = ownedUsage->selectByKind(StateUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 19 + }, + { + "name": "ownedSubclassification", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Classifier", + "type": "Subclassification", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedSpecialization" + ], + "redefines": [], + "doc": "The ownedSpecializations of this Classifier that are Subclassifications, for which this Classifier is the subclassifier.", + "doc_refs": [ + "Classifier", + "Subclassifications", + "ownedSpecializations", + "subclassifier" + ], + "corpus_elements": 1354, + "corpus_nonempty": 1150, + "class": "structural" + } + ], + "concrete_carriers": 37, + "also_owned_elsewhere": false, + "rules": { + "Classifier": "ownedSubclassification = ownedSpecialization->selectByKind(Subclassification)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 1150 + }, + { + "name": "ownedSubjectParameter", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "SubjectMembership", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberParameter" + ], + "doc": "The UsageownedMemberParameter of this SubjectMembership.", + "doc_refs": [ + "SubjectMembership", + "ownedMemberParameter" + ], + "corpus_elements": 122, + "corpus_nonempty": 122, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 122, + "corpus_nonempty": 122 + }, + { + "name": "ownedSubsetting", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Subsetting", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedSpecialization", + "subsetting" + ], + "redefines": [], + "doc": "The ownedSpecializations of this Feature that are Subsettings, for which the Feature is the subsettingFeature.", + "doc_refs": [ + "Feature", + "Subsettings", + "ownedSpecializations", + "subsettingFeature" + ], + "corpus_elements": 16951, + "corpus_nonempty": 5513, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedSubsetting = ownedSpecialization->selectByKind(Subsetting)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 5513 + }, + { + "name": "ownedTransition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "TransitionUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedUsage" + ], + "redefines": [], + "doc": "The TransitionUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "TransitionUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 6, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedTransition = ownedUsage->selectByKind(TransitionUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 6 + }, + { + "name": "ownedTypeFeaturing", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Feature", + "type": "TypeFeaturing", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "typeFeaturing" + ], + "redefines": [], + "doc": "The ownedRelationships of this Feature that are TypeFeaturings and for which the Feature is the featureOfType.", + "doc_refs": [ + "Feature", + "TypeFeaturings", + "featureOfType", + "ownedRelationships" + ], + "corpus_elements": 16951, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedTypeFeaturing = ownedRelationship->selectByKind(TypeFeaturing)-> select(tf | tf.featureOfType = self)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 0 + }, + { + "name": "ownedTyping", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "FeatureTyping", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedSpecialization", + "typing" + ], + "redefines": [], + "doc": "The ownedSpecializations of this Feature that are FeatureTypings, for which the Feature is the typedFeature.", + "doc_refs": [ + "Feature", + "FeatureTypings", + "ownedSpecializations", + "typedFeature" + ], + "corpus_elements": 16951, + "corpus_nonempty": 2780, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": { + "Feature": "ownedTyping = ownedGeneralization->selectByKind(FeatureTyping)" + }, + "corpus_elements": 16951, + "corpus_nonempty": 2780 + }, + { + "name": "ownedUnioning", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Unioning", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRelationship", + "sourceRelationship" + ], + "redefines": [], + "doc": "The ownedRelationships of this Type that are Unionings, having the Type as their typeUnioned.", + "doc_refs": [ + "Type", + "Unionings", + "ownedRelationships", + "typeUnioned" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": false, + "rules": { + "Type": "ownedUnioning = ownedRelationship->selectByKind(Unioning)" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "ownedUsage", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature", + "usage" + ], + "redefines": [], + "doc": "The Usages that are ownedFeatures of this Definition.", + "doc_refs": [ + "Definition", + "Usages", + "ownedFeatures" + ], + "corpus_elements": 1354, + "corpus_nonempty": 660, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedUsage = ownedFeature->selectByKind(Usage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 660 + }, + { + "name": "ownedUseCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "UseCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedCase" + ], + "redefines": [], + "doc": "The UseCaseUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "UseCaseUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedUseCase = ownedUsage->selectByKind(UseCaseUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 2 + }, + { + "name": "ownedVariantUsage", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "VariantMembership", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberElement" + ], + "doc": "The Usage that represents a variant in the context of the owningVariationDefinition or owningVariationUsage.", + "doc_refs": [ + "Usage", + "owningVariationDefinition", + "owningVariationUsage" + ], + "corpus_elements": 107, + "corpus_nonempty": 107, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 107, + "corpus_nonempty": 107 + }, + { + "name": "ownedVerificationCase", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "VerificationCaseUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedCase" + ], + "redefines": [], + "doc": "The VerificationCaseUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "VerificationCaseUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedVerificationCase = ownedUsage->selectByKind(VerificationCaseUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 1 + }, + { + "name": "ownedView", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedPart" + ], + "redefines": [], + "doc": "The ViewUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "ViewUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedView = ownedUsage->selectByKind(ViewUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 1 + }, + { + "name": "ownedViewpoint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Definition", + "type": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRequirement" + ], + "redefines": [], + "doc": "The ViewpointUsages that are ownedUsages of this Definition.", + "doc_refs": [ + "Definition", + "ViewpointUsages", + "ownedUsages" + ], + "corpus_elements": 1354, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 26, + "also_owned_elsewhere": false, + "rules": { + "Definition": "ownedViewpoint = ownedUsage->selectByKind(ViewpointUsage)" + }, + "corpus_elements": 1354, + "corpus_nonempty": 1 + }, + { + "name": "owner", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "Element", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The owner of this Element, derived as the owningRelatedElement of the owningRelationship of this Element, if any.", + "doc_refs": [ + "owningRelatedElement", + "owningRelationship" + ], + "corpus_elements": 52148, + "corpus_nonempty": 19249, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "owner = owningRelationship.owningRelatedElement" + }, + "corpus_elements": 52148, + "corpus_nonempty": 19249 + }, + { + "name": "owningAnnotatedElement", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "Annotation", + "type": "Element", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "annotatedElement", + "owningRelatedElement" + ], + "redefines": [], + "doc": "The annotatedElement of this Annotation, when it is also the owningRelatedElement.", + "doc_refs": [ + "Annotation", + "annotatedElement", + "owningRelatedElement" + ], + "corpus_elements": 19, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 19, + "corpus_nonempty": 0 + }, + { + "name": "owningAnnotatingElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Annotation", + "type": "AnnotatingElement", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "annotatingElement", + "owningRelatedElement" + ], + "redefines": [], + "doc": "The annotatingElement of this Annotation, when it is the owningRelatedElement.", + "doc_refs": [ + "Annotation", + "annotatingElement", + "owningRelatedElement" + ], + "corpus_elements": 19, + "corpus_nonempty": 19, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 19, + "corpus_nonempty": 19 + }, + { + "name": "owningAnnotatingRelationship", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "AnnotatingElement", + "type": "Annotation", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "annotation", + "owningRelationship" + ], + "redefines": [], + "doc": "The owningRelationship of this AnnotatingRelationship, if it is an Annotation", + "doc_refs": [ + "AnnotatingRelationship", + "Annotation", + "owningRelationship" + ], + "corpus_elements": 632, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 632, + "corpus_nonempty": 0 + }, + { + "name": "owningClassifier", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Subclassification", + "type": "Classifier", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "owningType" + ], + "doc": "The Classifier that owns this Subclassification relationship, which must also be its subclassifier.", + "doc_refs": [ + "Classifier", + "Subclassification", + "subclassifier" + ], + "corpus_elements": 1151, + "corpus_nonempty": 1151, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 1151, + "corpus_nonempty": 1151 + }, + { + "name": "owningDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Definition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "featuringDefinition", + "owningType" + ], + "redefines": [], + "doc": "The Definition that owns this Usage (if any).", + "doc_refs": [ + "Definition", + "Usage" + ], + "corpus_elements": 8045, + "corpus_nonempty": 1703, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 8045, + "corpus_nonempty": 1703 + }, + { + "name": "owningFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureInverting", + "type": "Feature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "featureInverted", + "owningRelatedElement" + ], + "redefines": [], + "doc": "A featureInverted that is also the owningRelatedElement of this FeatureInverting.", + "doc_refs": [ + "FeatureInverting", + "featureInverted", + "owningRelatedElement" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + }, + { + "metaclass": "Subsetting", + "type": "Feature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "subsettingFeature" + ], + "redefines": [ + "owningType" + ], + "doc": "A subsettingFeature that is also the owningRelatedElement of this Subsetting.", + "doc_refs": [ + "Subsetting", + "owningRelatedElement", + "subsettingFeature" + ], + "corpus_elements": 5637, + "corpus_nonempty": 5637, + "class": "structural" + }, + { + "metaclass": "FeatureTyping", + "type": "Feature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "typedFeature" + ], + "redefines": [ + "owningType" + ], + "doc": "A typedFeature that is also the owningRelatedElement of this FeatureTyping.", + "doc_refs": [ + "FeatureTyping", + "owningRelatedElement", + "typedFeature" + ], + "corpus_elements": 2787, + "corpus_nonempty": 2787, + "class": "structural" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 8424, + "corpus_nonempty": 8424 + }, + { + "name": "owningFeatureMembership", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "FeatureMembership", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "owningMembership" + ], + "redefines": [], + "doc": "The FeatureMembership that owns this Feature as an ownedMemberFeature, determining its owningType.", + "doc_refs": [ + "Feature", + "FeatureMembership", + "ownedMemberFeature", + "owningType" + ], + "corpus_elements": 16951, + "corpus_nonempty": 10203, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 16951, + "corpus_nonempty": 10203 + }, + { + "name": "owningFeatureOfType", + "class": "structural", + "status": "unexercised", + "declaring": [ + { + "metaclass": "TypeFeaturing", + "type": "Feature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "featureOfType", + "owningRelatedElement" + ], + "redefines": [], + "doc": "A featureOfType that is also the owningRelatedElement of this TypeFeaturing.", + "doc_refs": [ + "TypeFeaturing", + "featureOfType", + "owningRelatedElement" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 0, + "corpus_nonempty": 0 + }, + { + "name": "owningMembership", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "OwningMembership", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "membership", + "owningRelationship" + ], + "redefines": [], + "doc": "The owningRelationship of this Element, if that Relationship is a Membership.", + "doc_refs": [ + "Element", + "Membership", + "Relationship", + "owningRelationship" + ], + "corpus_elements": 52148, + "corpus_nonempty": 18728, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 52148, + "corpus_nonempty": 18728 + }, + { + "name": "owningNamespace", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "Namespace", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "namespace" + ], + "redefines": [], + "doc": "The Namespace that owns this Element, which is the membershipOwningNamespace of the owningMembership of this Element, if any.", + "doc_refs": [ + "Element", + "Namespace", + "membershipOwningNamespace", + "owningMembership" + ], + "corpus_elements": 52148, + "corpus_nonempty": 18728, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "owningNamespace = if owningMembership = null then null else owningMembership.membershipOwningNamespace endif" + }, + "corpus_elements": 52148, + "corpus_nonempty": 18728 + }, + { + "name": "owningType", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Disjoining", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "owningRelatedElement", + "typeDisjoined" + ], + "redefines": [], + "doc": "A typeDisjoined that is also an owningRelatedElement.", + "doc_refs": [ + "owningRelatedElement", + "typeDisjoined" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + }, + { + "metaclass": "FeatureMembership", + "type": "Type", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "type" + ], + "redefines": [ + "membershipOwningNamespace" + ], + "doc": "The Type that owns this FeatureMembership.", + "doc_refs": [ + "FeatureMembership", + "Type" + ], + "corpus_elements": 10203, + "corpus_nonempty": 10203, + "class": "structural" + }, + { + "metaclass": "Conjugation", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "conjugatedType", + "owningRelatedElement" + ], + "redefines": [], + "doc": "The conjugatedType of this Conjugation that is also its owningRelatedElement.", + "doc_refs": [ + "Conjugation", + "conjugatedType", + "owningRelatedElement" + ], + "corpus_elements": 91, + "corpus_nonempty": 91, + "class": "structural" + }, + { + "metaclass": "Specialization", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "owningRelatedElement", + "specific" + ], + "redefines": [], + "doc": "The Type that is the specific Type of this Specialization and owns it as its owningRelatedElement.", + "doc_refs": [ + "Specialization", + "Type", + "owningRelatedElement", + "specific" + ], + "corpus_elements": 9575, + "corpus_nonempty": 9575, + "class": "structural" + }, + { + "metaclass": "Feature", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "featuringType", + "owningNamespace", + "typeWithFeature" + ], + "redefines": [], + "doc": "The Type that is the owningType of the owningFeatureMembership of this Feature.", + "doc_refs": [ + "Feature", + "Type", + "owningFeatureMembership", + "owningType" + ], + "corpus_elements": 16951, + "corpus_nonempty": 10203, + "class": "structural" + } + ], + "concrete_carriers": 105, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 36820, + "corpus_nonempty": 30072 + }, + { + "name": "owningUsage", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Usage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "owningType" + ], + "redefines": [], + "doc": "The Usage in which this Usage is nested (if any).", + "doc_refs": [ + "Usage" + ], + "corpus_elements": 8045, + "corpus_nonempty": 5043, + "class": "structural" + } + ], + "concrete_carriers": 47, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 8045, + "corpus_nonempty": 5043 + }, + { + "name": "parameter", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Behavior", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "directedFeature" + ], + "doc": "The parameters of this Behavior, which are defined as its directedFeatures, whose values are passed into and/or out of a performance of the Behavior.", + "doc_refs": [ + "Behavior", + "directedFeatures" + ], + "corpus_elements": 259, + "corpus_nonempty": 160, + "class": "inheritance-aware" + }, + { + "metaclass": "Step", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "directedFeature" + ], + "doc": "The parameters of this Step, which are defined as its directedFeatures, whose values are passed into and/or out of a performance of the Step.", + "doc_refs": [ + "Step", + "directedFeatures", + "parameters" + ], + "corpus_elements": 6120, + "corpus_nonempty": 2160, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 69, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 6379, + "corpus_nonempty": 2320 + }, + { + "name": "partDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "PartUsage", + "type": "PartDefinition", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "itemDefinition" + ], + "redefines": [], + "doc": "The itemDefinitions of this PartUsage that are PartDefinitions.", + "doc_refs": [ + "itemDefinitions" + ], + "corpus_elements": 1236, + "corpus_nonempty": 798, + "class": "structural" + } + ], + "concrete_carriers": 6, + "also_owned_elsewhere": false, + "rules": { + "PartUsage": "itemDefinition->selectByKind(PartDefinition)" + }, + "corpus_elements": 1236, + "corpus_nonempty": 798 + }, + { + "name": "payloadArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "AcceptActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An Expression whose result is bound to the payload parameter of this AcceptActionUsage. If provided, the AcceptActionUsage will only accept a Transfer with exactly this payload.", + "doc_refs": [ + "AcceptActionUsage", + "Expression", + "parameter", + "result" + ], + "corpus_elements": 103, + "corpus_nonempty": 18, + "class": "inheritance-aware" + }, + { + "metaclass": "SendActionUsage", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An Expression whose result is bound to the payload input parameter of this SendActionUsage.", + "doc_refs": [ + "Expression", + "SendActionUsage" + ], + "corpus_elements": 37, + "corpus_nonempty": 35, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "AcceptActionUsage": "payloadArgument = argument(1)", + "SendActionUsage": "payloadArgument = argument(1)" + }, + "corpus_elements": 140, + "corpus_nonempty": 53 + }, + { + "name": "payloadFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "PayloadFeature", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The ownedFeature of the Flow that is a PayloadFeature (if any).", + "doc_refs": [ + "Flow", + "PayloadFeature", + "ownedFeature" + ], + "corpus_elements": 142, + "corpus_nonempty": 48, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "Flow": "payloadFeature = let payloadFeatures : Sequence(PayloadFeature) = ownedFeature->selectByKind(PayloadFeature) in if payloadFeatures->isEmpty() then null else payloadFeatures->first() endif" + }, + "corpus_elements": 142, + "corpus_nonempty": 48 + }, + { + "name": "payloadParameter", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "AcceptActionUsage", + "type": "ReferenceUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "nestedReference", + "parameter" + ], + "redefines": [], + "doc": "The nestedReference of this AcceptActionUsage that redefines the payload output parameter of the base AcceptActionUsage AcceptAction from the Systems Model Library.", + "doc_refs": [ + "AcceptAction", + "AcceptActionUsage", + "nestedReference", + "parameter", + "payload" + ], + "corpus_elements": 103, + "corpus_nonempty": 103, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "AcceptActionUsage": "payloadParameter = if parameter->isEmpty() then null else parameter->first() endif" + }, + "corpus_elements": 103, + "corpus_nonempty": 103 + }, + { + "name": "payloadType", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "Classifier", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The type of values transferred, which is the type of the payloadFeature of the Flow.", + "doc_refs": [ + "Flow", + "payloadFeature", + "type" + ], + "corpus_elements": 142, + "corpus_nonempty": 48, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "Flow": "payloadType = if payloadFeature = null then Sequence{} else payloadFeature.type endif" + }, + "corpus_elements": 142, + "corpus_nonempty": 48 + }, + { + "name": "performedAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "PerformActionUsage", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "eventOccurrence" + ], + "doc": "The ActionUsage to be performed by this PerformedActionUsage. It is the eventOccurrence of the PerformActionUsage considered as an EventOccurrenceUsage, which must be an ActionUsage.", + "doc_refs": [ + "ActionUsage", + "EventOccurrenceUsage", + "PerformActionUsage", + "PerformedActionUsage", + "eventOccurrence" + ], + "corpus_elements": 195, + "corpus_nonempty": 113, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 195, + "corpus_nonempty": 113 + }, + { + "name": "portDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ConjugatedPortTyping", + "type": "PortDefinition", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The originalPortDefinition of the conjugatedPortDefinition of this ConjugatedPortTyping.", + "doc_refs": [ + "ConjugatedPortTyping", + "conjugatedPortDefinition", + "originalPortDefinition" + ], + "corpus_elements": 48, + "corpus_nonempty": 0, + "class": "structural" + }, + { + "metaclass": "PortUsage", + "type": "PortDefinition", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "occurrenceDefinition" + ], + "doc": "The occurrenceDefinitions of this PortUsage, which must all be PortDefinitions.", + "doc_refs": [ + "PortUsage", + "occurrenceDefinitions" + ], + "corpus_elements": 365, + "corpus_nonempty": 305, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "ConjugatedPortTyping": "portDefinition = conjugatedPortDefinition.originalPortDefinition" + }, + "corpus_elements": 413, + "corpus_nonempty": 305 + }, + { + "name": "predicate", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "BooleanExpression", + "type": "Predicate", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "function" + ], + "doc": "The Predicate that types the Expression.", + "doc_refs": [], + "corpus_elements": 291, + "corpus_nonempty": 127, + "class": "structural" + } + ], + "concrete_carriers": 8, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 291, + "corpus_nonempty": 127 + }, + { + "name": "qualifiedName", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "String", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The full ownership-qualified name of this Element, represented in a form that is valid according to the KerML textual concrete syntax for qualified names (including use of unrestricted name notation and escaped characters, as necessary). The qualifiedName is null if this Element has no owningNamespace or if there is not a complete ownership chain of named Namespaces from a root Namespace to this Element. If the owningNamespace has other Elements with the same name as this one, then the qualifiedName is null for all such Elements other than the first.", + "doc_refs": [ + "Element", + "Elements", + "Namespace", + "Namespaces", + "owningNamespace", + "qualifiedName" + ], + "corpus_elements": 52148, + "corpus_nonempty": 7351, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "qualifiedName = if owningNamespace = null then null else if name <> null and owningNamespace.ownedMember-> select(m | m.name = name).indexOf(self) <> 1 then null else if owningNamespace.owner = null then escapedName() else if owningNamespace.qualifiedName = null or escapedName() = null then null else owningNamespace.qualifiedName + '::' + escapedName() endif endif endif endif" + }, + "corpus_elements": 52148, + "corpus_nonempty": 7351 + }, + { + "name": "receiverArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "AcceptActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An Expression whose result is bound to the receiver input parameter of this AcceptActionUsage.", + "doc_refs": [ + "AcceptActionUsage", + "Expression", + "parameter", + "receiver", + "result" + ], + "corpus_elements": 103, + "corpus_nonempty": 22, + "class": "inheritance-aware" + }, + { + "metaclass": "SendActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An Expression whose result is bound to the receiver input parameter of this SendActionUsage.", + "doc_refs": [ + "Expression", + "SendActionUsage", + "receiver" + ], + "corpus_elements": 37, + "corpus_nonempty": 23, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "AcceptActionUsage": "receiverArgument = argument(2)", + "SendActionUsage": "receiverArgument = argument(3)" + }, + "corpus_elements": 140, + "corpus_nonempty": 45 + }, + { + "name": "referencedConcern", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FramedConcernMembership", + "type": "ConcernUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "referencedConstraint" + ], + "doc": "The ConcernUsage that is referenced through this FramedConcernMembership. It is the referencedConstraint of the FramedConcernMembership considered as a RequirementConstraintMembership, which must be a ConcernUsage.", + "doc_refs": [ + "ConcernUsage", + "FramedConcernMembership", + "RequirementConstraintMembership", + "referencedConstraint" + ], + "corpus_elements": 6, + "corpus_nonempty": 6, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 6, + "corpus_nonempty": 6 + }, + { + "name": "referencedConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementConstraintMembership", + "type": "ConstraintUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ConstraintUsage that is referenced through this RequirementConstraintMembership. It is the referencedFeature of the ownedReferenceSubsetting of the ownedConstraint, if there is one, and, otherwise, the ownedConstraint itself.", + "doc_refs": [ + "ConstraintUsage", + "RequirementConstraintMembership", + "ownedConstraint", + "ownedReferenceSubsetting", + "referencedFeature" + ], + "corpus_elements": 66, + "corpus_nonempty": 66, + "class": "structural" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "RequirementConstraintMembership": "referencedConstraint = let referencedFeature : Feature = ownedConstraint.referencedFeatureTarget() in if referencedFeature = null then ownedConstraint else if referencedFeature.oclIsKindOf(ConstraintUsage) then refrencedFeature.oclAsType(ConstraintUsage) else null endif endif" + }, + "corpus_elements": 66, + "corpus_nonempty": 66 + }, + { + "name": "referencedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MetadataAccessExpression", + "type": "Element", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Element whose metadata is being accessed.", + "doc_refs": [ + "Element" + ], + "corpus_elements": 27, + "corpus_nonempty": 27, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "MetadataAccessExpression": "referencedElement = let elements : Sequence(Element) = ownedMembership-> reject(oclIsKindOf(FeatureMembership)).memberElement in if elements->isEmpty() then null else elements->first() endif" + }, + "corpus_elements": 27, + "corpus_nonempty": 27 + }, + { + "name": "referencedRendering", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewRenderingMembership", + "type": "RenderingUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The RenderingUsage that is referenced through this ViewRenderingMembership. It is the referencedFeature of the ownedReferenceSubsetting for the ownedRendering, if there is one, and, otherwise, the ownedRendering itself.", + "doc_refs": [ + "RenderingUsage", + "ViewRenderingMembership", + "ownedReferenceSubsetting", + "ownedRendering", + "referencedFeature" + ], + "corpus_elements": 11, + "corpus_nonempty": 11, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "ViewRenderingMembership": "referencedRendering = let referencedFeature : Feature = ownedRendering.referencedFeatureTarget() in if referencedFeature = null then ownedRendering else if referencedFeature.oclIsKindOf(RenderingUsage) then refrencedFeature.oclAsType(RenderingUsage) else null endif endif" + }, + "corpus_elements": 11, + "corpus_nonempty": 11 + }, + { + "name": "referencingFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ReferenceSubsetting", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "owningFeature", + "subsettingFeature" + ], + "doc": "The Feature that owns this ReferenceSubsetting relationship, which is also its subsettingFeature.", + "doc_refs": [ + "Feature", + "ReferenceSubsetting", + "subsettingFeature" + ], + "corpus_elements": 1164, + "corpus_nonempty": 1164, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 1164, + "corpus_nonempty": 1164 + }, + { + "name": "referent", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureReferenceExpression", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Feature that is referenced by this FeatureReferenceExpression, which is its first non-parameter member.", + "doc_refs": [ + "Feature", + "FeatureReferenceExpression", + "member", + "parameter" + ], + "corpus_elements": 1722, + "corpus_nonempty": 1685, + "class": "structural" + }, + { + "metaclass": "AssignmentActionUsage", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Feature whose value is to be set.", + "doc_refs": [ + "Feature" + ], + "corpus_elements": 27, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "FeatureReferenceExpression": "referent = let nonParameterMemberships : Sequence(Membership) = ownedMembership-> reject(oclIsKindOf(ParameterMembership)) in if nonParameterMemberships->isEmpty() or not nonParameterMemberships->first().memberElement.oclIsKindOf(Feature) then null else nonParameterMemberships->first().memberElement.oclAsType(Feature) endif", + "AssignmentActionUsage": "referent = let unownedFeatures : Sequence(Feature) = ownedMembership-> reject(oclIsKindOf(FeatureMembership)).memberElement-> selectByKind(Feature) in if unownedFeatures->isEmpty() then null else unownedFeatures->first().oclAsType(Feature) endif" + }, + "corpus_elements": 1749, + "corpus_nonempty": 1685 + }, + { + "name": "relatedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Relationship", + "type": "Element", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Elements that are related by this Relationship, derived as the union of the source and target Elements of the Relationship.", + "doc_refs": [ + "source", + "target" + ], + "corpus_elements": 33397, + "corpus_nonempty": 32658, + "class": "structural" + } + ], + "concrete_carriers": 62, + "also_owned_elsewhere": false, + "rules": { + "Relationship": "relatedElement = source->union(target)" + }, + "corpus_elements": 33397, + "corpus_nonempty": 32658 + }, + { + "name": "relatedFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Connector", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "relatedElement" + ], + "doc": "The Features that are related by this Connector considered as a Relationship and that restrict the links it identifies, given by the referenced Features of the connectorEnds of the Connector.", + "doc_refs": [ + "Connector", + "Features", + "Relationship", + "connectorEnds" + ], + "corpus_elements": 689, + "corpus_nonempty": 531, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 12, + "also_owned_elsewhere": false, + "rules": { + "Connector": "relatedFeature = connectorEnd.ownedReferenceSubsetting-> select(s | s <> null).subsettedFeature" + }, + "corpus_elements": 689, + "corpus_nonempty": 531 + }, + { + "name": "relatedType", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Association", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "relatedElement" + ], + "doc": "The types of the associationEnds of the Association, which are the relatedElements of the Association considered as a Relationship.", + "doc_refs": [ + "Association", + "Relationship", + "associationEnds", + "relatedElements", + "types" + ], + "corpus_elements": 50, + "corpus_nonempty": 44, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "Association": "relatedType = associationEnd.type" + }, + "corpus_elements": 50, + "corpus_nonempty": 44 + }, + { + "name": "rendering", + "class": "inheritance-aware", + "status": "absent", + "declaring": [ + { + "metaclass": "RenderingDefinition", + "type": "RenderingUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "usage" + ], + "redefines": [], + "doc": "The usages of a RenderingDefinition that are RenderingUsages.", + "doc_refs": [ + "RenderingDefinition", + "RenderingUsages", + "usages" + ], + "corpus_elements": 1, + "corpus_nonempty": 0, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "RenderingDefinition": "rendering = usages->selectByKind(RenderingUsage)" + }, + "corpus_elements": 1, + "corpus_nonempty": 0 + }, + { + "name": "renderingDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RenderingUsage", + "type": "RenderingDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "partDefinition" + ], + "doc": "The RenderingDefinition that is the definition of this RenderingUsage.", + "doc_refs": [ + "RenderingDefinition", + "RenderingUsage", + "definition" + ], + "corpus_elements": 14, + "corpus_nonempty": 13, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 14, + "corpus_nonempty": 13 + }, + { + "name": "representedElement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TextualRepresentation", + "type": "Element", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owner" + ], + "redefines": [ + "annotatedElement" + ], + "doc": "The Element that is represented by this TextualRepresentation.", + "doc_refs": [ + "Element", + "TextualRepresentation" + ], + "corpus_elements": 91, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 91, + "corpus_nonempty": 91 + }, + { + "name": "requiredConstraint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The owned ConstraintUsages that represent requirements of this RequirementUsage, which are the ownedConstraints of the RequirementConstraintMemberships of the RequirementUsage with kind = requirement.", + "doc_refs": [ + "ConstraintUsages", + "RequirementConstraintMemberships", + "RequirementUsage", + "kind", + "ownedConstraints", + "requirement" + ], + "corpus_elements": 171, + "corpus_nonempty": 24, + "class": "structural" + }, + { + "metaclass": "RequirementDefinition", + "type": "ConstraintUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The owned ConstraintUsages that represent requirements of this RequirementDefinition, derived as the ownedConstraints of the RequirementConstraintMemberships of the RequirementDefinition with kind = requirement.", + "doc_refs": [ + "ConstraintUsages", + "RequirementConstraintMemberships", + "RequirementDefinition", + "kind", + "ownedConstraints", + "requirement" + ], + "corpus_elements": 37, + "corpus_nonempty": 15, + "class": "structural" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "requiredConstraint = ownedFeatureMembership-> selectByKind(RequirementConstraintMembership)-> select(kind = RequirementConstraintKind::requirement). ownedConstraint", + "RequirementDefinition": "requiredConstraint = ownedFeatureMembership-> selectByKind(RequirementConstraintMembership)-> select(kind = RequirementConstraintKind::requirement). ownedConstraint" + }, + "corpus_elements": 208, + "corpus_nonempty": 39 + }, + { + "name": "requirementDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "RequirementDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "constraintDefinition" + ], + "doc": "The RequirementDefinition that is the single definition of this RequirementUsage.", + "doc_refs": [ + "RequirementDefinition", + "RequirementUsage", + "definition" + ], + "corpus_elements": 171, + "corpus_nonempty": 88, + "class": "structural" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 171, + "corpus_nonempty": 88 + }, + { + "name": "result", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Expression", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "output", + "parameter" + ], + "redefines": [], + "doc": "An output parameter of the Expression whose value is the result of the Expression. The result of an Expression is either inherited from its function or it is related to the Expression via a ReturnParameterMembership, in which case it redefines the result parameter of its function.", + "doc_refs": [ + "Expression", + "ReturnParameterMembership", + "function", + "output", + "parameter", + "result" + ], + "corpus_elements": 5092, + "corpus_nonempty": 110, + "class": "inheritance-aware" + }, + { + "metaclass": "Function", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "output", + "parameter" + ], + "redefines": [], + "doc": "The object or value that is the result of evaluating the Function.", + "doc_refs": [], + "corpus_elements": 127, + "corpus_nonempty": 47, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 43, + "also_owned_elsewhere": false, + "rules": { + "Expression": "result = let resultParams : Sequence(Feature) = featureMemberships-> selectByKind(ReturnParameterMembership). ownedMemberParameter in if resultParams->notEmpty() then resultParams->first() else null endif ", + "Function": "result = let resultParams : Sequence(Feature) = featureMemberships-> selectByKind(ReturnParameterMembership). ownedMemberParameter in if resultParams->notEmpty() then resultParams->first() else null endif" + }, + "corpus_elements": 5219, + "corpus_nonempty": 157 + }, + { + "name": "resultExpression", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "AnalysisCaseUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "An Expression used to compute the result of the AnalysisCaseUsage, owned via a ResultExpressionMembership.", + "doc_refs": [ + "AnalysisCaseUsage", + "Expression", + "ResultExpressionMembership", + "result" + ], + "corpus_elements": 26, + "corpus_nonempty": 0, + "class": "structural" + }, + { + "metaclass": "AnalysisCaseDefinition", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "expression", + "ownedFeature" + ], + "redefines": [], + "doc": "An Expression used to compute the result of the AnalysisCaseDefinition, owned via a ResultExpressionMembership.", + "doc_refs": [ + "AnalysisCaseDefinition", + "Expression", + "ResultExpressionMembership", + "result" + ], + "corpus_elements": 14, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "AnalysisCaseUsage": "resultExpression = let results : OrderedSet(ResultExpressionMembership) = featureMembersip-> selectByKind(ResultExpressionMembership) in if results->isEmpty() then null else results->first().ownedResultExpression endif", + "AnalysisCaseDefinition": "resultExpression = let results : OrderedSet(ResultExpressionMembership) = featureMembersip-> selectByKind(ResultExpressionMembership) in if results->isEmpty() then null else results->first().ownedResultExpression endif" + }, + "corpus_elements": 40, + "corpus_nonempty": 2 + }, + { + "name": "satisfiedRequirement", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "SatisfyRequirementUsage", + "type": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "assertedConstraint" + ], + "doc": "The RequirementUsage that is satisfied by the satisfyingSubject of this SatisfyRequirementUsage. It is the assertedConstraint of the SatisfyRequirementUsage considered as an AssertConstraintUsage, which must be a RequirementUsage.", + "doc_refs": [ + "AssertConstraintUsage", + "RequirementUsage", + "SatisfyRequirementUsage", + "assertedConstraint", + "satisfyingSubject" + ], + "corpus_elements": 22, + "corpus_nonempty": 18, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 22, + "corpus_nonempty": 18 + }, + { + "name": "satisfiedViewpoint", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewUsage", + "type": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "nestedRequirement" + ], + "redefines": [], + "doc": "The nestedRequirements of this ViewUsage that are ViewpointUsages for (additional) viewpoints satisfied by the ViewUsage.", + "doc_refs": [ + "ViewUsage", + "ViewpointUsages", + "nestedRequirements" + ], + "corpus_elements": 12, + "corpus_nonempty": 0, + "class": "structural" + }, + { + "metaclass": "ViewDefinition", + "type": "ViewpointUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedRequirement" + ], + "redefines": [], + "doc": "The composite ownedRequirements of this ViewDefinition that are ViewpointUsages for viewpoints satisfied by the ViewDefinition.", + "doc_refs": [ + "ViewDefinition", + "ViewpointUsages", + "ownedRequirements" + ], + "corpus_elements": 10, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "ViewUsage": "satisfiedViewpoint = ownedRequirement-> selectByKind(ViewpointUsage)-> select(isComposite)", + "ViewDefinition": "satisfiedViewpoint = ownedRequirement-> selectByKind(ViewpointUsage)-> select(isComposite)" + }, + "corpus_elements": 22, + "corpus_nonempty": 1 + }, + { + "name": "satisfyingFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "SatisfyRequirementUsage", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Feature that represents the actual subject that is asserted to satisfy the satisfiedRequirement. The satisfyingFeature is bound to the subjectParameter of the SatisfyRequirementUsage.", + "doc_refs": [ + "Feature", + "SatisfyRequirementUsage", + "satisfiedRequirement", + "satisfyingFeature", + "subjectParameter" + ], + "corpus_elements": 22, + "corpus_nonempty": 19, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "SatisfyRequirementUsage": "satisfyingFeature = let bindings: BindingConnector = ownedMember-> selectByKind(BindingConnector)-> select(b | b.relatedElement->includes(subjectParameter)) in if bindings->isEmpty() or bindings->first().relatedElement->exits(r | r <> subjectParameter) then null else bindings->first().relatedElement->any(r | r <> subjectParameter) endif" + }, + "corpus_elements": 22, + "corpus_nonempty": 19 + }, + { + "name": "senderArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "SendActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An Expression whose result is bound to the sender input parameter of this SendActionUsage.", + "doc_refs": [ + "Expression", + "SendActionUsage", + "sender" + ], + "corpus_elements": 37, + "corpus_nonempty": 14, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "SendActionUsage": "senderArgument = argument(2)" + }, + "corpus_elements": 37, + "corpus_nonempty": 14 + }, + { + "name": "seqArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "ForLoopActionUsage", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose result provides the sequence of values to which the loopVariable is set for each iterative performance of the bodyAction. It is the Expression whose result is bound to the seq input parameter of this ForLoopActionUsage.", + "doc_refs": [ + "Expression", + "ForLoopActionUsage", + "bodyAction", + "input", + "loopVariable", + "parameter", + "result", + "seq" + ], + "corpus_elements": 3, + "corpus_nonempty": 3, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "ForLoopActionUsage": "seqArgument = argument(1) " + }, + "corpus_elements": 3, + "corpus_nonempty": 3 + }, + { + "name": "shortName", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "String", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The short name to be used for this Element during name resolution within its owningNamespace. This is derived using the effectiveShortName() operation. By default, it is the same as the declaredShortName, but this is overridden for certain kinds of Elements to compute a shortName even when the declaredName is null.", + "doc_refs": [ + "Element", + "Elements", + "declaredName", + "declaredShortName", + "owningNamespace", + "shortName" + ], + "corpus_elements": 52148, + "corpus_nonempty": 77, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "shortName = effectiveShortName()" + }, + "corpus_elements": 52148, + "corpus_nonempty": 77 + }, + { + "name": "source", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The source ActionUsage of this TransitionUsage, which becomes the source of the succession for the TransitionUsage.", + "doc_refs": [ + "ActionUsage", + "TransitionUsage", + "source", + "succession" + ], + "corpus_elements": 111, + "corpus_nonempty": 52, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": true, + "rules": { + "TransitionUsage": "source = let sourceFeature : Feature = sourceFeature() in if sourceFeature = null then null else sourceFeature.featureTarget.oclAsType(ActionUsage)" + }, + "corpus_elements": 111, + "corpus_nonempty": 52 + }, + { + "name": "sourceFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Connector", + "type": "Feature", + "multiplicity": "0..1", + "ordered": true, + "subsets": [ + "relatedFeature" + ], + "redefines": [ + "source" + ], + "doc": "The source relatedFeature for this Connector. It is the first relatedFeature.", + "doc_refs": [ + "Connector", + "relatedFeature" + ], + "corpus_elements": 689, + "corpus_nonempty": 531, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 12, + "also_owned_elsewhere": false, + "rules": { + "Connector": "sourceFeature = if relatedFeature->isEmpty() then null else relatedFeature->first() endif" + }, + "corpus_elements": 689, + "corpus_nonempty": 531 + }, + { + "name": "sourceOutputFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "Feature", + "multiplicity": "0..1", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Feature that provides the items carried by the Flow. It must be a feature of the source of the Flow.", + "doc_refs": [ + "Feature", + "Flow", + "feature", + "source" + ], + "corpus_elements": 142, + "corpus_nonempty": 122, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "Flow": "sourceOutputFeature = if connectorEnd->isEmpty() or connectorEnd.ownedFeature->isEmpty() then null else connectorEnd.ownedFeature->first() endif" + }, + "corpus_elements": 142, + "corpus_nonempty": 122 + }, + { + "name": "sourceType", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Association", + "type": "Type", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "relatedType" + ], + "redefines": [ + "source" + ], + "doc": "The source relatedType for this Association. It is the first relatedType of the Association.", + "doc_refs": [ + "Association", + "relatedType" + ], + "corpus_elements": 50, + "corpus_nonempty": 44, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "Association": "sourceType = if relatedType->isEmpty() then null else relatedType->first() endif" + }, + "corpus_elements": 50, + "corpus_nonempty": 44 + }, + { + "name": "stakeholderParameter", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this RequirementUsage that represent stakeholders for the requirement.", + "doc_refs": [ + "RequirementUsage", + "parameters" + ], + "corpus_elements": 171, + "corpus_nonempty": 4, + "class": "inheritance-aware" + }, + { + "metaclass": "RequirementDefinition", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameters of this RequirementDefinition that represent stakeholders for th requirement.", + "doc_refs": [ + "RequirementDefinition", + "parameters" + ], + "corpus_elements": 37, + "corpus_nonempty": 2, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "stakeholderParameter = featureMembership-> selectByKind(AStakholderMembership). ownedStakeholderParameter", + "RequirementDefinition": "stakeholderParameter = featureMembership-> selectByKind(StakholderMembership). ownedStakeholderParameter" + }, + "corpus_elements": 208, + "corpus_nonempty": 6 + }, + { + "name": "state", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "StateDefinition", + "type": "StateUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "action" + ], + "redefines": [], + "doc": "The StateUsages, which are actions in the StateDefinition, that specify the discrete states in the behavior defined by the StateDefinition.", + "doc_refs": [ + "StateDefinition", + "StateUsages", + "actions" + ], + "corpus_elements": 17, + "corpus_nonempty": 4, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "StateDefinition": "state = action->selectByKind(StateUsage)" + }, + "corpus_elements": 17, + "corpus_nonempty": 4 + }, + { + "name": "stateDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "StateUsage", + "type": "Behavior", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [ + "actionDefinition" + ], + "doc": "The Behaviors that are the types of this StateUsage. Nominally, these would be StateDefinitions, but kernel Behaviors are also allowed, to permit use of Behaviors from the Kernel Model Libraries.", + "doc_refs": [ + "Behaviors", + "StateDefinitions", + "StateUsage", + "types" + ], + "corpus_elements": 160, + "corpus_nonempty": 24, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 160, + "corpus_nonempty": 24 + }, + { + "name": "step", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Behavior", + "type": "Step", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "The Steps that make up this Behavior.", + "doc_refs": [ + "Behavior", + "Steps" + ], + "corpus_elements": 259, + "corpus_nonempty": 81, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 16, + "also_owned_elsewhere": false, + "rules": { + "Behavior": "step = feature->selectByKind(Step)" + }, + "corpus_elements": 259, + "corpus_nonempty": 81 + }, + { + "name": "subjectParameter", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameter of this RequirementUsage that represents its subject.", + "doc_refs": [ + "RequirementUsage", + "parameter" + ], + "corpus_elements": 171, + "corpus_nonempty": 54, + "class": "inheritance-aware" + }, + { + "metaclass": "RequirementDefinition", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameter of this RequirementDefinition that represents its subject.", + "doc_refs": [ + "RequirementDefinition", + "parameter" + ], + "corpus_elements": 37, + "corpus_nonempty": 10, + "class": "inheritance-aware" + }, + { + "metaclass": "CaseUsage", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameter of this CaseUsage that represents its subject.", + "doc_refs": [ + "CaseUsage", + "parameter" + ], + "corpus_elements": 65, + "corpus_nonempty": 38, + "class": "inheritance-aware" + }, + { + "metaclass": "CaseDefinition", + "type": "Usage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "parameter", + "usage" + ], + "redefines": [], + "doc": "The parameter of this CaseDefinition that represents its subject.", + "doc_refs": [ + "CaseDefinition", + "parameter" + ], + "corpus_elements": 30, + "corpus_nonempty": 20, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 16, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "subjectParameter = let subjects : OrderedSet(SubjectMembership) = featureMembership->selectByKind(SubjectMembership) in if subjects->isEmpty() then null else subjects->first().ownedSubjectParameter endif", + "RequirementDefinition": "subjectParameter = let subjects : OrderedSet(SubjectMembership) = featureMembership->selectByKind(SubjectMembership) in if subjects->isEmpty() then null else subjects->first().ownedSubjectParameter endif", + "CaseUsage": "subjectParameter = let subjects : OrderedSet(SubjectMembership) = featureMembership->selectByKind(SubjectMembership) in if subjects->isEmpty() then null else subjects->first().ownedSubjectParameter endif", + "CaseDefinition": "subjectParameter = let subjectMems : OrderedSet(SubjectMembership) = featureMembership->selectByKind(SubjectMembership) in if subjectMems->isEmpty() then null else subjectMems->first().ownedSubjectParameter endif" + }, + "corpus_elements": 303, + "corpus_nonempty": 122 + }, + { + "name": "succession", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "Succession", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The Succession that is the ownedFeature of this TransitionUsage, which, if the TransitionUsage is triggered, asserts the temporal ordering of the source and target.", + "doc_refs": [ + "Succession", + "TransitionUsage", + "ownedFeature", + "source", + "target" + ], + "corpus_elements": 111, + "corpus_nonempty": 111, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "TransitionUsage": "succession = ownedMember->selectByKind(Succession)->at(1)" + }, + "corpus_elements": 111, + "corpus_nonempty": 111 + }, + { + "name": "target", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The target ActionUsage of this TransitionUsage, which is the targetFeature of the succession for the TransitionUsage.", + "doc_refs": [ + "ActionUsage", + "TransitionUsage", + "succession", + "targetFeature" + ], + "corpus_elements": 111, + "corpus_nonempty": 111, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": true, + "rules": { + "TransitionUsage": "target = if succession.targetFeature->isEmpty() then null else let targetFeature : Feature = succession.targetFeature->first().featureTarget in if not targetFeature.oclIsKindOf(ActionUsage) then null else targetFeature.oclAsType(ActionUsage) endif endif " + }, + "corpus_elements": 111, + "corpus_nonempty": 111 + }, + { + "name": "targetArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "AssignmentActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose value is an occurrence in the domain of the referent Feature, for which the value of the referent will be set to the result of the valueExpression by this AssignmentActionUsage.", + "doc_refs": [ + "AssignmentActionUsage", + "Expression", + "Feature", + "referent", + "valueExpression" + ], + "corpus_elements": 27, + "corpus_nonempty": 27, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "AssignmentActionUsage": "targetArgument = argument(1)" + }, + "corpus_elements": 27, + "corpus_nonempty": 27 + }, + { + "name": "targetFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureChainExpression", + "type": "Feature", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "member" + ], + "redefines": [], + "doc": "The Feature that is accessed by this FeatureChainExpression, which is its first non-parameter member.", + "doc_refs": [ + "Feature", + "member", + "parameter" + ], + "corpus_elements": 438, + "corpus_nonempty": 438, + "class": "structural" + }, + { + "metaclass": "Connector", + "type": "Feature", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "relatedFeature" + ], + "redefines": [ + "target" + ], + "doc": "The target relatedFeatures for this Connector. This includes all the relatedFeatures other than the sourceFeature.", + "doc_refs": [ + "Connector", + "relatedFeatures", + "sourceFeature" + ], + "corpus_elements": 689, + "corpus_nonempty": 367, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 13, + "also_owned_elsewhere": false, + "rules": { + "FeatureChainExpression": "targetFeature = let nonParameterMemberships : Sequence(Membership) = ownedMembership-> reject(oclIsKindOf(ParameterMembership)) in if nonParameterMemberships->isEmpty() or not nonParameterMemberships->first().memberElement.oclIsKindOf(Feature) then null else nonParameterMemberships->first().memberElement.oclAsType(Feature) endif", + "Connector": "targetFeature = if relatedFeature->size() < 2 then OrderedSet{} else relatedFeature-> subSequence(2, relatedFeature->size())-> asOrderedSet() endif" + }, + "corpus_elements": 1127, + "corpus_nonempty": 805 + }, + { + "name": "targetInputFeature", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Flow", + "type": "Feature", + "multiplicity": "0..1", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The Feature that receives the values carried by the Flow. It must be a feature of the target of the Flow.", + "doc_refs": [ + "Feature", + "Flow", + "feature", + "target" + ], + "corpus_elements": 142, + "corpus_nonempty": 122, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 4, + "also_owned_elsewhere": false, + "rules": { + "Flow": "targetInputFeature = if connectorEnd->size() < 2 or connectorEnd->at(2).ownedFeature->isEmpty() then null else connectorEnd->at(2).ownedFeature->first() endif" + }, + "corpus_elements": 142, + "corpus_nonempty": 122 + }, + { + "name": "targetType", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Association", + "type": "Type", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "relatedType" + ], + "redefines": [ + "target" + ], + "doc": "The target relatedTypes for this Association. This includes all the relatedTypes other than the sourceType.", + "doc_refs": [ + "Association", + "relatedTypes", + "sourceType" + ], + "corpus_elements": 50, + "corpus_nonempty": 44, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "Association": "targetType = if relatedType->size() < 2 then OrderedSet{} else relatedType-> subSequence(2, relatedType->size())-> asOrderedSet() endif" + }, + "corpus_elements": 50, + "corpus_nonempty": 44 + }, + { + "name": "terminatedOccurrenceArgument", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "TerminateActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression that is the featureValue of the terminateOccurrence parameter of this TerminateActionUsage.", + "doc_refs": [ + "Expression", + "TerminateActionUsage", + "featureValue", + "parameter", + "terminateOccurrence" + ], + "corpus_elements": 6, + "corpus_nonempty": 3, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "TerminateActionUsage": "terminatedOccurrenceArgument = argument(1)" + }, + "corpus_elements": 6, + "corpus_nonempty": 3 + }, + { + "name": "text", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementUsage", + "type": "String", + "multiplicity": "0..*", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An optional textual statement of the requirement represented by this RequirementUsage, derived from the bodies of the documentation of the RequirementUsage.", + "doc_refs": [ + "RequirementUsage", + "documentation" + ], + "corpus_elements": 171, + "corpus_nonempty": 39, + "class": "structural" + }, + { + "metaclass": "RequirementDefinition", + "type": "String", + "multiplicity": "0..*", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "An optional textual statement of the requirement represented by this RequirementDefinition, derived from the bodies of the documentation of the RequirementDefinition.", + "doc_refs": [ + "RequirementDefinition", + "bodies", + "documentation" + ], + "corpus_elements": 37, + "corpus_nonempty": 20, + "class": "structural" + } + ], + "concrete_carriers": 7, + "also_owned_elsewhere": false, + "rules": { + "RequirementUsage": "text = documentation.body", + "RequirementDefinition": "text = documentation.body" + }, + "corpus_elements": 208, + "corpus_nonempty": 59 + }, + { + "name": "textualRepresentation", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Element", + "type": "TextualRepresentation", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "annotatingElement", + "ownedElement" + ], + "redefines": [], + "doc": "The TextualRepresentations that annotate this Element.", + "doc_refs": [ + "Element", + "TextualRepresentations" + ], + "corpus_elements": 52148, + "corpus_nonempty": 91, + "class": "structural" + } + ], + "concrete_carriers": 167, + "also_owned_elsewhere": false, + "rules": { + "Element": "textualRepresentation = ownedElement->selectByKind(TextualRepresentation)" + }, + "corpus_elements": 52148, + "corpus_nonempty": 91 + }, + { + "name": "thenAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "IfActionUsage", + "type": "ActionUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The ActionUsage that is to be performed if the result of the ifArgument is true. It is the second parameter of the IfActionUsage.", + "doc_refs": [ + "ActionUsage", + "IfActionUsage", + "ifArgument" + ], + "corpus_elements": 4, + "corpus_nonempty": 4, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "IfActionUsage": "thenAction = let parameter : Feature = inputParameter(2) in if parameter <> null and parameter.oclIsKindOf(ActionUsage) then parameter.oclAsType(ActionUsage) else null endif" + }, + "corpus_elements": 4, + "corpus_nonempty": 4 + }, + { + "name": "transitionFeature", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionFeatureMembership", + "type": "Step", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberFeature" + ], + "doc": "The Step that is the ownedMemberFeature of this TransitionFeatureMembership.", + "doc_refs": [ + "Step", + "TransitionFeatureMembership", + "ownedMemberFeature" + ], + "corpus_elements": 121, + "corpus_nonempty": 121, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 121, + "corpus_nonempty": 121 + }, + { + "name": "triggerAction", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "TransitionUsage", + "type": "AcceptActionUsage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedFeature" + ], + "redefines": [], + "doc": "The AcceptActionUsages that define the triggers of this TransitionUsage, which are the ownedFeatures of the TransitionUsage related to it by TransitionFeatureMemberships with kind = trigger, which must all be AcceptActionUsages.", + "doc_refs": [ + "AcceptActionUsages", + "TransitionFeatureMemberships", + "TransitionUsage", + "ownedFeatures" + ], + "corpus_elements": 111, + "corpus_nonempty": 80, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "TransitionUsage": "triggerAction = ownedFeatureMembership-> selectByKind(TransitionFeatureMembership)-> select(kind = TransitionFeatureKind::trigger).transitionFeature-> selectByKind(AcceptActionUsage)" + }, + "corpus_elements": 111, + "corpus_nonempty": 80 + }, + { + "name": "type", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Feature", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "Types that restrict the values of this Feature, such that the values must be instances of all the types. The types of a Feature are derived from its typings and the types of its subsettings. If the Feature is chained, then the types of the last Feature in the chain are also types of the chained Feature.", + "doc_refs": [ + "Feature", + "Types", + "subsettings", + "types", + "typings" + ], + "corpus_elements": 16951, + "corpus_nonempty": 4906, + "class": "structural" + } + ], + "concrete_carriers": 79, + "also_owned_elsewhere": true, + "rules": { + "Feature": "type = let types : OrderedSet(Types) = OrderedSet{self}-> -- Note: The closure operation automatically handles circular relationships. closure(typingFeatures()).typing.type->asOrderedSet() in types->reject(t1 | types->exist(t2 | t2 <> t1 and t2.specializes(t1)))" + }, + "corpus_elements": 16951, + "corpus_nonempty": 4906 + }, + { + "name": "typeDifferenced", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Differencing", + "type": "Type", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "Type with interpretations partly determined by differencingType, as described in Type::differencingType.", + "doc_refs": [ + "Type", + "differencingType" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 0, + "corpus_nonempty": 0 + }, + { + "name": "typeIntersected", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Intersecting", + "type": "Type", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "Type with interpretations partly determined by intersectingType, as described in Type::intersectingType.", + "doc_refs": [ + "Type", + "intersectingType" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 0, + "corpus_nonempty": 0 + }, + { + "name": "typeUnioned", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Unioning", + "type": "Type", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "owningRelatedElement" + ], + "redefines": [ + "source" + ], + "doc": "Type with interpretations partly determined by unioningType, as described in Type::unioningType.", + "doc_refs": [ + "Type", + "unioningType" + ], + "corpus_elements": 0, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 0, + "corpus_nonempty": 0 + }, + { + "name": "unioningType", + "class": "structural", + "status": "absent", + "declaring": [ + { + "metaclass": "Type", + "type": "Type", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The interpretations of a Type with unioningTypes are asserted to be the same as those of all the unioningTypes together, which are the Types derived from the unioningType of the ownedUnionings of this Type. For example, a Classifier for people might be the union of Classifiers for all the sexes. Similarly, a feature for people's children might be the union of features dividing them in the same ways as people in general.", + "doc_refs": [ + "Classifier", + "Classifiers", + "Type", + "Types", + "ownedUnionings", + "unioningType", + "unioningTypes" + ], + "corpus_elements": 18305, + "corpus_nonempty": 0, + "class": "structural" + } + ], + "concrete_carriers": 117, + "also_owned_elsewhere": true, + "rules": { + "Type": "unioningType = ownedUnioning.unioningType" + }, + "corpus_elements": 18305, + "corpus_nonempty": 0 + }, + { + "name": "untilArgument", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "WhileLoopActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose result, if false, determines that the bodyAction should continue to be performed. It is the (optional) third owned parameter of the WhileLoopActionUsage.", + "doc_refs": [ + "Expression", + "WhileLoopActionUsage", + "bodyAction", + "parameter" + ], + "corpus_elements": 5, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "WhileLoopActionUsage": "untilArgument = let parameter : Feature = inputParameter(3) in if parameter <> null and parameter.oclIsKindOf(Expression) then parameter.oclAsType(Expression) else null endif " + }, + "corpus_elements": 5, + "corpus_nonempty": 1 + }, + { + "name": "upperBound", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "MultiplicityRange", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [ + "bound" + ], + "redefines": [], + "doc": "The Expression whose result is the upper bound of the MultiplicityRange.", + "doc_refs": [ + "Expression", + "MultiplicityRange" + ], + "corpus_elements": 576, + "corpus_nonempty": 576, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "MultiplicityRange": "upperBound = let ownedExpressions : Sequence(Expression) = ownedMember->selectByKind(Expression) in if ownedExpressions->isEmpty() then null else if ownedExpressions->size() = 1 then ownedExpressions->at(1) else ownedExpressions->at(2) endif endif " + }, + "corpus_elements": 576, + "corpus_nonempty": 576 + }, + { + "name": "usage", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "The Usages that are features of this Usage (not necessarily owned).", + "doc_refs": [ + "Usage", + "Usages", + "features" + ], + "corpus_elements": 8045, + "corpus_nonempty": 2207, + "class": "inheritance-aware" + }, + { + "metaclass": "Definition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "feature" + ], + "redefines": [], + "doc": "The Usages that are features of this Definition (not necessarily owned).", + "doc_refs": [ + "Definition", + "Usages", + "features" + ], + "corpus_elements": 1354, + "corpus_nonempty": 660, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 73, + "also_owned_elsewhere": false, + "rules": { + "Usage": "usage = feature->selectByKind(Usage)", + "Definition": "usage = feature->selectByKind(Usage)" + }, + "corpus_elements": 9399, + "corpus_nonempty": 2867 + }, + { + "name": "useCaseDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "UseCaseUsage", + "type": "UseCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "caseDefinition" + ], + "doc": "The UseCaseDefinition that is the definition of this UseCaseUsage.", + "doc_refs": [ + "UseCaseDefinition", + "UseCaseUsage", + "definition" + ], + "corpus_elements": 32, + "corpus_nonempty": 14, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 32, + "corpus_nonempty": 14 + }, + { + "name": "useCaseIncluded", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "IncludeUseCaseUsage", + "type": "UseCaseUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "performedAction" + ], + "doc": "The UseCaseUsage to be included by this IncludeUseCaseUsage. It is the performedAction of the IncludeUseCaseUsage considered as a PerformActionUsage, which must be a UseCaseUsage.", + "doc_refs": [ + "IncludeUseCaseUsage", + "PerformActionUsage", + "UseCaseUsage", + "performedAction" + ], + "corpus_elements": 13, + "corpus_nonempty": 7, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 13, + "corpus_nonempty": 7 + }, + { + "name": "value", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "FeatureValue", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "ownedMemberElement" + ], + "doc": "The Expression that provides the value as a result.", + "doc_refs": [], + "corpus_elements": 3825, + "corpus_nonempty": 3825, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": true, + "rules": {}, + "corpus_elements": 3825, + "corpus_nonempty": 3825 + }, + { + "name": "valueExpression", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "AssignmentActionUsage", + "type": "Expression", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose result is to be assigned to the referent Feature.", + "doc_refs": [ + "Expression", + "Feature", + "referent" + ], + "corpus_elements": 27, + "corpus_nonempty": 27, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "AssignmentActionUsage": "valueExpression = argument(2)" + }, + "corpus_elements": 27, + "corpus_nonempty": 27 + }, + { + "name": "variant", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "Usage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The Usages which represent the variants of this Usage as a variation point Usage, if isVariation = true. If isVariation = false, then there must be no variants.", + "doc_refs": [ + "Usage", + "Usages", + "variants" + ], + "corpus_elements": 8045, + "corpus_nonempty": 22, + "class": "structural" + }, + { + "metaclass": "Definition", + "type": "Usage", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The Usages which represent the variants of this Definition as a variation point Definition, if isVariation = true. If isVariation = false, the there must be no variants.", + "doc_refs": [ + "Definition", + "Usages", + "isVariation", + "variants" + ], + "corpus_elements": 1354, + "corpus_nonempty": 25, + "class": "structural" + } + ], + "concrete_carriers": 73, + "also_owned_elsewhere": false, + "rules": { + "Usage": "variant = variantMembership.ownedVariantUsage", + "Definition": "variant = variantMembership.ownedVariantUsage" + }, + "corpus_elements": 9399, + "corpus_nonempty": 47 + }, + { + "name": "variantMembership", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "Usage", + "type": "VariantMembership", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedMembership" + ], + "redefines": [], + "doc": "The ownedMemberships of this Usage that are VariantMemberships. If isVariation = true, then this must be all memberships of the Usage. If isVariation = false, then variantMembershipmust be empty.", + "doc_refs": [ + "Usage", + "VariantMemberships", + "memberships", + "ownedMemberships", + "variantMembership" + ], + "corpus_elements": 8045, + "corpus_nonempty": 22, + "class": "structural" + }, + { + "metaclass": "Definition", + "type": "VariantMembership", + "multiplicity": "0..*", + "ordered": false, + "subsets": [ + "ownedMembership" + ], + "redefines": [], + "doc": "The ownedMemberships of this Definition that are VariantMemberships. If isVariation = true, then this must be all ownedMemberships of the Definition. If isVariation = false, then variantMembershipmust be empty.", + "doc_refs": [ + "Definition", + "VariantMemberships", + "isVariation", + "ownedMemberships", + "variantMembership" + ], + "corpus_elements": 1354, + "corpus_nonempty": 25, + "class": "structural" + } + ], + "concrete_carriers": 73, + "also_owned_elsewhere": false, + "rules": { + "Usage": "variantMembership = ownedMembership->selectByKind(VariantMembership)", + "Definition": "variantMembership = ownedMembership->selectByKind(VariantMembership)" + }, + "corpus_elements": 9399, + "corpus_nonempty": 47 + }, + { + "name": "verificationCaseDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "VerificationCaseUsage", + "type": "VerificationCaseDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [ + "caseDefinition" + ], + "redefines": [], + "doc": "The VerificationCase that is the definition of this VerificationCaseUsage.", + "doc_refs": [ + "VerificationCase", + "VerificationCaseUsage", + "definition" + ], + "corpus_elements": 7, + "corpus_nonempty": 6, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 7, + "corpus_nonempty": 6 + }, + { + "name": "verifiedRequirement", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "RequirementVerificationMembership", + "type": "RequirementUsage", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [ + "referencedConstraint" + ], + "doc": "The RequirementUsage that is identified as being verified. It is the referencedConstraint of the RequirementVerificationMembership considered as a RequirementConstraintMembership, which must be a RequirementUsage.", + "doc_refs": [ + "RequirementConstraintMembership", + "RequirementUsage", + "RequirementVerificationMembership", + "referencedConstraint" + ], + "corpus_elements": 6, + "corpus_nonempty": 6, + "class": "structural" + }, + { + "metaclass": "VerificationCaseDefinition", + "type": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The RequirementUsages verified by this VerificationCaseDefinition, which are the verifiedRequirements of all RequirementVerificationMemberships of the objectiveRequirement.", + "doc_refs": [ + "RequirementUsages", + "RequirementVerificationMemberships", + "VerificationCaseDefinition", + "objectiveRequirement", + "verifiedRequirements" + ], + "corpus_elements": 8, + "corpus_nonempty": 4, + "class": "inheritance-aware" + }, + { + "metaclass": "VerificationCaseUsage", + "type": "RequirementUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The RequirementUsages verified by this VerificationCaseUsage, which are the verifiedRequirements of all RequirementVerificationMemberships of the objectiveRequirement.", + "doc_refs": [ + "RequirementUsages", + "RequirementVerificationMemberships", + "VerificationCaseUsage", + "objectiveRequirement", + "verifiedRequirements" + ], + "corpus_elements": 7, + "corpus_nonempty": 2, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 3, + "also_owned_elsewhere": false, + "rules": { + "VerificationCaseDefinition": "verifiedRequirement = if objectiveRequirement = null then OrderedSet{} else objectiveRequirement.featureMembership-> selectByKind(RequirementVerificationMembership). verifiedRequirement->asOrderedSet() endif", + "VerificationCaseUsage": "verifiedRequirement = if objectiveRequirement = null then OrderedSet{} else objectiveRequirement.featureMembership-> selectByKind(RequirementVerificationMembership). verifiedRequirement->asOrderedSet() endif" + }, + "corpus_elements": 21, + "corpus_nonempty": 12 + }, + { + "name": "view", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewDefinition", + "type": "ViewUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "usage" + ], + "redefines": [], + "doc": "The usages of this ViewDefinition that are ViewUsages.", + "doc_refs": [ + "ViewDefinition", + "ViewUsages", + "usages" + ], + "corpus_elements": 10, + "corpus_nonempty": 1, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "ViewDefinition": "view = usage->selectByKind(ViewUsage)" + }, + "corpus_elements": 10, + "corpus_nonempty": 1 + }, + { + "name": "viewCondition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewUsage", + "type": "Expression", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The Expressions related to this ViewUsage by ElementFilterMemberships, which specify conditions on Elements to be rendered in a view.", + "doc_refs": [ + "ElementFilterMemberships", + "Elements", + "Expressions", + "ViewUsage" + ], + "corpus_elements": 12, + "corpus_nonempty": 2, + "class": "structural" + }, + { + "metaclass": "ViewDefinition", + "type": "Expression", + "multiplicity": "0..*", + "ordered": true, + "subsets": [ + "ownedMember" + ], + "redefines": [], + "doc": "The Expressions related to this ViewDefinition by ElementFilterMemberships, which specify conditions on Elements to be rendered in a view.", + "doc_refs": [ + "ElementFilterMemberships", + "Elements", + "Expressions", + "ViewDefinition" + ], + "corpus_elements": 10, + "corpus_nonempty": 4, + "class": "structural" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "ViewUsage": "viewCondition = ownedMembership-> selectByKind(ElementFilterMembership). condition", + "ViewDefinition": "viewCondition = ownedMembership-> selectByKind(ElementFilterMembership). condition" + }, + "corpus_elements": 22, + "corpus_nonempty": 6 + }, + { + "name": "viewDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewUsage", + "type": "ViewDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "partDefinition" + ], + "doc": "The ViewDefinition that is the definition of this ViewUsage.", + "doc_refs": [ + "ViewDefinition", + "ViewUsage", + "definition" + ], + "corpus_elements": 12, + "corpus_nonempty": 7, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 12, + "corpus_nonempty": 7 + }, + { + "name": "viewRendering", + "class": "inheritance-aware", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewUsage", + "type": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The RenderingUsage to be used to render views defined by this ViewUsage, which is the referencedRendering of the ViewRenderingMembership of the ViewUsage.", + "doc_refs": [ + "RenderingUsage", + "ViewRenderingMembership", + "ViewUsage", + "referencedRendering" + ], + "corpus_elements": 12, + "corpus_nonempty": 8, + "class": "inheritance-aware" + }, + { + "metaclass": "ViewDefinition", + "type": "RenderingUsage", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The RenderingUsage to be used to render views defined by this ViewDefinition, which is the referencedRendering of the ViewRenderingMembership of the ViewDefinition.", + "doc_refs": [ + "RenderingUsage", + "ViewDefinition", + "ViewRenderingMembership", + "referencedRendering" + ], + "corpus_elements": 10, + "corpus_nonempty": 3, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "ViewUsage": "viewRendering = let renderings: OrderedSet(ViewRenderingMembership) = featureMembership->selectByKind(ViewRenderingMembership) in if renderings->isEmpty() then null else renderings->first().referencedRendering endif", + "ViewDefinition": "viewRendering = let renderings: OrderedSet(ViewRenderingMembership) = featureMembership->selectByKind(ViewRenderingMembership) in if renderings->isEmpty() then null else renderings->first().referencedRendering endif" + }, + "corpus_elements": 22, + "corpus_nonempty": 11 + }, + { + "name": "viewpointDefinition", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "ViewpointUsage", + "type": "ViewpointDefinition", + "multiplicity": "0..1", + "ordered": false, + "subsets": [], + "redefines": [ + "requirementDefinition" + ], + "doc": "The ViewpointDefinition that is the definition of this ViewpointUsage.", + "doc_refs": [ + "ViewpointDefinition", + "definition" + ], + "corpus_elements": 3, + "corpus_nonempty": 1, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": {}, + "corpus_elements": 3, + "corpus_nonempty": 1 + }, + { + "name": "viewpointStakeholder", + "class": "inheritance-aware", + "status": "absent", + "declaring": [ + { + "metaclass": "ViewpointDefinition", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The PartUsages that identify the stakeholders with concerns framed by this ViewpointDefinition, which are the owned and inherited stakeholderParameters of the framedConcerns of this ViewpointDefinition.", + "doc_refs": [ + "PartUsages", + "ViewpointDefinition", + "framedConcerns", + "stakeholderParameters" + ], + "corpus_elements": 3, + "corpus_nonempty": 0, + "class": "inheritance-aware" + }, + { + "metaclass": "ViewpointUsage", + "type": "PartUsage", + "multiplicity": "0..*", + "ordered": true, + "subsets": [], + "redefines": [], + "doc": "The PartUsages that identify the stakeholders with concerns framed by this ViewpointUsage, which are the owned and inherited stakeholderParameters of the framedConcerns of this ViewpointUsage.", + "doc_refs": [ + "PartUsages", + "ViewpointUsage", + "framedConcerns", + "stakeholderParameters" + ], + "corpus_elements": 3, + "corpus_nonempty": 0, + "class": "inheritance-aware" + } + ], + "concrete_carriers": 2, + "also_owned_elsewhere": false, + "rules": { + "ViewpointDefinition": "viewpointStakeholder = framedConcern.featureMemberhsip-> selectByKind(StakeholderMembership). ownedStakeholderParameter", + "ViewpointUsage": "viewpointStakeholder = framedConcern.featureMemberhsip-> selectByKind(StakeholderMembership). ownedStakeholderParameter" + }, + "corpus_elements": 6, + "corpus_nonempty": 0 + }, + { + "name": "whileArgument", + "class": "structural", + "status": "derived", + "declaring": [ + { + "metaclass": "WhileLoopActionUsage", + "type": "Expression", + "multiplicity": "1..1", + "ordered": false, + "subsets": [], + "redefines": [], + "doc": "The Expression whose result, if true, determines that the bodyAction should continue to be performed. It is the first owned parameter of the WhileLoopActionUsage.", + "doc_refs": [ + "Expression", + "WhileLoopActionUsage", + "bodyAction", + "parameter" + ], + "corpus_elements": 5, + "corpus_nonempty": 2, + "class": "structural" + } + ], + "concrete_carriers": 1, + "also_owned_elsewhere": false, + "rules": { + "WhileLoopActionUsage": "whileArgument = let parameter : Feature = inputParameter(1) in if parameter <> null and parameter.oclIsKindOf(Expression) then parameter.oclAsType(Expression) else null endif " + }, + "corpus_elements": 5, + "corpus_nonempty": 2 + } + ] +} diff --git a/spec-refs/derived-properties.md b/spec-refs/derived-properties.md new file mode 100644 index 0000000..5a32674 --- /dev/null +++ b/spec-refs/derived-properties.md @@ -0,0 +1,304 @@ +# Derived properties — census + +Generated by `tools/derived_census.py` from `spec-refs/{KerML,SysML}.xmi` (20250201), the full-form emitter and the corpus baseline. Do not edit; regenerate after changing the emitter and refreshing the baseline. The JSON twin `derived-properties.json` carries the per-declaration facts (type, multiplicity, subsets, redefines, OCL rule). + +279 distinct derived property names. Status: **derived** = the corpus emits a non-empty value for it on a metaclass where it is derived (the primary evidence — the emitter writes some names without a literal, through the membership required-reference alias); **unexercised** = the emitter writes the name but the corpus never emits a non-empty value (a placeholder such as the `result` self-reference, or a shape only foreign payloads carry); **absent** = never written, so it falls to the catalog's type-correct empty default. + +| Class | Total | derived | unexercised | absent | +|---|---|---|---|---| +| structural | 222 | 197 | 6 | 19 | +| inheritance-aware | 53 | 50 | 0 | 3 | +| closure | 4 | 0 | 0 | 4 | +| **all** | 279 | 247 | 6 | 26 | + +A *closure* is one of the four inheritance/import closures; an *inheritance-aware* property is one whose derivation rule (or, for a property without an OCL rule, the property it redefines, or its normative documentation's direct closure reference) transitively reads a closure, so its passthrough-level value is an owned-only approximation until the closure policy is on; everything else is *structural*. Hand adjudications: `expression` → inheritance-aware. A name's class is the strongest over its declarations; names whose declarations disagree: `action`, `targetFeature`, `verifiedRequirement`. + +Names that are derived on one metaclass and owned on another (corpus fill counts only the derived carriers, and an emitter mention of such a name may be a read of the owned spelling): `annotatedElement`, `chainingFeature`, `conjugatedPortDefinition`, `differencingType`, `featuringType`, `importedMembership`, `intersectingType`, `originalPortDefinition`, `source`, `target`, `type`, `unioningType`, `value`. + +## Inheritance-aware names + +`action`, `actorParameter`, `allocation`, `argument`, `associationEnd`, `calculation`, `connectionEnd`, `connectorEnd`, `defaultFeaturingType`, `directedFeature`, `directedUsage`, `endFeature`, `exposedElement`, `expression`, `feature`, `featureMembership`, `flowEnd`, `framedConcern`, `input`, `interfaceEnd`, `member`, `membership`, `objectiveRequirement`, `output`, `parameter`, `payloadArgument`, `payloadParameter`, `receiverArgument`, `relatedFeature`, `relatedType`, `rendering`, `result`, `satisfyingFeature`, `senderArgument`, `seqArgument`, `sourceFeature`, `sourceOutputFeature`, `sourceType`, `stakeholderParameter`, `state`, `step`, `subjectParameter`, `targetArgument`, `targetFeature`, `targetInputFeature`, `targetType`, `terminatedOccurrenceArgument`, `usage`, `valueExpression`, `verifiedRequirement`, `view`, `viewRendering`, `viewpointStakeholder` + +## Every derived name + +| Name | Class | Status | Declared by | Carriers | Type | Corpus non-empty / elements | +|---|---|---|---|---|---|---| +| `action` | inheritance-aware | derived | StateSubactionMembership, ActionDefinition | 9 | ActionUsage | 88 / 257 | +| `actionDefinition` | structural | derived | ActionUsage | 24 | Behavior | 273 / 1124 | +| `actorParameter` | inheritance-aware | derived | RequirementUsage, RequirementDefinition, CaseUsage, CaseDefinition | 16 | PartUsage | 22 / 303 | +| `allocation` | inheritance-aware | absent | AllocationDefinition | 1 | AllocationUsage | 0 / 5 | +| `allocationDefinition` | structural | derived | AllocationUsage | 1 | AllocationDefinition | 5 / 18 | +| `analysisCaseDefinition` | structural | derived | AnalysisCaseUsage | 1 | AnalysisCaseDefinition | 24 / 26 | +| `annotatedElement` | structural | derived | AnnotatingElement | 6 | Element | 632 / 632 | +| `annotatingElement` | structural | derived | Annotation | 1 | AnnotatingElement | 19 / 19 | +| `annotation` | structural | derived | AnnotatingElement | 6 | Annotation | 16 / 632 | +| `argument` | inheritance-aware | derived | InstantiationExpression | 8 | Expression | 1585 / 1605 | +| `assertedConstraint` | structural | derived | AssertConstraintUsage | 2 | ConstraintUsage | 22 / 69 | +| `association` | structural | derived | Connector | 12 | Association | 63 / 689 | +| `associationEnd` | inheritance-aware | derived | Association | 7 | Feature | 46 / 50 | +| `assumedConstraint` | structural | derived | RequirementUsage, RequirementDefinition | 7 | ConstraintUsage | 19 / 208 | +| `attributeDefinition` | structural | derived | AttributeUsage | 2 | DataType | 778 / 869 | +| `behavior` | structural | derived | Step | 53 | Behavior | 400 / 6120 | +| `bodyAction` | structural | derived | LoopActionUsage | 2 | ActionUsage | 5 / 8 | +| `bound` | structural | derived | MultiplicityRange | 1 | Expression | 576 / 576 | +| `calculation` | inheritance-aware | derived | CalculationDefinition | 5 | CalculationUsage | 6 / 69 | +| `calculationDefinition` | structural | derived | CalculationUsage | 6 | Function | 68 / 96 | +| `caseDefinition` | structural | derived | CaseUsage | 5 | CaseDefinition | 44 / 65 | +| `chainingFeature` | structural | derived | Feature | 79 | Feature | 588 / 16951 | +| `concernDefinition` | structural | derived | ConcernUsage | 1 | ConcernDefinition | 3 / 11 | +| `condition` | structural | derived | ElementFilterMembership | 1 | Expression | 26 / 26 | +| `conjugatedPortDefinition` | structural | derived | PortConjugation, PortDefinition | 3 | ConjugatedPortDefinition | 182 / 273 | +| `connectionDefinition` | structural | derived | ConnectionUsage | 3 | AssociationStructure | 52 / 127 | +| `connectionEnd` | inheritance-aware | derived | ConnectionDefinition | 3 | Usage | 45 / 48 | +| `connectorEnd` | inheritance-aware | derived | Connector | 12 | Feature | 670 / 689 | +| `constraintDefinition` | structural | derived | ConstraintUsage | 6 | Predicate | 127 / 291 | +| `crossFeature` | structural | derived | Feature | 79 | Feature | 2 / 16951 | +| `crossingFeature` | structural | derived | CrossSubsetting | 1 | Feature | 2 / 2 | +| `defaultFeaturingType` | inheritance-aware | derived | Connector | 12 | Type | 475 / 689 | +| `definition` | structural | derived | Usage | 47 | Classifier | 4244 / 8045 | +| `differencingType` | structural | absent | Type | 117 | Type | 0 / 18305 | +| `directedFeature` | inheritance-aware | derived | Type | 117 | Feature | 2635 / 18305 | +| `directedUsage` | inheritance-aware | derived | Usage, Definition | 73 | Usage | 758 / 9399 | +| `doAction` | structural | derived | StateUsage, StateDefinition | 3 | ActionUsage | 18 / 177 | +| `documentation` | structural | derived | Element | 167 | Documentation | 156 / 52148 | +| `documentedElement` | structural | derived | Documentation | 1 | Element | 157 / 157 | +| `effectAction` | structural | derived | TransitionUsage | 1 | ActionUsage | 20 / 111 | +| `elseAction` | structural | derived | IfActionUsage | 1 | ActionUsage | 2 / 4 | +| `endFeature` | inheritance-aware | derived | Type | 117 | Feature | 716 / 18305 | +| `endOwningType` | structural | derived | Feature | 79 | Type | 1420 / 16951 | +| `entryAction` | structural | derived | StateUsage, StateDefinition | 3 | ActionUsage | 31 / 177 | +| `enumeratedValue` | structural | derived | EnumerationDefinition | 1 | EnumerationUsage | 18 / 19 | +| `enumerationDefinition` | structural | derived | EnumerationUsage | 1 | EnumerationDefinition | 54 / 55 | +| `eventOccurrence` | structural | derived | EventOccurrenceUsage | 4 | OccurrenceUsage | 184 / 324 | +| `exhibitedState` | structural | derived | ExhibitStateUsage | 1 | StateUsage | 10 / 29 | +| `exitAction` | structural | derived | StateUsage, StateDefinition | 3 | ActionUsage | 7 / 177 | +| `exposedElement` | inheritance-aware | derived | ViewUsage | 1 | Element | 5 / 12 | +| `expression` | inheritance-aware | derived | Function | 11 | Expression | 56 / 127 | +| `feature` | inheritance-aware | derived | Type | 117 | Feature | 4942 / 18305 | +| `featureChained` | structural | derived | FeatureChaining | 1 | Feature | 1331 / 1331 | +| `featureMembership` | inheritance-aware | derived | Type | 117 | FeatureMembership | 4942 / 18305 | +| `featureTarget` | structural | derived | Feature | 79 | Feature | 588 / 16951 | +| `featureWithValue` | structural | derived | FeatureValue | 1 | Feature | 3825 / 3825 | +| `featuringType` | closure | absent | Feature | 79 | Type | 0 / 16951 | +| `filterCondition` | structural | derived | Package | 2 | Expression | 20 / 481 | +| `flowDefinition` | structural | derived | FlowUsage | 2 | Interaction | 8 / 142 | +| `flowEnd` | inheritance-aware | derived | Flow, FlowDefinition | 5 | FlowEnd, Usage | 122 / 144 | +| `framedConcern` | inheritance-aware | derived | RequirementUsage, RequirementDefinition | 7 | ConcernUsage | 5 / 208 | +| `function` | structural | derived | Expression | 32 | Function | 195 / 5092 | +| `guardExpression` | structural | derived | TransitionUsage | 1 | Expression | 21 / 111 | +| `ifArgument` | structural | derived | IfActionUsage | 1 | Expression | 4 / 4 | +| `importOwningNamespace` | structural | derived | Import | 4 | Namespace | 566 / 566 | +| `importedElement` | structural | derived | Import | 4 | Element | 566 / 566 | +| `importedMembership` | closure | absent | Namespace | 120 | Membership | 0 / 19037 | +| `includedUseCase` | structural | derived | UseCaseUsage, UseCaseDefinition | 3 | UseCaseUsage | 7 / 40 | +| `individualDefinition` | structural | derived | OccurrenceUsage | 41 | OccurrenceDefinition | 61 / 3627 | +| `inheritedFeature` | closure | absent | Type | 117 | Feature | 0 / 18305 | +| `inheritedMembership` | closure | absent | Type | 117 | Membership | 0 / 18305 | +| `input` | inheritance-aware | derived | Type | 117 | Feature | 2414 / 18305 | +| `instantiatedType` | structural | derived | InstantiationExpression | 8 | Type | 1605 / 1605 | +| `interaction` | structural | derived | Flow | 4 | Interaction | 8 / 142 | +| `interfaceDefinition` | structural | derived | InterfaceUsage | 1 | InterfaceDefinition | 28 / 37 | +| `interfaceEnd` | inheritance-aware | derived | InterfaceDefinition | 1 | PortUsage | 17 / 17 | +| `intersectingType` | structural | absent | Type | 117 | Type | 0 / 18305 | +| `isConjugated` | structural | derived | Type | 117 | Boolean | 91 / 18305 | +| `isLibraryElement` | structural | derived | Element | 167 | Boolean | 1093 / 52148 | +| `isModelLevelEvaluable` | structural | derived | Expression, Function | 43 | Boolean | 2441 / 5219 | +| `isReference` | structural | derived | EventOccurrenceUsage, Usage, ReferenceUsage, AttributeUsage | 47 | Boolean | 5766 / 8045 | +| `itemDefinition` | structural | derived | ItemUsage | 8 | Structure | 1125 / 1605 | +| `loopVariable` | structural | derived | ForLoopActionUsage | 1 | ReferenceUsage | 3 / 3 | +| `lowerBound` | structural | derived | MultiplicityRange | 1 | Expression | 116 / 576 | +| `mayTimeVary` | structural | derived | Usage | 47 | Boolean | 1212 / 8045 | +| `member` | inheritance-aware | derived | Namespace | 120 | Element | 12491 / 19037 | +| `memberElementId` | structural | derived | Membership | 20 | String | 21066 / 21066 | +| `membership` | inheritance-aware | derived | Namespace | 120 | Membership | 12491 / 19037 | +| `membershipOwningNamespace` | structural | derived | Membership | 20 | Namespace | 21066 / 21066 | +| `metaclass` | structural | derived | MetadataFeature | 2 | Metaclass | 179 / 179 | +| `metadataDefinition` | structural | derived | MetadataUsage | 1 | Metaclass | 179 / 179 | +| `multiplicity` | structural | derived | Type | 117 | Multiplicity | 576 / 18305 | +| `name` | structural | derived | Element | 167 | String | 9724 / 52148 | +| `nestedAction` | structural | derived | Usage | 47 | ActionUsage | 379 / 8045 | +| `nestedAllocation` | structural | derived | Usage | 47 | AllocationUsage | 9 / 8045 | +| `nestedAnalysisCase` | structural | derived | Usage | 47 | AnalysisCaseUsage | 7 / 8045 | +| `nestedAttribute` | structural | derived | Usage | 47 | AttributeUsage | 217 / 8045 | +| `nestedCalculation` | structural | derived | Usage | 47 | CalculationUsage | 27 / 8045 | +| `nestedCase` | structural | derived | Usage | 47 | CaseUsage | 14 / 8045 | +| `nestedConcern` | structural | derived | Usage | 47 | ConcernUsage | 3 / 8045 | +| `nestedConnection` | structural | derived | Usage | 47 | ConnectorAsUsage | 169 / 8045 | +| `nestedConstraint` | structural | derived | Usage | 47 | ConstraintUsage | 113 / 8045 | +| `nestedEnumeration` | structural | absent | Usage | 47 | EnumerationUsage | 0 / 8045 | +| `nestedFlow` | structural | absent | Usage | 47 | FlowUsage | 0 / 8045 | +| `nestedInterface` | structural | derived | Usage | 47 | InterfaceUsage | 1290 / 8045 | +| `nestedItem` | structural | derived | Usage | 47 | ItemUsage | 407 / 8045 | +| `nestedMetadata` | structural | absent | Usage | 47 | MetadataUsage | 0 / 8045 | +| `nestedOccurrence` | structural | derived | Usage | 47 | OccurrenceUsage | 1004 / 8045 | +| `nestedPart` | structural | derived | Usage | 47 | PartUsage | 342 / 8045 | +| `nestedPort` | structural | derived | Usage | 47 | PortUsage | 154 / 8045 | +| `nestedReference` | structural | derived | Usage | 47 | ReferenceUsage | 1290 / 8045 | +| `nestedRendering` | structural | derived | Usage | 47 | RenderingUsage | 8 / 8045 | +| `nestedRequirement` | structural | derived | Usage | 47 | RequirementUsage | 57 / 8045 | +| `nestedState` | structural | derived | Usage | 47 | StateUsage | 64 / 8045 | +| `nestedTransition` | structural | derived | Usage | 47 | TransitionUsage | 32 / 8045 | +| `nestedUsage` | structural | derived | Usage | 47 | Usage | 2207 / 8045 | +| `nestedUseCase` | structural | derived | Usage | 47 | UseCaseUsage | 6 / 8045 | +| `nestedVerificationCase` | structural | derived | Usage | 47 | VerificationCaseUsage | 1 / 8045 | +| `nestedView` | structural | derived | Usage | 47 | ViewUsage | 3 / 8045 | +| `nestedViewpoint` | structural | absent | Usage | 47 | ViewpointUsage | 0 / 8045 | +| `objectiveRequirement` | inheritance-aware | derived | CaseUsage, CaseDefinition | 9 | RequirementUsage | 26 / 95 | +| `occurrenceDefinition` | structural | derived | OccurrenceUsage | 41 | Class | 1918 / 3627 | +| `originalPortDefinition` | structural | derived | ConjugatedPortDefinition | 1 | PortDefinition | 91 / 91 | +| `output` | inheritance-aware | derived | Type | 117 | Feature | 584 / 18305 | +| `ownedAction` | structural | derived | Definition | 26 | ActionUsage | 73 / 1354 | +| `ownedActorParameter` | structural | derived | ActorMembership | 1 | PartUsage | 42 / 42 | +| `ownedAllocation` | structural | absent | Definition | 26 | AllocationUsage | 0 / 1354 | +| `ownedAnalysisCase` | structural | derived | Definition | 26 | AnalysisCaseUsage | 2 / 1354 | +| `ownedAnnotatingElement` | structural | unexercised | Annotation | 1 | AnnotatingElement | 0 / 19 | +| `ownedAnnotatingRelationship` | structural | derived | AnnotatingElement | 6 | Annotation | 16 / 632 | +| `ownedAnnotation` | structural | unexercised | Element | 167 | Annotation | 0 / 52148 | +| `ownedAttribute` | structural | derived | Definition | 26 | AttributeUsage | 219 / 1354 | +| `ownedCalculation` | structural | derived | Definition | 26 | CalculationUsage | 7 / 1354 | +| `ownedCase` | structural | derived | Definition | 26 | CaseUsage | 5 / 1354 | +| `ownedConcern` | structural | derived | FramedConcernMembership, Definition | 27 | ConcernUsage | 8 / 1360 | +| `ownedConjugator` | structural | derived | Type | 117 | Conjugation | 91 / 18305 | +| `ownedConnection` | structural | derived | Definition | 26 | ConnectorAsUsage | 42 / 1354 | +| `ownedConstraint` | structural | derived | RequirementConstraintMembership, Definition | 29 | ConstraintUsage | 127 / 1420 | +| `ownedCrossSubsetting` | structural | derived | Feature | 79 | CrossSubsetting | 2 / 16951 | +| `ownedDifferencing` | structural | absent | Type | 117 | Differencing | 0 / 18305 | +| `ownedDisjoining` | structural | unexercised | Type | 117 | Disjoining | 0 / 18305 | +| `ownedElement` | structural | derived | Element | 167 | Element | 11182 / 52148 | +| `ownedEndFeature` | structural | derived | Type | 117 | Feature | 716 / 18305 | +| `ownedEnumeration` | structural | absent | Definition | 26 | EnumerationUsage | 0 / 1354 | +| `ownedFeature` | structural | derived | Type | 117 | Feature | 4942 / 18305 | +| `ownedFeatureChaining` | structural | derived | Feature | 79 | FeatureChaining | 588 / 16951 | +| `ownedFeatureInverting` | structural | absent | Feature | 79 | FeatureInverting | 0 / 16951 | +| `ownedFeatureMembership` | structural | derived | Type | 117 | FeatureMembership | 4942 / 18305 | +| `ownedFlow` | structural | absent | Definition | 26 | FlowUsage | 0 / 1354 | +| `ownedImport` | structural | derived | Namespace | 120 | Import | 279 / 19037 | +| `ownedInterface` | structural | derived | Definition | 26 | InterfaceUsage | 265 / 1354 | +| `ownedIntersecting` | structural | absent | Type | 117 | Intersecting | 0 / 18305 | +| `ownedItem` | structural | derived | Definition | 26 | ItemUsage | 151 / 1354 | +| `ownedMember` | structural | derived | Namespace | 120 | Element | 10764 / 19037 | +| `ownedMemberElement` | structural | derived | OwningMembership | 19 | Element | 18728 / 18728 | +| `ownedMemberElementId` | structural | derived | OwningMembership | 19 | String | 18728 / 18728 | +| `ownedMemberFeature` | structural | derived | FeatureMembership, EndFeatureMembership | 15 | Feature | 10203 / 10203 | +| `ownedMemberName` | structural | derived | OwningMembership | 19 | String | 9230 / 18728 | +| `ownedMemberParameter` | structural | derived | ParameterMembership | 5 | Feature | 3432 / 3432 | +| `ownedMemberShortName` | structural | derived | OwningMembership | 19 | String | 75 / 18728 | +| `ownedMembership` | structural | derived | Namespace | 120 | Membership | 12491 / 19037 | +| `ownedMetadata` | structural | absent | Definition | 26 | MetadataUsage | 0 / 1354 | +| `ownedObjectiveRequirement` | structural | derived | ObjectiveMembership | 1 | RequirementUsage | 26 / 26 | +| `ownedOccurrence` | structural | derived | Definition | 26 | OccurrenceUsage | 301 / 1354 | +| `ownedPart` | structural | derived | Definition | 26 | PartUsage | 107 / 1354 | +| `ownedPort` | structural | derived | Definition | 26 | PortUsage | 76 / 1354 | +| `ownedPortConjugator` | structural | derived | ConjugatedPortDefinition | 1 | PortConjugation | 91 / 91 | +| `ownedRedefinition` | structural | derived | Feature | 79 | Redefinition | 1294 / 16951 | +| `ownedReference` | structural | derived | Definition | 26 | ReferenceUsage | 265 / 1354 | +| `ownedReferenceSubsetting` | structural | derived | Feature | 79 | ReferenceSubsetting | 1164 / 16951 | +| `ownedRendering` | structural | derived | Definition, ViewRenderingMembership | 27 | RenderingUsage | 14 / 1365 | +| `ownedRequirement` | structural | derived | Definition, RequirementVerificationMembership | 27 | RequirementUsage | 29 / 1360 | +| `ownedResultExpression` | structural | derived | ResultExpressionMembership | 1 | Expression | 105 / 105 | +| `ownedSpecialization` | structural | derived | Type | 117 | Specialization | 7923 / 18305 | +| `ownedStakeholderParameter` | structural | derived | StakeholderMembership | 1 | PartUsage | 7 / 7 | +| `ownedState` | structural | derived | Definition | 26 | StateUsage | 19 / 1354 | +| `ownedSubclassification` | structural | derived | Classifier | 37 | Subclassification | 1150 / 1354 | +| `ownedSubjectParameter` | structural | derived | SubjectMembership | 1 | Usage | 122 / 122 | +| `ownedSubsetting` | structural | derived | Feature | 79 | Subsetting | 5513 / 16951 | +| `ownedTransition` | structural | derived | Definition | 26 | TransitionUsage | 6 / 1354 | +| `ownedTypeFeaturing` | structural | absent | Feature | 79 | TypeFeaturing | 0 / 16951 | +| `ownedTyping` | structural | derived | Feature | 79 | FeatureTyping | 2780 / 16951 | +| `ownedUnioning` | structural | absent | Type | 117 | Unioning | 0 / 18305 | +| `ownedUsage` | structural | derived | Definition | 26 | Usage | 660 / 1354 | +| `ownedUseCase` | structural | derived | Definition | 26 | UseCaseUsage | 2 / 1354 | +| `ownedVariantUsage` | structural | derived | VariantMembership | 1 | Usage | 107 / 107 | +| `ownedVerificationCase` | structural | derived | Definition | 26 | VerificationCaseUsage | 1 / 1354 | +| `ownedView` | structural | derived | Definition | 26 | ViewUsage | 1 / 1354 | +| `ownedViewpoint` | structural | derived | Definition | 26 | ViewpointUsage | 1 / 1354 | +| `owner` | structural | derived | Element | 167 | Element | 19249 / 52148 | +| `owningAnnotatedElement` | structural | unexercised | Annotation | 1 | Element | 0 / 19 | +| `owningAnnotatingElement` | structural | derived | Annotation | 1 | AnnotatingElement | 19 / 19 | +| `owningAnnotatingRelationship` | structural | unexercised | AnnotatingElement | 6 | Annotation | 0 / 632 | +| `owningClassifier` | structural | derived | Subclassification | 1 | Classifier | 1151 / 1151 | +| `owningDefinition` | structural | derived | Usage | 47 | Definition | 1703 / 8045 | +| `owningFeature` | structural | derived | FeatureInverting, Subsetting, FeatureTyping | 7 | Feature | 8424 / 8424 | +| `owningFeatureMembership` | structural | derived | Feature | 79 | FeatureMembership | 10203 / 16951 | +| `owningFeatureOfType` | structural | unexercised | TypeFeaturing | 1 | Feature | 0 / 0 | +| `owningMembership` | structural | derived | Element | 167 | OwningMembership | 18728 / 52148 | +| `owningNamespace` | structural | derived | Element | 167 | Namespace | 18728 / 52148 | +| `owningType` | structural | derived | Disjoining, FeatureMembership, Conjugation, Specialization, Feature | 105 | Type | 30072 / 36820 | +| `owningUsage` | structural | derived | Usage | 47 | Usage | 5043 / 8045 | +| `parameter` | inheritance-aware | derived | Behavior, Step | 69 | Feature | 2320 / 6379 | +| `partDefinition` | structural | derived | PartUsage | 6 | PartDefinition | 798 / 1236 | +| `payloadArgument` | inheritance-aware | derived | AcceptActionUsage, SendActionUsage | 2 | Expression | 53 / 140 | +| `payloadFeature` | structural | derived | Flow | 4 | PayloadFeature | 48 / 142 | +| `payloadParameter` | inheritance-aware | derived | AcceptActionUsage | 1 | ReferenceUsage | 103 / 103 | +| `payloadType` | structural | derived | Flow | 4 | Classifier | 48 / 142 | +| `performedAction` | structural | derived | PerformActionUsage | 3 | ActionUsage | 113 / 195 | +| `portDefinition` | structural | derived | ConjugatedPortTyping, PortUsage | 2 | PortDefinition | 305 / 413 | +| `predicate` | structural | derived | BooleanExpression | 8 | Predicate | 127 / 291 | +| `qualifiedName` | structural | derived | Element | 167 | String | 7351 / 52148 | +| `receiverArgument` | inheritance-aware | derived | AcceptActionUsage, SendActionUsage | 2 | Expression | 45 / 140 | +| `referencedConcern` | structural | derived | FramedConcernMembership | 1 | ConcernUsage | 6 / 6 | +| `referencedConstraint` | structural | derived | RequirementConstraintMembership | 3 | ConstraintUsage | 66 / 66 | +| `referencedElement` | structural | derived | MetadataAccessExpression | 1 | Element | 27 / 27 | +| `referencedRendering` | structural | derived | ViewRenderingMembership | 1 | RenderingUsage | 11 / 11 | +| `referencingFeature` | structural | derived | ReferenceSubsetting | 1 | Feature | 1164 / 1164 | +| `referent` | structural | derived | FeatureReferenceExpression, AssignmentActionUsage | 2 | Feature | 1685 / 1749 | +| `relatedElement` | structural | derived | Relationship | 62 | Element | 32658 / 33397 | +| `relatedFeature` | inheritance-aware | derived | Connector | 12 | Feature | 531 / 689 | +| `relatedType` | inheritance-aware | derived | Association | 7 | Type | 44 / 50 | +| `rendering` | inheritance-aware | absent | RenderingDefinition | 1 | RenderingUsage | 0 / 1 | +| `renderingDefinition` | structural | derived | RenderingUsage | 1 | RenderingDefinition | 13 / 14 | +| `representedElement` | structural | derived | TextualRepresentation | 1 | Element | 91 / 91 | +| `requiredConstraint` | structural | derived | RequirementUsage, RequirementDefinition | 7 | ConstraintUsage | 39 / 208 | +| `requirementDefinition` | structural | derived | RequirementUsage | 4 | RequirementDefinition | 88 / 171 | +| `result` | inheritance-aware | derived | Expression, Function | 43 | Feature | 157 / 5219 | +| `resultExpression` | structural | derived | AnalysisCaseUsage, AnalysisCaseDefinition | 2 | Expression | 2 / 40 | +| `satisfiedRequirement` | structural | derived | SatisfyRequirementUsage | 1 | RequirementUsage | 18 / 22 | +| `satisfiedViewpoint` | structural | derived | ViewUsage, ViewDefinition | 2 | ViewpointUsage | 1 / 22 | +| `satisfyingFeature` | inheritance-aware | derived | SatisfyRequirementUsage | 1 | Feature | 19 / 22 | +| `senderArgument` | inheritance-aware | derived | SendActionUsage | 1 | Expression | 14 / 37 | +| `seqArgument` | inheritance-aware | derived | ForLoopActionUsage | 1 | Expression | 3 / 3 | +| `shortName` | structural | derived | Element | 167 | String | 77 / 52148 | +| `source` | structural | derived | TransitionUsage | 1 | ActionUsage | 52 / 111 | +| `sourceFeature` | inheritance-aware | derived | Connector | 12 | Feature | 531 / 689 | +| `sourceOutputFeature` | inheritance-aware | derived | Flow | 4 | Feature | 122 / 142 | +| `sourceType` | inheritance-aware | derived | Association | 7 | Type | 44 / 50 | +| `stakeholderParameter` | inheritance-aware | derived | RequirementUsage, RequirementDefinition | 7 | PartUsage | 6 / 208 | +| `state` | inheritance-aware | derived | StateDefinition | 1 | StateUsage | 4 / 17 | +| `stateDefinition` | structural | derived | StateUsage | 2 | Behavior | 24 / 160 | +| `step` | inheritance-aware | derived | Behavior | 16 | Step | 81 / 259 | +| `subjectParameter` | inheritance-aware | derived | RequirementUsage, RequirementDefinition, CaseUsage, CaseDefinition | 16 | Usage | 122 / 303 | +| `succession` | structural | derived | TransitionUsage | 1 | Succession | 111 / 111 | +| `target` | structural | derived | TransitionUsage | 1 | ActionUsage | 111 / 111 | +| `targetArgument` | inheritance-aware | derived | AssignmentActionUsage | 1 | Expression | 27 / 27 | +| `targetFeature` | inheritance-aware | derived | FeatureChainExpression, Connector | 13 | Feature | 805 / 1127 | +| `targetInputFeature` | inheritance-aware | derived | Flow | 4 | Feature | 122 / 142 | +| `targetType` | inheritance-aware | derived | Association | 7 | Type | 44 / 50 | +| `terminatedOccurrenceArgument` | inheritance-aware | derived | TerminateActionUsage | 1 | Expression | 3 / 6 | +| `text` | structural | derived | RequirementUsage, RequirementDefinition | 7 | String | 59 / 208 | +| `textualRepresentation` | structural | derived | Element | 167 | TextualRepresentation | 91 / 52148 | +| `thenAction` | structural | derived | IfActionUsage | 1 | ActionUsage | 4 / 4 | +| `transitionFeature` | structural | derived | TransitionFeatureMembership | 1 | Step | 121 / 121 | +| `triggerAction` | structural | derived | TransitionUsage | 1 | AcceptActionUsage | 80 / 111 | +| `type` | structural | derived | Feature | 79 | Type | 4906 / 16951 | +| `typeDifferenced` | structural | absent | Differencing | 1 | Type | 0 / 0 | +| `typeIntersected` | structural | absent | Intersecting | 1 | Type | 0 / 0 | +| `typeUnioned` | structural | absent | Unioning | 1 | Type | 0 / 0 | +| `unioningType` | structural | absent | Type | 117 | Type | 0 / 18305 | +| `untilArgument` | structural | derived | WhileLoopActionUsage | 1 | Expression | 1 / 5 | +| `upperBound` | structural | derived | MultiplicityRange | 1 | Expression | 576 / 576 | +| `usage` | inheritance-aware | derived | Usage, Definition | 73 | Usage | 2867 / 9399 | +| `useCaseDefinition` | structural | derived | UseCaseUsage | 2 | UseCaseDefinition | 14 / 32 | +| `useCaseIncluded` | structural | derived | IncludeUseCaseUsage | 1 | UseCaseUsage | 7 / 13 | +| `value` | structural | derived | FeatureValue | 1 | Expression | 3825 / 3825 | +| `valueExpression` | inheritance-aware | derived | AssignmentActionUsage | 1 | Expression | 27 / 27 | +| `variant` | structural | derived | Usage, Definition | 73 | Usage | 47 / 9399 | +| `variantMembership` | structural | derived | Usage, Definition | 73 | VariantMembership | 47 / 9399 | +| `verificationCaseDefinition` | structural | derived | VerificationCaseUsage | 1 | VerificationCaseDefinition | 6 / 7 | +| `verifiedRequirement` | inheritance-aware | derived | RequirementVerificationMembership, VerificationCaseDefinition, VerificationCaseUsage | 3 | RequirementUsage | 12 / 21 | +| `view` | inheritance-aware | derived | ViewDefinition | 1 | ViewUsage | 1 / 10 | +| `viewCondition` | structural | derived | ViewUsage, ViewDefinition | 2 | Expression | 6 / 22 | +| `viewDefinition` | structural | derived | ViewUsage | 1 | ViewDefinition | 7 / 12 | +| `viewRendering` | inheritance-aware | derived | ViewUsage, ViewDefinition | 2 | RenderingUsage | 11 / 22 | +| `viewpointDefinition` | structural | derived | ViewpointUsage | 1 | ViewpointDefinition | 1 / 3 | +| `viewpointStakeholder` | inheritance-aware | absent | ViewpointDefinition, ViewpointUsage | 2 | PartUsage | 0 / 6 | +| `whileArgument` | structural | derived | WhileLoopActionUsage | 1 | Expression | 2 / 5 | diff --git a/tools/derived_census.py b/tools/derived_census.py new file mode 100644 index 0000000..e4e9cb8 --- /dev/null +++ b/tools/derived_census.py @@ -0,0 +1,558 @@ +#!/usr/bin/env python3 +"""Census of the metamodel's derived properties against the toolkit. + +Reads the vendored normative metamodel XMI (spec-refs/KerML.xmi + +spec-refs/SysML.xmi, 20250201), the full-form emitter +(crates/sysmlv2-model/src/full.rs) and the corpus baseline the +`full_baseline` test maintains +(crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv), and writes + +- spec-refs/derived-properties.json — one record per derived property + name: declaring metaclasses, target type, multiplicity, subsetted and + redefined properties, the OCL derivation rule, the class the toolkit + computes it in, and its implementation status; +- spec-refs/derived-properties.md — the same as tables, with counts. + +The class is computed from the rules, not hand-listed: a property is a +*closure* when it is one of the four inheritance/import closures, an +*inheritance-aware* property when its derivation rule (transitively) +reads a closure or another inheritance-aware property, and *structural* +otherwise. Implementation status combines two evidence sources, because +neither alone is reliable: whether the emitter names the property (code +inspection) and how often the corpus emits a non-empty value for it +(fill rate). A name the emitter never mentions is *absent* whatever the +catalog default; a mentioned name with no non-empty corpus value is +*unexercised* and needs adjudication by hand. + +Usage: python3 tools/derived_census.py (from the workspace root) +""" + +import html +import json +import re +import subprocess +import sys +import xml.etree.ElementTree as ET +from collections import defaultdict +from pathlib import Path + +sys.dont_write_bytecode = True +sys.path.insert(0, str(Path(__file__).resolve().parent)) +from xmi_props import SOURCES, XMI_ID, XMI_IDREF, XMI_TYPE, closure, load, ref_of # noqa: E402 + +ROOT = Path(__file__).resolve().parents[1] +EMITTER = ROOT / "crates/sysmlv2-model/src/full.rs" +BASELINE = ROOT / "crates/sysmlv2-parser/tests/fixtures/full-form-baseline.tsv" +OUT_JSON = ROOT / "spec-refs/derived-properties.json" +OUT_MD = ROOT / "spec-refs/derived-properties.md" +OUT_RS = ROOT / "crates/sysmlv2-model/src/derived_names.rs" +OUT_COMPOSITIONS = ROOT / "crates/sysmlv2-model/src/json/derived_compositions.rs" + +# Bases the XMI spells that this metamodel version does not carry under +# that name, or misspells. +BASE_ALIASES = {"usages": "usage", "ownedGeneralization": "ownedSpecialization"} +# A rule whose left-hand side is misspelled (`ownedNested = nestedUsage->…` +# for `nestedEnumeration`): the rule is attributed to its property by +# constraint name already, so the left-hand side is only a guard. +LHS_ALIASES = {"ownedNested": "nestedEnumeration"} + +CLOSURES = {"inheritedMembership", "inheritedFeature", "importedMembership", "featuringType"} + +# Hand adjudications the mechanical rule cannot make. `subsets` does not +# propagate a class in general (`owningMembership` subsets `membership` +# structurally), but `Function::expression` — "the Expressions that are +# steps", subsetting `step`, no OCL rule — is a kind filter over the +# inheritance-aware `step`, the same shape as `calculation` over `action`. +CLASS_OVERRIDES = {"expression": "inheritance-aware"} + + +def strip_html(text): + return re.sub(r"\s+", " ", re.sub(r"<[^>]+>", "", html.unescape(text or ""))).strip() + + +def read_xmi(): + """Derived attributes with their facts, keyed by name, plus the rules.""" + ids = {} # xmi id -> element name (classes and properties) + derived = defaultdict(lambda: {"declaring": [], "types": set(), "rules": {}}) + rules_by_class = defaultdict(dict) # class name -> rule name -> body + roots = [(src, ET.parse(src).getroot()) for src in SOURCES] + for _, root in roots: + for el in root.iter(): + if el.get(XMI_ID) and el.get("name"): + ids[el.get(XMI_ID)] = el.get("name") + for _, root in roots: + for cls in root.iter("packagedElement"): + if cls.get(XMI_TYPE) != "uml:Class": + continue + cname = cls.get("name") + for rule in cls.findall("ownedRule"): + spec = rule.find("specification") + if spec is not None and spec.get("body"): + rules_by_class[cname][rule.get("name")] = html.unescape(spec.get("body")) + for a in cls.findall("ownedAttribute"): + if a.get(XMI_TYPE) != "uml:Property" or a.get("isDerived") != "true": + continue + name = a.get("name") + rec = derived[name] + lower = a.find("lowerValue") + upper = a.find("upperValue") + lo = int(lower.get("value") or 0) if lower is not None else 1 + up = (upper.get("value") or "1") if upper is not None else "1" + up = "*" if up == "-1" else up + tref = a.find("type") + tid = ref_of(tref) if tref is not None else None + # Primitive types live in PrimitiveTypes.xmi, outside `ids`. + tname = ids.get(tid, tid or "?") + comment = a.find("ownedComment") + raw_doc = html.unescape(comment.get("body") or "") if comment is not None else "" + rec["declaring"].append( + { + "metaclass": cname, + "type": tname, + "multiplicity": f"{lo}..{up}", + "ordered": a.get("isOrdered") == "true", + "subsets": sorted(ids.get(ref_of(s), "?") for s in a.findall("subsettedProperty")), + "redefines": sorted(ids.get(ref_of(r), "?") for r in a.findall("redefinedProperty")), + "doc": strip_html(raw_doc), + # The names the normative prose marks as code — the + # only tokens that stand for properties in a doc. + "doc_refs": sorted(set(re.findall(r"([A-Za-z_][A-Za-z0-9_]*)", raw_doc))), + } + ) + rec["types"].add(tname) + # Attach derivation rules: every `derive` rule, on the + # declaring class or on a subclass that refines the derivation + # (`deriveInvocationExpressionArgument` for InstantiationExpression's + # `argument`), plus any `derive*` rule whose body assigns the property. + for cname, rules in rules_by_class.items(): + for rname, body in rules.items(): + if not rname.startswith("derive"): + continue + assigned = re.match(r"\s*([A-Za-z_][A-Za-z0-9_]*)\s*=[^=]", body) + for name, rec in derived.items(): + cap = name[0].upper() + name[1:] + if rname == f"derive{cname}{cap}" or (assigned and assigned.group(1) == name): + rec["rules"][cname] = body + return derived + + +def emitter_mentions(): + """Property names the emitter *writes*. A literal that only ever + appears as a read (`get("x")`, `contains_key("x")`) is the owned + spelling being consulted, not a derivation.""" + text = EMITTER.read_text() + written = set() + for m in re.finditer(r'"([a-z][A-Za-z]+)"', text): + before = text[max(0, m.start() - 16) : m.start()] + if re.search(r'(?:get|get_mut|contains_key|remove)\(&?$|\[$', before): + continue + written.add(m.group(1)) + return written + + +def ancestors(classes): + """class name -> {names of its superclasses}, transitively.""" + by_id = {cid: c["name"] for cid, c in classes.items()} + gens = {c["name"]: [by_id[g] for g in c["generals"]] for c in classes.values()} + out = {} + + def walk(n): + if n in out: + return out[n] + acc = set() + for g in gens.get(n, ()): + acc.add(g) + acc |= walk(g) + out[n] = acc + return acc + + for n in gens: + walk(n) + return out + + +def descendants(classes): + """class name -> {names of it and every subclass}.""" + by_id = {cid: c["name"] for cid, c in classes.items()} + down = defaultdict(set) + for cid, c in classes.items(): + for g in c["generals"]: + down[by_id[g]].add(c["name"]) + out = {} + + def walk(n): + if n in out: + return out[n] + acc = {n} + for d in down.get(n, ()): + acc |= walk(d) + out[n] = acc + return acc + + for n in by_id.values(): + walk(n) + return out + + +def baseline_fill(derived_on): + """name -> (elements, nonempty) summed over the metaclasses on which + the name is *derived*; None if the baseline is absent. A name can be + owned on one metaclass and derived on another (`importedMembership` + is owned on MembershipImport, derived on Namespace), so the owned + spellings must not count as derived fill.""" + if not BASELINE.exists(): + return None + fill = defaultdict(lambda: [0, 0]) + per_class = defaultdict(dict) # prop -> metaclass -> [elements, nonempty] + for line in BASELINE.read_text().splitlines(): + if not line or line.startswith("#"): + continue + metaclass, prop, _, elements, nonempty = line.split("\t") + if (metaclass, prop) not in derived_on: + continue + fill[prop][0] += int(elements) + fill[prop][1] += int(nonempty) + per_class[prop][metaclass] = [int(elements), int(nonempty)] + return fill, per_class + + +def classify(derived, derived_on, ancestors_of): + """closure / inheritance-aware / structural. A rule's references + propagate transitively (`usage = feature->…` inherits `feature`'s + class). A property without a rule counts only a *direct* reference to + a closure in its code-marked documentation, and only where that + closure is derived on the declaring metaclass (`MembershipImport`'s + `importedMembership` is the owned spelling): prose references to + ordinary properties are back-references as often as derivations.""" + ident = re.compile(r"[A-Za-z_][A-Za-z0-9_]*") + # Iterator and let-bound variables (`select(f | …)`, `let t : Type =`) + # are not property navigations, whatever they are called. + bound = re.compile(r"(?:\(|,)\s*([A-Za-z_][A-Za-z0-9_]*)\s*(?::\s*[A-Za-z_][A-Za-z0-9_()]*\s*)?\||let\s+([A-Za-z_][A-Za-z0-9_]*)") + known = set(derived) + + def canon(tok): + # `importedMemberships` (an operation, or prose plural) names the + # property `importedMembership`. + if tok not in known and tok.endswith("s") and tok[:-1] in known: + return tok[:-1] + return tok + + refs = {} + for name, rec in derived.items(): + toks = set() + for cname, body in rec["rules"].items(): + vars_ = {v for pair in bound.findall(body) for v in pair if v} + for t in ident.findall(body): + if t in vars_: + continue + t = canon(t) + # A closure name counts only where it is the derived + # property, not an owned spelling of the same name. + if t in CLOSURES and (cname, t) not in derived_on: + continue + toks.add(t) + if not rec["rules"]: + # No OCL rule: the normative documentation is the only + # statement of the derivation (`membership` = "the union of + # ownedMemberships and importedMemberships"). + for decl in rec["declaring"]: + toks.update( + canon(t) + for t in decl["doc_refs"] + if canon(t) in CLOSURES and (decl["metaclass"], canon(t)) in derived_on + ) + # A UML redefinition is the redefined property under a + # narrower name (`parameter` redefines `directedFeature`), + # so it takes that property's class. A mere `subsets` does + # not: `owningType` subsets `featuringType` structurally. + toks.update(decl["redefines"]) + refs[name] = toks - {name} + cls = {n: "closure" for n in CLOSURES} + changed = True + while changed: + changed = False + for name in derived: + if name in cls: + continue + if any(t in cls and cls[t] in ("closure", "inheritance-aware") for t in refs[name]): + cls[name] = "inheritance-aware" + changed = True + for name in derived: + cls.setdefault(name, "structural") + for name, forced in CLASS_OVERRIDES.items(): + cls[name] = forced + # Per declaration: the same name can be several properties, and only + # the declarations whose own rule (or the rule of a refining subclass), + # redefinition or documentation reaches a closure are inheritance-aware + # (`Connector::targetFeature` is, `FeatureChainExpression::targetFeature` + # is not). + decl_cls = {} + for name, rec in derived.items(): + for decl in rec["declaring"]: + cname = decl["metaclass"] + if name in CLOSURES: + decl_cls[(name, cname)] = "closure" + continue + if name in CLASS_OVERRIDES: + decl_cls[(name, cname)] = CLASS_OVERRIDES[name] + continue + toks = set(decl["redefines"]) + for rule_class, body in rec["rules"].items(): + if rule_class == cname or cname in ancestors_of.get(rule_class, set()): + vars_ = {v for pair in bound.findall(body) for v in pair if v} + for t in ident.findall(body): + if t in vars_: + continue + t = canon(t) + # Same guard as the name-level pass: a closure name + # counts only where it is the derived property. + if t in CLOSURES and (rule_class, t) not in derived_on: + continue + toks.add(t) + if not rec["rules"]: + toks.update(canon(t) for t in decl["doc_refs"] if canon(t) in CLOSURES and (cname, canon(t)) in derived_on) + aware = any(t != name and cls.get(t) in ("closure", "inheritance-aware") for t in toks) + decl_cls[(name, cname)] = "inheritance-aware" if aware else "structural" + # The two computations must agree: a name's class is the strongest of + # its declarations' classes. + rank = {"structural": 0, "inheritance-aware": 1, "closure": 2} + for name, rec in derived.items(): + strongest = max((decl_cls[(name, d["metaclass"])] for d in rec["declaring"]), key=rank.get) + assert cls[name] == strongest, f"{name}: name class {cls[name]} vs declarations {strongest}" + return cls, decl_cls + + +def concrete_carriers(classes, prop_names): + """(name -> number of concrete metaclasses whose closure carries it as + derived, {(metaclass, name)} where it is derived, {name} that is owned + on some metaclass and derived on another).""" + carriers = defaultdict(int) + derived_on = set() + owned_on = set() + for cid, c in classes.items(): + for pname, (flags, _) in closure(classes, prop_names, cid, {}).items(): + if flags & 1: + derived_on.add((c["name"], pname)) + if not c["abstract"]: + carriers[pname] += 1 + else: + owned_on.add(pname) + dual = {p for (_, p) in derived_on} & owned_on + return carriers, derived_on, dual + + +def write_compositions(records): + """The kind-filtered compositions: every derived property whose OCL + rule is `name = base->selectByKind(Kind)` (or `selectAsKind`), plus + the rule-less `*Definition` back-references, which the normative + documentation defines as the usage's definitions of the property's + declared type (`definition->selectByKind()`). Single-valued + properties (upper bound 1) take the first match.""" + # `name = base->selectByKind(Kind)`, or the same without the left-hand + # side (a few rules spell the expression alone). + pat = re.compile(r"^\s*(?:(\w+)\s*=\s*)?(\w+)\s*->\s*select(?:By|As)Kind\(\s*(\w+)\s*\)\s*$") + rows = {} + for r in records: + name = r["name"] + single = all(d["multiplicity"].endswith("..1") for d in r["declaring"]) + for body in r["rules"].values(): + m = pat.match(body.replace("\n", " ")) + lhs = LHS_ALIASES.get(m.group(1), m.group(1)) if m else None + if m and lhs in (None, name): + base = BASE_ALIASES.get(m.group(2), m.group(2)) + rows.setdefault(name, (base, m.group(3), single)) + # A `*Definition` back-reference declared on a usage without a rule + # on that usage (per declaration: `PortUsage::portDefinition` has + # no rule although `ConjugatedPortTyping::portDefinition` does). + if name.endswith("Definition") and name not in ("owningDefinition", "originalPortDefinition"): + decls = [ + d + for d in r["declaring"] + if d["metaclass"].endswith("Usage") and d["metaclass"] not in r["rules"] + ] + if decls and name not in rows: + kinds = sorted({d["type"] for d in decls}) + if len(kinds) == 1: + rows.setdefault(name, ("definition", kinds[0], single)) + lines = [ + "//! Generated from `spec-refs/{KerML,SysML}.xmi` (normative metamodel", + "//! 20250201) by `tools/derived_census.py` — do not edit.", + "//!", + "//! Kind-filtered compositions among the derived properties: `name =", + "//! base->selectByKind(kind)` per the OCL derivation rules, and the", + "//! rule-less `*Definition` back-references, which the normative", + "//! documentation defines as the usage's `definition`s of the", + "//! property's declared type. `single` marks an upper bound of 1 (the", + "//! first match, else null). A composition is computable exactly when", + "//! its base is.", + "", + "/// `(name, base, kind, single)`, sorted by name.", + "pub(crate) static COMPOSITIONS: &[(&str, &str, &str, bool)] = &[", + ] + for name in sorted(rows): + base, kind, single = rows[name] + lines.append(f' ("{name}", "{base}", "{kind}", {str(single).lower()}),') + lines += ["];", ""] + OUT_COMPOSITIONS.write_text("\n".join(lines)) + subprocess.run(["rustfmt", "--edition", "2024", str(OUT_COMPOSITIONS)], check=False) + return len(rows) + + +def write_rust_table(classes, prop_names, derived_names, dual): + """The model crate's derived-name table: every derived name, the + metaclasses (abstract ones included — the schema catalog carries a + few) on which a dual-spelled name is *owned*, and the abstract + metaclasses themselves.""" + owned_on = defaultdict(list) + for cid, c in classes.items(): + for pname, (flags, _) in closure(classes, prop_names, cid, {}).items(): + if pname in dual and not flags & 1: + owned_on[pname].append(c["name"]) + lines = [ + "//! Generated from `spec-refs/{KerML,SysML}.xmi` (normative metamodel", + "//! 20250201) by `tools/derived_census.py` — do not edit.", + "//!", + "//! The abstract syntax's derived property names, for the derived-property", + "//! read API: a property is derived on a concrete metaclass when the", + "//! schema catalog declares it, its name is in [`DERIVED_NAMES`], and the", + "//! metaclass is not listed under that name in [`OWNED_ON`] (a few names", + "//! are owned on one metaclass and derived on another).", + "", + "/// Every `isDerived` property name, sorted.", + "pub(crate) static DERIVED_NAMES: &[&str] = &[", + ] + lines += [f' "{n}",' for n in sorted(derived_names)] + lines += [ + "];", + "", + "/// Names that are derived somewhere but *owned* on these metaclasses", + "/// (abstract ones included).", + "pub(crate) static OWNED_ON: &[(&str, &[&str])] = &[", + ] + for pname in sorted(owned_on): + cls_list = ", ".join(f'"{c}"' for c in sorted(owned_on[pname])) + lines.append(f' ("{pname}", &[{cls_list}]),') + lines += [ + "];", + "", + "/// The abstract metaclasses of the abstract syntax, sorted: no element", + "/// has one, and the property catalog skips them.", + "pub(crate) static ABSTRACT_METACLASSES: &[&str] = &[", + ] + lines += [f' "{c["name"]}",' for c in sorted(classes.values(), key=lambda c: c["name"]) if c["abstract"]] + lines += ["];", ""] + OUT_RS.write_text("\n".join(lines)) + subprocess.run(["rustfmt", "--edition", "2024", str(OUT_RS)], check=False) + + +def main(): + derived = read_xmi() + classes, prop_names = {}, {} + for src in SOURCES: + classes.update(load(src, prop_names)) + carriers, derived_on, dual = concrete_carriers(classes, prop_names) + mentioned = emitter_mentions() + fill, per_class = baseline_fill(derived_on) if BASELINE.exists() else (None, None) + below = descendants(classes) + ancestors_of = ancestors(classes) + cls, decl_cls = classify(derived, derived_on, ancestors_of) + + records = [] + for name in sorted(derived): + rec = derived[name] + elements, nonempty = (fill.get(name, [0, 0]) if fill is not None else [None, None]) + # Corpus fill is the primary evidence: a non-empty value proves the + # emitter derives the name whether or not a literal names it + # (membership required-reference aliases write under every + # redefining name). A literal without fill is unexercised. + if fill is not None and nonempty: + status = "derived" + elif name in mentioned: + status = "unexercised" if fill is not None else "derived" + else: + status = "absent" + # Fill per declaration: summed over the declaring metaclass and its + # subclasses, since one name can be several properties (`action` on + # StateSubactionMembership vs. ActionDefinition). + if per_class is not None: + for decl in rec["declaring"]: + sub = below.get(decl["metaclass"], {decl["metaclass"]}) + e = sum(v[0] for c, v in per_class.get(name, {}).items() if c in sub) + n = sum(v[1] for c, v in per_class.get(name, {}).items() if c in sub) + decl["corpus_elements"], decl["corpus_nonempty"] = e, n + for decl in rec["declaring"]: + decl["class"] = decl_cls[(name, decl["metaclass"])] + records.append( + { + "name": name, + "class": cls[name], + "status": status, + "declaring": rec["declaring"], + "concrete_carriers": carriers.get(name, 0), + "also_owned_elsewhere": name in dual, + "rules": rec["rules"], + "corpus_elements": elements, + "corpus_nonempty": nonempty, + } + ) + + write_rust_table(classes, prop_names, set(derived), dual) + n_comp = write_compositions(records) + OUT_JSON.write_text(json.dumps({"source": "spec-refs/{KerML,SysML}.xmi 20250201", "generator": "tools/derived_census.py", "properties": records}, indent=1) + "\n") + + by_class = defaultdict(list) + by_status = defaultdict(list) + for r in records: + by_class[r["class"]].append(r["name"]) + by_status[r["status"]].append(r["name"]) + lines = [ + "# Derived properties — census", + "", + "Generated by `tools/derived_census.py` from `spec-refs/{KerML,SysML}.xmi` (20250201), the full-form emitter and the corpus baseline. Do not edit; regenerate after changing the emitter and refreshing the baseline. The JSON twin `derived-properties.json` carries the per-declaration facts (type, multiplicity, subsets, redefines, OCL rule).", + "", + f"{len(records)} distinct derived property names. Status: **derived** = the corpus emits a non-empty value for it on a metaclass where it is derived (the primary evidence — the emitter writes some names without a literal, through the membership required-reference alias); **unexercised** = the emitter writes the name but the corpus never emits a non-empty value (a placeholder such as the `result` self-reference, or a shape only foreign payloads carry); **absent** = never written, so it falls to the catalog's type-correct empty default.", + "", + "| Class | Total | derived | unexercised | absent |", + "|---|---|---|---|---|", + ] + for c in ("structural", "inheritance-aware", "closure"): + names = by_class[c] + counts = {s: sum(1 for n in names if next(r for r in records if r["name"] == n)["status"] == s) for s in ("derived", "unexercised", "absent")} + lines.append(f"| {c} | {len(names)} | {counts['derived']} | {counts['unexercised']} | {counts['absent']} |") + lines.append(f"| **all** | {len(records)} | {len(by_status['derived'])} | {len(by_status['unexercised'])} | {len(by_status['absent'])} |") + lines += [ + "", + "A *closure* is one of the four inheritance/import closures; an *inheritance-aware* property is one whose derivation rule (or, for a property without an OCL rule, the property it redefines, or its normative documentation's direct closure reference) transitively reads a closure, so its passthrough-level value is an owned-only approximation until the closure policy is on; everything else is *structural*. Hand adjudications: " + ", ".join(f"`{n}` → {c}" for n, c in sorted(CLASS_OVERRIDES.items())) + ". A name's class is the strongest over its declarations; names whose declarations disagree: " + (", ".join(f"`{r['name']}`" for r in records if len({d['class'] for d in r['declaring']}) > 1) or "(none)") + ".", + "", + "Names that are derived on one metaclass and owned on another (corpus fill counts only the derived carriers, and an emitter mention of such a name may be a read of the owned spelling): " + (", ".join(f"`{n}`" for n in sorted(dual)) or "(none)") + ".", + "", + "## Inheritance-aware names", + "", + ", ".join(f"`{n}`" for n in sorted(by_class["inheritance-aware"])) or "(none)", + "", + "## Every derived name", + "", + "| Name | Class | Status | Declared by | Carriers | Type | Corpus non-empty / elements |", + "|---|---|---|---|---|---|---|", + ] + for r in records: + decl = ", ".join(d["metaclass"] for d in r["declaring"]) + types = ", ".join(sorted({d["type"] for d in r["declaring"]})) + fillcol = "—" if r["corpus_elements"] is None else f"{r['corpus_nonempty']} / {r['corpus_elements']}" + lines.append(f"| `{r['name']}` | {r['class']} | {r['status']} | {decl} | {r['concrete_carriers']} | {types} | {fillcol} |") + lines.append("") + OUT_MD.write_text("\n".join(lines)) + + print(f"wrote {OUT_JSON.relative_to(ROOT)}, {OUT_MD.relative_to(ROOT)} and {OUT_RS.relative_to(ROOT)}") + print(f"{len(records)} derived names: " + ", ".join(f"{s}={len(by_status[s])}" for s in ("derived", "unexercised", "absent"))) + print("classes: " + ", ".join(f"{c}={len(by_class[c])}" for c in ("structural", "inheritance-aware", "closure"))) + missing_rules = [r["name"] for r in records if not r["rules"]] + print(f"names without a matched derivation rule: {len(missing_rules)}") + print(f"names owned on one metaclass and derived on another: {sorted(dual)}") + print(f"kind-filtered compositions generated: {n_comp}") + if fill is None: + print("baseline fixture absent: statuses use emitter mentions only") + + +if __name__ == "__main__": + main() diff --git a/tools/gen_metaclass_hierarchy.py b/tools/gen_metaclass_hierarchy.py new file mode 100644 index 0000000..a94657a --- /dev/null +++ b/tools/gen_metaclass_hierarchy.py @@ -0,0 +1,130 @@ +#!/usr/bin/env python3 +"""Generate metaclass conformance from the pinned KerML/SysML XMI. + +The output is a sorted name table plus one ancestor bit set per metaclass, so +a conformance test is two generated name dispatches and a bit test. The same ancestor +sets are also emitted as name lists under `cfg(test)` for the differential +test that pins the bit table against them. +""" +import argparse +import subprocess +import sys +from pathlib import Path +sys.dont_write_bytecode = True +from xmi_props import load, SOURCES + +ROOT = Path(__file__).resolve().parents[1] +OUTPUT = ROOT / "crates/sysmlv2-model/src/metaclass.rs" + + +def hierarchy(): + """Sorted `(name, sorted strict-ancestor names)` pairs.""" + classes = {} + for source in SOURCES: + classes.update(load(source, {})) + def ancestors(cid, active): + if cid in active: + raise ValueError(f"cyclic metaclass inheritance: {cid}") + row = classes[cid] + out = {row["name"]} + for parent in row["generals"]: + out.update(ancestors(parent, active | {cid})) + return out + rows = [] + for cid, row in sorted(classes.items(), key=lambda item: item[1]["name"]): + rows.append((row["name"], sorted(ancestors(cid, set()) - {row["name"]}))) + names = [name for name, _ in rows] + if len(set(names)) != len(names): + raise ValueError("metaclass name collision across files") + return rows + + +def generate(): + rows = hierarchy() + index = {name: i for i, (name, _) in enumerate(rows)} + n = len(rows) + words = (n + 63) // 64 + lines = [ + "//! Generated from the pinned `spec-refs/{KerML,SysML}.xmi` by", + "//! `tools/gen_metaclass_hierarchy.py`; do not edit.", + "//!", + "//! Abstract-syntax inheritance, distinct from a model element's declared", + "//! specializations. Used to validate the kinds of explicit typing targets.", + "//!", + "//! `NAMES` holds every metaclass in sorted order and `ANCESTORS[i]` the", + "//! bit set, over that same order, of the metaclasses `NAMES[i]` strictly", + "//! specializes; a conformance test is two generated name dispatches and a bit test.", + "", + f"const COUNT: usize = {n};", + f"const WORDS: usize = {words};", + "", + "/// Every metaclass name, in stable index order.", + "const NAMES: [&str; COUNT] = [", + ] + lines += [f' "{name}",' for name, _ in rows] + lines += [ + "];", + "", + "/// Strict ancestors of `NAMES[i]`, as a bit set in `NAMES` order.", + "const ANCESTORS: [[u64; WORDS]; COUNT] = [", + ] + for _, parents in rows: + bits = [0] * words + for parent in parents: + j = index[parent] + bits[j // 64] |= 1 << (j % 64) + lines.append(" [" + ", ".join(f"0x{b:016x}" for b in bits) + "],") + lines += [ + "];", + "", + "fn index(name: &str) -> Option {", + " match name {", + ] + lines += [f' "{name}" => Some({i}),' for i, (name, _) in enumerate(rows)] + lines += [ + " _ => None,", + " }", + "}", + "", + "pub(crate) fn conforms(specific: &str, general: &str) -> bool {", + " if specific == general {", + " return true;", + " }", + " let (Some(s), Some(g)) = (index(specific), index(general)) else {", + " return false;", + " };", + " ANCESTORS[s][g / 64] >> (g % 64) & 1 == 1", + "}", + "", + "pub(crate) fn canonical_name(name: &str) -> Option<&'static str> {", + " index(name).map(|i| NAMES[i])", + "}", + "", + "/// The same hierarchy as name lists: `(metaclass, strict ancestors)`,", + "/// for the test that pins the bit table.", + "#[cfg(test)]", + "pub(crate) const ANCESTOR_NAMES: [(&str, &[&str]); COUNT] = [", + ] + for name, parents in rows: + listed = ", ".join(f'"{p}"' for p in parents) + lines.append(f' ("{name}", &[{listed}]),') + lines += ["];", ""] + source = "\n".join(lines) + return subprocess.run(["rustfmt", "--edition", "2021"], input=source, + text=True, capture_output=True, check=True).stdout + + +def main(): + parser = argparse.ArgumentParser(description=__doc__) + parser.add_argument("--check", action="store_true") + args = parser.parse_args() + text = generate() + if args.check: + if OUTPUT.read_text() != text: + raise SystemExit(f"stale generated file: {OUTPUT}") + else: + OUTPUT.write_text(text) + + +if __name__ == "__main__": + main()