Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## Unreleased

### Fixed

- A message is abstract (SysML 8.2.2.16 `Message : FlowUsage = ... { isAbstract = true }`, 7.16.2 "A message is always abstract"): `message m of M;` exports `isAbstract: true`. The full-form baseline moves for the corpus's 40 messages.
- `validateConnectorRelatedFeatures` reports a concrete connector with no ends, and `validateBindingConnectorIsBinary` a binding connector with no ends, abstract or not (KerML 8.3.4.5.3, 8.3.4.5.2); both reported only one end before. The opensysml fixture `k49-binding-connector-with-three-ends` gains the finding on its `abstract binding b2;`.

## v0.11.3

### Added
Expand Down
38 changes: 38 additions & 0 deletions crates/sysmlv2-model/src/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1168,6 +1168,44 @@ mod tests {
assert_eq!(shown(&on_threads), shown(&in_line));
}

/// KerML 8.3.4.5.3 validateConnectorRelatedFeatures and 8.3.4.5.2
/// validateBindingConnectorIsBinary hold without ends too. A message
/// is always abstract (SysML 7.16.2, 8.2.2.16), so it needs no ends.
#[test]
fn connectors_without_ends() {
let mut model = Model::new();
model.add_source(
"user.kerml",
"package P {
classifier C {
connector c;
abstract connector d;
abstract binding b;
}
}",
);
model.add_source(
"user.sysml",
"package Q { item def M; part p { message m of M; } }",
);
let found: Vec<String> = findings(&model)
.into_iter()
.map(|(_, m)| m)
.filter(|m| m.contains("connector"))
.collect();
assert_eq!(found.len(), 2, "{found:?}");
assert!(
found
.iter()
.any(|m| m.contains("validateConnectorRelatedFeatures"))
);
assert!(
found
.iter()
.any(|m| m.contains("validateBindingConnectorIsBinary"))
);
}

#[test]
fn semantic_checks_walk_tables_without_copying_them() {
// Fresh build: library rows and user rows share one storage.
Expand Down
4 changes: 2 additions & 2 deletions crates/sysmlv2-model/src/check/relationships.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ pub(super) fn validate(
Vec::new()
};
if is_a!(b.elements[e], "BindingConnector") {
if !ends.is_empty() && ends.len() != 2 {
if ends.len() != 2 {
report(
"validateBindingConnectorIsBinary",
"A binding connector must have exactly two ends",
Expand All @@ -95,7 +95,7 @@ pub(super) fn validate(
bindings.push((unit, span, g.typed(b, *a), g.typed(b, *z)));
}
}
if is_a!(b.elements[e], "Connector") && !flag(b, e, "isAbstract") && ends.len() == 1 {
if is_a!(b.elements[e], "Connector") && !flag(b, e, "isAbstract") && ends.len() < 2 {
report(
"validateConnectorRelatedFeatures",
"A concrete connector must relate at least two features",
Expand Down
9 changes: 7 additions & 2 deletions crates/sysmlv2-model/src/json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5422,11 +5422,16 @@ impl Builder {
self.emit_multiplicity(cf, mult, body_scope);
}
}
// A variation is implicitly abstract (pilot `UsageAdapter.postProcess`).
// A variation is implicitly abstract (pilot `UsageAdapter.postProcess`),
// and so is a message (SysML 8.2.2.16 `{ isAbstract = true }`).
self.set(
e,
"isAbstract",
json!(u.prefix.is_abstract || u.prefix.is_variation),
json!(
u.prefix.is_abstract
|| u.prefix.is_variation
|| matches!(u.kind, UsageKind::Message)
),
);
if declares_variation(ty) {
self.set(e, "isVariation", json!(u.prefix.is_variation));
Expand Down
2 changes: 1 addition & 1 deletion crates/sysmlv2-parser/tests/check.rs
Original file line number Diff line number Diff line change
Expand Up @@ -858,7 +858,7 @@ fn usage_typing_respects_metaclass_inheritance_and_single_type_rules() {
);
}
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("interface def I; abstract 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());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3990,7 +3990,7 @@ 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 isAbstract 27db29890d44d382 138 40
FlowUsage isComposite d6f5f34e0a9981d7 138 137
FlowUsage isConjugated 7a1270115d01d5aa 138 0
FlowUsage isConstant 7a1270115d01d5aa 138 0
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2025,6 +2025,13 @@
"severity": "Error",
"stage": "semantics",
"start": 322
},
{
"end": 392,
"message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]",
"severity": "Error",
"stage": "semantics",
"start": 390
}
],
"status": "diagnostic baseline"
Expand Down
7 changes: 7 additions & 0 deletions crates/sysmlv2-parser/tests/fixtures/opensysml/baseline.json
Original file line number Diff line number Diff line change
Expand Up @@ -2060,6 +2060,13 @@
"severity": "Error",
"stage": "semantics",
"start": 322
},
{
"end": 392,
"message": "A binding connector must have exactly two ends [validateBindingConnectorIsBinary]",
"severity": "Error",
"stage": "semantics",
"start": 390
}
],
"status": "diagnostic baseline"
Expand Down