Skip to content

Commit 2d9887d

Browse files
avrabeclaude
andcommitted
style: cargo fmt
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 0729593 commit 2d9887d

5 files changed

Lines changed: 251 additions & 155 deletions

File tree

crates/spar-analysis/src/feature_group_check.rs

Lines changed: 119 additions & 89 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
//! - **Feature group connection expansion tracking**: Reports diagnostics for
1111
//! feature group connections that could not be expanded.
1212
13-
use spar_hir_def::feature_group::{expand_feature_group, flip_direction, ExpandedFeature};
13+
use spar_hir_def::feature_group::{ExpandedFeature, expand_feature_group, flip_direction};
1414
use spar_hir_def::instance::SystemInstance;
1515
use spar_hir_def::item_tree::{ConnectionKind, Direction, FeatureKind, ItemTree};
1616
use spar_hir_def::name::Name;
@@ -233,12 +233,10 @@ pub fn check_feature_group_complements(
233233
};
234234

235235
// Expand the feature groups.
236-
let src_expanded = expand_component_feature_group(
237-
instance, scope, src_comp_idx, &src_end.feature,
238-
);
239-
let dst_expanded = expand_component_feature_group(
240-
instance, scope, dst_comp_idx, &dst_end.feature,
241-
);
236+
let src_expanded =
237+
expand_component_feature_group(instance, scope, src_comp_idx, &src_end.feature);
238+
let dst_expanded =
239+
expand_component_feature_group(instance, scope, dst_comp_idx, &dst_end.feature);
242240

243241
let (src_features, dst_features) = match (src_expanded, dst_expanded) {
244242
(Some(s), Some(d)) => (s, d),
@@ -271,9 +269,15 @@ pub fn check_feature_group_complements(
271269
(source: {}, destination: {}, expected destination: {})",
272270
conn.name,
273271
mismatch.feature_name,
274-
mismatch.source_direction.map_or("none".to_string(), |d| d.to_string()),
275-
mismatch.destination_direction.map_or("none".to_string(), |d| d.to_string()),
276-
mismatch.source_direction.map_or("none".to_string(), |d| flip_direction(d).to_string()),
272+
mismatch
273+
.source_direction
274+
.map_or("none".to_string(), |d| d.to_string()),
275+
mismatch
276+
.destination_direction
277+
.map_or("none".to_string(), |d| d.to_string()),
278+
mismatch
279+
.source_direction
280+
.map_or("none".to_string(), |d| flip_direction(d).to_string()),
277281
),
278282
path: conn_path.clone(),
279283
analysis: "feature_group_check".to_string(),
@@ -295,9 +299,11 @@ fn resolve_endpoint_component(
295299
match subcomponent {
296300
Some(sub_name) => {
297301
let owner_comp = instance.component(owner);
298-
owner_comp.children.iter().find(|&&child_idx| {
299-
instance.component(child_idx).name.eq_ci(sub_name)
300-
}).copied()
302+
owner_comp
303+
.children
304+
.iter()
305+
.find(|&&child_idx| instance.component(child_idx).name.eq_ci(sub_name))
306+
.copied()
301307
}
302308
None => Some(owner),
303309
}
@@ -457,8 +463,14 @@ mod tests {
457463
];
458464

459465
let result = validate_complement(&source, &destination);
460-
assert!(result.unmatched_source.is_empty(), "all features should match");
461-
assert!(result.direction_mismatches.is_empty(), "directions should be complementary");
466+
assert!(
467+
result.unmatched_source.is_empty(),
468+
"all features should match"
469+
);
470+
assert!(
471+
result.direction_mismatches.is_empty(),
472+
"directions should be complementary"
473+
);
462474
}
463475

464476
#[test]
@@ -477,14 +489,12 @@ mod tests {
477489
group_prefix: None,
478490
},
479491
];
480-
let destination = vec![
481-
ExpandedFeature {
482-
name: Name::new("temp"),
483-
kind: FeatureKind::DataPort,
484-
direction: Some(Direction::In),
485-
group_prefix: None,
486-
},
487-
];
492+
let destination = vec![ExpandedFeature {
493+
name: Name::new("temp"),
494+
kind: FeatureKind::DataPort,
495+
direction: Some(Direction::In),
496+
group_prefix: None,
497+
}];
488498

