cairo_lang_starknet/inline_macros/
get_dep_component.rs1use cairo_lang_defs::extract_macro_unnamed_args;
2use cairo_lang_defs::patcher::{PatchBuilder, RewriteNode};
3use cairo_lang_defs::plugin::{
4 InlineMacroExprPlugin, InlinePluginResult, MacroPluginMetadata, NamedPlugin, PluginDiagnostic,
5 PluginGeneratedFile,
6};
7use cairo_lang_syntax::node::db::SyntaxGroup;
8use cairo_lang_syntax::node::{TypedStablePtr, TypedSyntaxNode, ast};
9use cairo_lang_utils::extract_matches;
10
11#[derive(Debug, Default)]
13pub struct GetDepComponentMacro;
14impl NamedPlugin for GetDepComponentMacro {
15 const NAME: &'static str = "get_dep_component";
16}
17impl InlineMacroExprPlugin for GetDepComponentMacro {
18 fn generate_code(
19 &self,
20 db: &dyn SyntaxGroup,
21 syntax: &ast::ExprInlineMacro,
22 _metadata: &MacroPluginMetadata<'_>,
23 ) -> InlinePluginResult {
24 get_dep_component_generate_code_helper(db, syntax, false)
25 }
26}
27
28#[derive(Debug, Default)]
30pub struct GetDepComponentMutMacro;
31impl NamedPlugin for GetDepComponentMutMacro {
32 const NAME: &'static str = "get_dep_component_mut";
33}
34impl InlineMacroExprPlugin for GetDepComponentMutMacro {
35 fn generate_code(
36 &self,
37 db: &dyn SyntaxGroup,
38 syntax: &ast::ExprInlineMacro,
39 _metadata: &MacroPluginMetadata<'_>,
40 ) -> InlinePluginResult {
41 get_dep_component_generate_code_helper(db, syntax, true)
42 }
43}
44
45fn get_dep_component_generate_code_helper(
48 db: &dyn SyntaxGroup,
49 syntax: &ast::ExprInlineMacro,
50 is_mut: bool,
51) -> InlinePluginResult {
52 let [contract_arg, component_impl_arg] =
53 extract_macro_unnamed_args!(db, syntax, 2, ast::WrappedArgList::ParenthesizedArgList(_));
54
55 if is_mut {
56 let contract_arg_modifiers =
58 extract_matches!(syntax.arguments(db), ast::WrappedArgList::ParenthesizedArgList)
59 .arguments(db)
60 .elements(db)[0]
61 .modifiers(db)
62 .elements(db);
63
64 if !matches!(&contract_arg_modifiers[..], &[ast::Modifier::Ref(_)]) {
66 let diagnostics = vec![PluginDiagnostic::error(
69 contract_arg.stable_ptr().untyped(),
70 format!(
71 "The first argument of `{}` macro must have only a `ref` modifier.",
72 GetDepComponentMutMacro::NAME
73 ),
74 )];
75 return InlinePluginResult { code: None, diagnostics };
76 };
77 }
78 let mut builder = PatchBuilder::new(db, syntax);
79 let (let_part, maybe_mut, maybe_ref) =
80 if is_mut { ("let mut", "_mut", "ref ") } else { ("let", "", "") };
81 builder.add_modified(RewriteNode::interpolate_patched(
82 &format!(
83 "
84 {{
85 {let_part} __get_dep_component_macro_temp_contract__ = \
86 HasComponent::get_contract{maybe_mut}({maybe_ref}$contract_path$);
87 $component_impl_path$::get_component{maybe_mut}({maybe_ref}\
88 __get_dep_component_macro_temp_contract__)
89 }}
90 "
91 ),
92 &[
93 ("contract_path".to_string(), RewriteNode::from_ast_trimmed(&contract_arg)),
94 ("component_impl_path".to_string(), RewriteNode::from_ast_trimmed(&component_impl_arg)),
95 ]
96 .into(),
97 ));
98
99 let (content, code_mappings) = builder.build();
100 InlinePluginResult {
101 code: Some(PluginGeneratedFile {
102 name: "get_dep_component_inline_macro".into(),
103 content,
104 code_mappings,
105 aux_data: None,
106 diagnostics_note: Default::default(),
107 }),
108 diagnostics: vec![],
109 }
110}