codama_plugin_core/
resolve_directives_visitor.rs1use crate::DirectiveResolver;
2use codama_attributes::{Attribute, CodamaDirective, Resolvable, SeedDirectiveType};
3use codama_errors::CodamaResult;
4use codama_korok_visitors::KorokVisitor;
5use codama_koroks::*;
6use codama_nodes::{InstructionInputValueNode, ValueNode};
7
8pub struct ResolveDirectivesVisitor<'a> {
14 resolver: &'a dyn DirectiveResolver,
15}
16
17impl<'a> ResolveDirectivesVisitor<'a> {
18 pub fn new(resolver: &'a dyn DirectiveResolver) -> Self {
19 Self { resolver }
20 }
21
22 fn resolve_attributes(
23 &self,
24 attributes: &mut codama_attributes::Attributes,
25 ) -> CodamaResult<()> {
26 for attr in attributes.iter_mut() {
27 let Attribute::Codama(codama_attr) = attr else {
28 continue;
29 };
30 self.resolve_directive(codama_attr.directive.as_mut())?;
31 }
32 Ok(())
33 }
34
35 fn resolve_directive(&self, directive: &mut CodamaDirective) -> CodamaResult<()> {
36 match directive {
37 CodamaDirective::Type(d) => {
38 self.resolve_type(&mut d.node)?;
39 }
40 CodamaDirective::DefaultValue(d) => {
41 self.resolve_instruction_input_value(&mut d.node)?;
42 }
43 CodamaDirective::Account(d) => {
44 if let Some(ref mut dv) = d.default_value {
45 self.resolve_instruction_input_value(dv)?;
46 }
47 }
48 CodamaDirective::Field(d) => {
49 self.resolve_type_node(&mut d.r#type)?;
50 if let Some(ref mut dv) = d.default_value {
51 self.resolve_value_node(dv)?;
52 }
53 }
54 CodamaDirective::Argument(d) => {
55 self.resolve_type_node(&mut d.r#type)?;
56 if let Some(ref mut dv) = d.default_value {
57 self.resolve_instruction_input_value(dv)?;
58 }
59 }
60 CodamaDirective::Seed(d) => match &mut d.seed {
61 SeedDirectiveType::Variable { r#type, .. } => {
62 self.resolve_type_node(r#type)?;
63 }
64 SeedDirectiveType::Constant { r#type, value } => {
65 self.resolve_type_node(r#type)?;
66 self.resolve_value_node(value)?;
67 }
68 SeedDirectiveType::Linked(_) => {}
69 },
70 _ => {}
72 }
73 Ok(())
74 }
75
76 fn resolve_type(
77 &self,
78 resolvable: &mut Resolvable<codama_nodes::RegisteredTypeNode>,
79 ) -> CodamaResult<()> {
80 if let Resolvable::Unresolved(directive) = resolvable {
81 let resolved = self.resolver.resolve_type_directive(directive)?;
82 *resolvable = Resolvable::Resolved(resolved);
83 }
84 Ok(())
85 }
86
87 fn resolve_type_node(
88 &self,
89 resolvable: &mut Resolvable<codama_nodes::TypeNode>,
90 ) -> CodamaResult<()> {
91 if let Resolvable::Unresolved(directive) = resolvable {
92 let registered = self.resolver.resolve_type_directive(directive)?;
93 let type_node = codama_nodes::TypeNode::try_from(registered)?;
94 *resolvable = Resolvable::Resolved(type_node);
95 }
96 Ok(())
97 }
98
99 fn resolve_instruction_input_value(
100 &self,
101 resolvable: &mut Resolvable<InstructionInputValueNode>,
102 ) -> CodamaResult<()> {
103 if let Resolvable::Unresolved(directive) = resolvable {
104 let resolved = self.resolver.resolve_value_directive(directive)?;
105 *resolvable = Resolvable::Resolved(resolved);
106 }
107 Ok(())
108 }
109
110 fn resolve_value_node(&self, resolvable: &mut Resolvable<ValueNode>) -> CodamaResult<()> {
111 if let Resolvable::Unresolved(directive) = resolvable {
112 let instruction_input = self.resolver.resolve_value_directive(directive)?;
113 let value_node = ValueNode::try_from(instruction_input)?;
114 *resolvable = Resolvable::Resolved(value_node);
115 }
116 Ok(())
117 }
118}
119
120impl KorokVisitor for ResolveDirectivesVisitor<'_> {
121 fn visit_root(&mut self, korok: &mut RootKorok) -> CodamaResult<()> {
122 self.visit_children(korok)
123 }
124
125 fn visit_crate(&mut self, korok: &mut CrateKorok) -> CodamaResult<()> {
126 self.resolve_attributes(&mut korok.attributes)?;
127 self.visit_children(korok)
128 }
129
130 fn visit_file_module(&mut self, korok: &mut FileModuleKorok) -> CodamaResult<()> {
131 self.resolve_attributes(&mut korok.attributes)?;
132 self.visit_children(korok)
133 }
134
135 fn visit_module(&mut self, korok: &mut ModuleKorok) -> CodamaResult<()> {
136 self.resolve_attributes(&mut korok.attributes)?;
137 self.visit_children(korok)
138 }
139
140 fn visit_struct(&mut self, korok: &mut StructKorok) -> CodamaResult<()> {
141 self.resolve_attributes(&mut korok.attributes)?;
142 self.visit_children(korok)
143 }
144
145 fn visit_enum(&mut self, korok: &mut EnumKorok) -> CodamaResult<()> {
146 self.resolve_attributes(&mut korok.attributes)?;
147 self.visit_children(korok)
148 }
149
150 fn visit_enum_variant(&mut self, korok: &mut EnumVariantKorok) -> CodamaResult<()> {
151 self.resolve_attributes(&mut korok.attributes)?;
152 self.visit_children(korok)
153 }
154
155 fn visit_field(&mut self, korok: &mut FieldKorok) -> CodamaResult<()> {
156 self.resolve_attributes(&mut korok.attributes)
157 }
158
159 fn visit_unsupported_item(&mut self, korok: &mut UnsupportedItemKorok) -> CodamaResult<()> {
160 self.resolve_attributes(&mut korok.attributes)
161 }
162
163 fn visit_impl(&mut self, korok: &mut ImplKorok) -> CodamaResult<()> {
164 self.resolve_attributes(&mut korok.attributes)?;
165 self.visit_children(korok)
166 }
167
168 fn visit_const(&mut self, korok: &mut ConstKorok) -> CodamaResult<()> {
169 self.resolve_attributes(&mut korok.attributes)
170 }
171
172 fn visit_unsupported_impl_item(
173 &mut self,
174 korok: &mut UnsupportedImplItemKorok,
175 ) -> CodamaResult<()> {
176 self.resolve_attributes(&mut korok.attributes)
177 }
178}