489499
let result = validate_complement(&source, &destination);
490500
assert_eq!(result.unmatched_source.len(), 1);
@@ -493,22 +503,18 @@ mod tests {
493503

494504
#[test]
495505
fn complement_direction_mismatch() {
496-
let source = vec![
497-
ExpandedFeature {
498-
name: Name::new("data"),
499-
kind: FeatureKind::DataPort,
500-
direction: Some(Direction::Out),
501-
group_prefix: None,
502-
},
503-
];
504-
let destination = vec![
505-
ExpandedFeature {
506-
name: Name::new("data"),
507-
kind: FeatureKind::DataPort,
508-
direction: Some(Direction::Out), // Should be In!
509-
group_prefix: None,
510-
},
511-
];
506+
let source = vec![ExpandedFeature {
507+
name: Name::new("data"),
508+
kind: FeatureKind::DataPort,
509+
direction: Some(Direction::Out),
510+
group_prefix: None,
511+
}];
512+
let destination = vec![ExpandedFeature {
513+
name: Name::new("data"),
514+
kind: FeatureKind::DataPort,
515+
direction: Some(Direction::Out), // Should be In!
516+
group_prefix: None,
517+
}];
512518

513519
let result = validate_complement(&source, &destination);
514520
assert!(result.unmatched_source.is_empty());
@@ -518,48 +524,46 @@ mod tests {
518524

519525
#[test]
520526
fn complement_inout_matches_inout() {
521-
let source = vec![
522-
ExpandedFeature {
523-
name: Name::new("bus"),
524-
kind: FeatureKind::DataPort,
525-
direction: Some(Direction::InOut),
526-
group_prefix: None,
527-
},
528-
];
529-
let destination = vec![
530-
ExpandedFeature {
531-
name: Name::new("bus"),
532-
kind: FeatureKind::DataPort,
533-
direction: Some(Direction::InOut),
534-
group_prefix: None,
535-
},
536-
];
527+
let source = vec![ExpandedFeature {
528+
name: Name::new("bus"),
529+
kind: FeatureKind::DataPort,
530+
direction: Some(Direction::InOut),
531+
group_prefix: None,
532+
}];
533+
let destination = vec![ExpandedFeature {
534+
name: Name::new("bus"),
535+
kind: FeatureKind::DataPort,
536+
direction: Some(Direction::InOut),
537+
group_prefix: None,
538+
}];
537539

538540
let result = validate_complement(&source, &destination);
539-
assert!(result.direction_mismatches.is_empty(), "InOut matches InOut");
541+
assert!(
542+
result.direction_mismatches.is_empty(),
543+
"InOut matches InOut"
544+
);
540545
}
541546

542547
#[test]
543548
fn complement_case_insensitive_matching() {
544-
let source = vec![
545-
ExpandedFeature {
546-
name: Name::new("Temperature"),
547-
kind: FeatureKind::DataPort,
548-
direction: Some(Direction::Out),
549-
group_prefix: None,
550-
},
551-
];
552-
let destination = vec![
553-
ExpandedFeature {
554-
name: Name::new("temperature"),
555-
kind: FeatureKind::DataPort,
556-
direction: Some(Direction::In),
557-
group_prefix: None,
558-
},
559-
];
549+
let source = vec![ExpandedFeature {
550+
name: Name::new("Temperature"),
551+
kind: FeatureKind::DataPort,
552+
direction: Some(Direction::Out),
553+
group_prefix: None,
554+
}];
555+
let destination = vec![ExpandedFeature {
556+
name: Name::new("temperature"),
557+
kind: FeatureKind::DataPort,
558+
direction: Some(Direction::In),
559+
group_prefix: None,
560+
}];
560561

561562
let result = validate_complement(&source, &destination);
562-
assert!(result.unmatched_source.is_empty(), "matching should be case-insensitive");
563+
assert!(
564+
result.unmatched_source.is_empty(),
565+
"matching should be case-insensitive"
566+
);
563567
assert!(result.direction_mismatches.is_empty());
564568
}
565569

@@ -601,7 +605,11 @@ mod tests {
601605
});
602606

603607
let diags = check_inverse_of_rules(&tree);
604-
assert!(diags.is_empty(), "inverse_of with no features should be valid: {:?}", diags);
608+
assert!(
609+
diags.is_empty(),
610+
"inverse_of with no features should be valid: {:?}",
611+
diags
612+
);
605613
}
606614

607615
#[test]
@@ -828,26 +836,45 @@ mod tests {
828836

829837
// The instance should have semantic connections from FG expansion.
830838
// We should find individual semantic connections for "temp" and "pressure".
831-
let fg_semantic: Vec<_> = instance.semantic_connections.iter()
839+
let fg_semantic: Vec<_> = instance
840+
.semantic_connections
841+
.iter()
832842
.filter(|sc| sc.name.as_str().starts_with("c1."))
833843
.collect();
834844

835845
assert_eq!(
836-
fg_semantic.len(), 2,
846+
fg_semantic.len(),
847+
2,
837848
"feature group connection should expand into 2 individual connections, \
838849
got {} semantic connections: {:?}",
839850
fg_semantic.len(),
840-
instance.semantic_connections.iter().map(|sc| sc.name.as_str()).collect::<Vec<_>>()
851+
instance
852+
.semantic_connections
853+
.iter()
854+
.map(|sc| sc.name.as_str())
855+
.collect::<Vec<_>>()
841856
);
842857

843858
// Check that we have connections for both temp and pressure
844859
let names: Vec<_> = fg_semantic.iter().map(|sc| sc.name.as_str()).collect();
845-
assert!(names.contains(&"c1.temp"), "should have c1.temp: {:?}", names);
846-
assert!(names.contains(&"c1.pressure"), "should have c1.pressure: {:?}", names);
860+
assert!(
861+
names.contains(&"c1.temp"),
862+
"should have c1.temp: {:?}",
863+
names
864+
);
865+
assert!(
866+
names.contains(&"c1.pressure"),
867+
"should have c1.pressure: {:?}",
868+
names
869+
);
847870

848871
// Each expanded connection should be of kind Port (since the features are DataPort)
849872
for sc in &fg_semantic {
850-
assert_eq!(sc.kind, ConnectionKind::Port, "expanded FG connection should be Port kind");
873+
assert_eq!(
874+
sc.kind,
875+
ConnectionKind::Port,
876+
"expanded FG connection should be Port kind"
877+
);
851878
}
852879
}
853880

@@ -1057,13 +1084,15 @@ mod tests {
10571084
diags.iter().map(|d| &d.message).collect::<Vec<_>>()
10581085
);
10591086

1060-
let unmatched: Vec<_> = diags.iter()
1087+
let unmatched: Vec<_> = diags
1088+
.iter()
10611089
.filter(|d| d.message.contains("no matching"))
10621090
.collect();
10631091
assert_eq!(unmatched.len(), 1, "pressure should be unmatched");
10641092
assert!(unmatched[0].message.contains("pressure"));
10651093

1066-
let mismatches: Vec<_> = diags.iter()
1094+
let mismatches: Vec<_> = diags
1095+
.iter()
10671096
.filter(|d| d.message.contains("incompatible directions"))
10681097
.collect();
10691098
assert_eq!(mismatches.len(), 1, "temp should have direction mismatch");
@@ -1121,20 +1150,21 @@ mod tests {
11211150
// Expand both and verify they are complements
11221151
let scope = GlobalScope::from_trees(vec![Arc::new(tree)]);
11231152

1124-
let src_expanded = expand_feature_group(
1125-
&scope, &Name::new("P"), &Name::new("SensorOutput"), false,
1126-
);
1127-
let dst_expanded = expand_feature_group(
1128-
&scope, &Name::new("P"), &Name::new("SensorInput"), false,
1129-
);
1153+
let src_expanded =
1154+
expand_feature_group(&scope, &Name::new("P"), &Name::new("SensorOutput"), false);
1155+
let dst_expanded =
1156+
expand_feature_group(&scope, &Name::new("P"), &Name::new("SensorInput"), false);
11301157

11311158
assert_eq!(src_expanded.len(), 2);
11321159
assert_eq!(dst_expanded.len(), 2);
11331160

11341161
// SensorOutput: temp=Out, pressure=Out
11351162
// SensorInput (inverse): temp=In, pressure=In
11361163
let result = validate_complement(&src_expanded, &dst_expanded);
1137-
assert!(result.unmatched_source.is_empty(), "inverse should match all features");
1164+
assert!(
1165+
result.unmatched_source.is_empty(),
1166+
"inverse should match all features"
1167+
);
11381168
assert!(
11391169
result.direction_mismatches.is_empty(),
11401170
"inverse should have complementary directions: {:?}",

0 commit comments

Comments
 (0)