ryo_executor/executor/registry/converters/
spec_alias.rs1use crate::engine::ASTRegApply;
15use crate::executor::registry::converters::ResolveTargetSymbol;
16use crate::executor::registry::{ConvertError, MutationConverter};
17use crate::executor::spec::MutationSpec;
18use ryo_analysis::AnalysisContext;
19use ryo_mutations::{AddItemMutation, RemoveItemMutation};
20use ryo_source::ItemKind;
21
22#[derive(Debug, Clone, Default)]
23pub struct SpecAliasConverter;
24
25impl SpecAliasConverter {
26 pub fn new() -> Self {
27 Self
28 }
29}
30
31impl ResolveTargetSymbol for SpecAliasConverter {}
32
33impl MutationConverter for SpecAliasConverter {
34 fn spec_kinds(&self) -> &'static [&'static str] {
35 &["AddSpec", "RemoveSpec", "ValidateSpec"]
36 }
37
38 fn convert_v2(
39 &self,
40 spec: &MutationSpec,
41 ctx: &AnalysisContext,
42 ) -> Result<Vec<Box<dyn ASTRegApply>>, ConvertError> {
43 match spec {
44 MutationSpec::AddSpec {
45 type_id,
46 module_id,
47 group,
48 alias_name,
49 relations,
50 } => {
51 let wrapped_name = ctx
52 .registry
53 .resolve(*type_id)
54 .map(|p| p.name().to_string())
55 .ok_or_else(|| {
56 ConvertError::TargetNotFound(format!(
57 "AddSpec wrapped type SymbolId {:?} not in registry",
58 type_id
59 ))
60 })?;
61
62 let alias = alias_name
63 .clone()
64 .unwrap_or_else(|| format!("{}Spec", wrapped_name));
65
66 let content = if relations.is_empty() {
67 format!("pub type {} = Spec<{}, {}>;", alias, group, wrapped_name)
68 } else {
69 let rel_terms: Vec<String> = relations
70 .iter()
71 .map(|r| format!("{}<{}>", r.kind.as_type_name(), r.target))
72 .collect();
73 let rel_block = if rel_terms.len() == 1 {
74 rel_terms.into_iter().next().expect("len 1 above")
75 } else {
76 format!("({})", rel_terms.join(", "))
77 };
78 format!(
79 "pub type {} = SpecWith<{}, {}, {}>;",
80 alias, group, rel_block, wrapped_name
81 )
82 };
83
84 let mutation = AddItemMutation::new(*module_id, content);
85 Ok(vec![Box::new(mutation)])
86 }
87
88 MutationSpec::RemoveSpec { type_id, .. } => {
89 let mutation = RemoveItemMutation::new(*type_id, ItemKind::TypeAlias);
90 Ok(vec![Box::new(mutation)])
91 }
92
93 MutationSpec::ValidateSpec { .. } => {
94 Ok(vec![])
98 }
99
100 _ => Err(ConvertError::TypeMismatch {
101 expected: "AddSpec | RemoveSpec | ValidateSpec",
102 actual: spec.kind_name().to_string(),
103 }),
104 }
105 }
106}
107
108#[cfg(test)]
109mod tests {
110 use super::*;
111
112 #[test]
113 fn test_spec_alias_converter_spec_kinds() {
114 let converter = SpecAliasConverter::new();
115 assert_eq!(
116 converter.spec_kinds(),
117 &["AddSpec", "RemoveSpec", "ValidateSpec"]
118 );
119 }
120}