cairo_lang_plugins/plugins/
compile_error.rs

1use cairo_lang_defs::extract_macro_single_unnamed_arg;
2use cairo_lang_defs::plugin::{MacroPlugin, MacroPluginMetadata, PluginDiagnostic, PluginResult};
3use cairo_lang_defs::plugin_utils::{PluginResultTrait, not_legacy_macro_diagnostic};
4use cairo_lang_filesystem::ids::SmolStrId;
5use cairo_lang_parser::macro_helpers::AsLegacyInlineMacro;
6use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode, ast};
7use salsa::Database;
8
9/// Plugin that allows writing item level `compile_error!` causing a diagnostic.
10/// Useful for testing that `cfg` attributes are valid.
11#[derive(Debug, Default)]
12#[non_exhaustive]
13pub struct CompileErrorPlugin;
14
15impl MacroPlugin for CompileErrorPlugin {
16    fn generate_code<'db>(
17        &self,
18        db: &'db dyn Database,
19        item_ast: ast::ModuleItem<'db>,
20        _metadata: &MacroPluginMetadata<'_>,
21    ) -> PluginResult<'db> {
22        let ast::ModuleItem::InlineMacro(inline_macro_ast) = item_ast else {
23            return Default::default();
24        };
25        if inline_macro_ast.path(db).as_syntax_node().get_text_without_trivia(db).long(db)
26            != "compile_error"
27        {
28            return Default::default();
29        }
30        let item_ast_ptr = inline_macro_ast.stable_ptr(db).untyped();
31        let Some(legacy_inline_macro_ast) = inline_macro_ast.as_legacy_inline_macro(db) else {
32            return PluginResult::diagnostic_only(not_legacy_macro_diagnostic(item_ast_ptr));
33        };
34        let compilation_error_arg = extract_macro_single_unnamed_arg!(
35            db,
36            &legacy_inline_macro_ast,
37            ast::WrappedArgList::ParenthesizedArgList(_),
38            item_ast_ptr
39        );
40        PluginResult::diagnostic_only(
41            if let ast::Expr::String(err_message) = compilation_error_arg {
42                PluginDiagnostic::error(item_ast_ptr, err_message.text(db).to_string(db))
43            } else {
44                PluginDiagnostic::error_with_inner_span(
45                    db,
46                    item_ast_ptr,
47                    compilation_error_arg.as_syntax_node(),
48                    "`compile_error!` argument must be an unnamed string argument.".to_string(),
49                )
50            },
51        )
52    }
53
54    fn declared_attributes<'db>(&self, _db: &'db dyn Database) -> Vec<SmolStrId<'db>> {
55        vec![]
56    }
57}