cairo_lang_starknet/plugin/
mod.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
#[cfg(test)]
mod test;

pub mod consts;

use cairo_lang_defs::plugin::{MacroPlugin, MacroPluginMetadata, PluginResult};
use cairo_lang_syntax::node::db::SyntaxGroup;
use cairo_lang_syntax::node::helpers::QueryAttrs;
use cairo_lang_syntax::node::{ast, Terminal};
use consts::*;

pub mod aux_data;
mod derive;
mod dispatcher;
mod embeddable;
mod entry_point;
pub mod events;
mod starknet_module;
mod storage;
pub(crate) mod storage_interfaces;
mod utils;

use dispatcher::handle_trait;

use self::derive::{derive_needed, handle_derive};
use self::embeddable::handle_embeddable;
use self::starknet_module::{handle_module, handle_module_by_storage};

#[derive(Debug, Default)]
#[non_exhaustive]
pub struct StarkNetPlugin;

impl MacroPlugin for StarkNetPlugin {
    fn generate_code(
        &self,
        db: &dyn SyntaxGroup,
        item_ast: ast::ModuleItem,
        metadata: &MacroPluginMetadata<'_>,
    ) -> PluginResult {
        match item_ast {
            ast::ModuleItem::Module(module_ast) => handle_module(db, module_ast),
            ast::ModuleItem::Trait(trait_ast) => handle_trait(db, trait_ast),
            ast::ModuleItem::Impl(impl_ast) if impl_ast.has_attr(db, EMBEDDABLE_ATTR) => {
                handle_embeddable(db, impl_ast)
            }
            ast::ModuleItem::Struct(struct_ast) if struct_ast.has_attr(db, STORAGE_ATTR) => {
                handle_module_by_storage(db, struct_ast, metadata).unwrap_or_default()
            }
            ast::ModuleItem::Struct(_) | ast::ModuleItem::Enum(_)
                if derive_needed(&item_ast, db) =>
            {
                handle_derive(db, item_ast, metadata)
            }
            ast::ModuleItem::InlineMacro(inline_macro_ast)
                if inline_macro_ast.name(db).text(db) == COMPONENT_INLINE_MACRO =>
            {
                // The macro is expanded in handle_module_by_storage, but we also need to remove the
                // original code.
                starknet_module::contract::remove_component_inline_macro(db, &inline_macro_ast)
            }
            // Nothing to do for other items.
            _ => PluginResult::default(),
        }
    }

    fn declared_attributes(&self) -> Vec<String> {
        vec![
            ABI_ATTR.to_string(),
            COMPONENT_ATTR.to_string(),
            CONSTRUCTOR_ATTR.to_string(),
            CONTRACT_ATTR.to_string(),
            EMBEDDABLE_AS_ATTR.to_string(),
            EMBEDDABLE_ATTR.to_string(),
            EVENT_ATTR.to_string(),
            EXTERNAL_ATTR.to_string(),
            FLAT_ATTR.to_string(),
            INTERFACE_ATTR.to_string(),
            KEY_ATTR.to_string(),
            L1_HANDLER_ATTR.to_string(),
            NESTED_ATTR.to_string(),
            RAW_OUTPUT_ATTR.to_string(),
            STORAGE_ATTR.to_string(),
            SUBSTORAGE_ATTR.to_string(),
        ]
    }

    fn declared_derives(&self) -> Vec<String> {
        vec!["starknet::Event".to_string(), "starknet::Store".to_string()]
    }

    fn phantom_type_attributes(&self) -> Vec<String> {
        vec![STORAGE_ATTR.to_string()]
    }
}