use crate::parser::sysml::Rule;
use crate::syntax::sysml::ast::utils::is_body_rule;
const HANDLED_BODY_RULES: &[Rule] = &[
Rule::action_body,
Rule::calculation_body,
Rule::case_body,
Rule::constraint_body,
Rule::definition_body,
Rule::enumeration_body,
Rule::interface_body,
Rule::metadata_body,
Rule::requirement_body,
Rule::state_def_body,
Rule::view_definition_body,
Rule::state_usage_body,
Rule::usage_body,
Rule::view_body,
];
const EXCLUDED_BODY_RULES: &[Rule] = &[
Rule::package_body, Rule::expression_body, Rule::relationship_body, ];
#[test]
fn test_all_handled_body_rules_return_true() {
let mut failures = Vec::new();
for rule in HANDLED_BODY_RULES {
if !is_body_rule(*rule) {
failures.push(format!(
"Rule::{:?} should be handled by is_body_rule() but returns false",
rule
));
}
}
assert!(
failures.is_empty(),
"Body rules missing from is_body_rule():\n{}",
failures.join("\n")
);
}
#[test]
fn test_excluded_body_rules_return_false() {
let mut failures = Vec::new();
for rule in EXCLUDED_BODY_RULES {
if is_body_rule(*rule) {
failures.push(format!(
"Rule::{:?} should NOT be handled by is_body_rule() but returns true",
rule
));
}
}
assert!(
failures.is_empty(),
"Body rules incorrectly included in is_body_rule():\n{}",
failures.join("\n")
);
}
#[test]
fn test_interface_body_extracts_port_usages() {
use crate::parser::sysml::{Rule, SysMLParser};
use crate::syntax::sysml::ast::parse_definition;
use pest::Parser;
let source = r#"interface def DataInterface {
port dataIn : DataPort;
port dataOut : DataPort;
}"#;
let mut pairs = SysMLParser::parse(Rule::interface_definition, source).expect("parse failed");
let def = parse_definition(pairs.next().expect("no pair")).expect("AST construction failed");
assert_eq!(def.name.as_deref(), Some("DataInterface"));
let port_count = def
.body
.iter()
.filter(|m| {
matches!(
m,
crate::syntax::sysml::ast::DefinitionMember::Usage(u)
if u.kind == crate::syntax::sysml::ast::UsageKind::Port
)
})
.count();
assert_eq!(
port_count, 2,
"Expected 2 port usages in interface body, got {}",
port_count
);
}
#[test]
fn test_view_body_extracts_usages() {
use crate::parser::sysml::{Rule, SysMLParser};
use crate::syntax::sysml::ast::parse_usage;
use pest::Parser;
let source = r#"view myView : ViewDef {
attribute name : String;
}"#;
let mut pairs = SysMLParser::parse(Rule::view_usage, source).expect("parse failed");
let usage = parse_usage(pairs.next().expect("no pair"));
assert_eq!(usage.name.as_deref(), Some("myView"));
assert_eq!(usage.kind, crate::syntax::sysml::ast::UsageKind::View);
let attr_count = usage
.body
.iter()
.filter(|m| {
matches!(
m,
crate::syntax::sysml::ast::UsageMember::Usage(u)
if u.kind == crate::syntax::sysml::ast::UsageKind::Attribute
)
})
.count();
assert_eq!(
attr_count, 1,
"Expected 1 attribute usage in view body, got {}",
attr_count
);
}