cairo_lint/lints/
empty_enum_brackets_variant.rs1use cairo_lang_defs::{ids::ModuleItemId, plugin::PluginDiagnostic};
2use cairo_lang_diagnostics::Severity;
3use cairo_lang_semantic::items::enm::EnumSemantic;
4use cairo_lang_syntax::node::{
5 SyntaxNode, TypedStablePtr, TypedSyntaxNode,
6 ast::{self, OptionTypeClause},
7};
8
9use crate::{
10 context::{CairoLintKind, Lint},
11 fixer::InternalFix,
12};
13use salsa::Database;
14
15pub struct EmptyEnumBracketsVariant;
16
17impl Lint for EmptyEnumBracketsVariant {
39 fn allowed_name(&self) -> &'static str {
40 "empty_enum_brackets_variant"
41 }
42
43 fn diagnostic_message(&self) -> &'static str {
44 "redundant parentheses in enum variant definition"
45 }
46
47 fn kind(&self) -> CairoLintKind {
48 CairoLintKind::EnumEmptyVariantBrackets
49 }
50
51 fn has_fixer(&self) -> bool {
52 true
53 }
54
55 fn fix<'db>(&self, db: &'db dyn Database, node: SyntaxNode<'db>) -> Option<InternalFix<'db>> {
56 fix_empty_enum_brackets_variant(db, node)
57 }
58
59 fn fix_message(&self) -> Option<&'static str> {
60 Some("Remove unit type definition from enum variant")
61 }
62}
63
64#[tracing::instrument(skip_all, level = "trace")]
65pub fn check_empty_enum_brackets_variant<'db>(
66 db: &'db dyn Database,
67 item: &ModuleItemId<'db>,
68 diagnostics: &mut Vec<PluginDiagnostic<'db>>,
69) {
70 let ModuleItemId::Enum(enum_id) = item else {
71 return;
72 };
73
74 let Ok(variants) = db.enum_variants(*enum_id) else {
75 return;
76 };
77
78 for variant in variants.values() {
79 let Ok(semantic_variant) = db.variant_semantic(*enum_id, *variant) else {
80 return;
81 };
82
83 if semantic_variant.ty.is_unit(db) {
85 let ast_variant = variant.stable_ptr(db).lookup(db);
86
87 if let OptionTypeClause::TypeClause(_) = ast_variant.type_clause(db) {
89 diagnostics.push(PluginDiagnostic {
90 stable_ptr: variant.stable_ptr(db).untyped(),
91 message: EmptyEnumBracketsVariant.diagnostic_message().to_string(),
92 severity: Severity::Warning,
93 inner_span: None,
94 error_code: None,
95 });
96 }
97 }
98 }
99}
100
101#[tracing::instrument(skip_all, level = "trace")]
102fn fix_empty_enum_brackets_variant<'db>(
103 db: &'db dyn Database,
104 node: SyntaxNode<'db>,
105) -> Option<InternalFix<'db>> {
106 let ast_variant = ast::Variant::from_syntax_node(db, node);
107
108 let type_clause = ast_variant
110 .type_clause(db)
111 .as_syntax_node()
112 .get_text_without_trivia(db);
113
114 let variant_text = node.get_text(db);
115 let fixed = variant_text.replace(type_clause.long(db).as_str(), "");
116
117 Some(InternalFix {
118 node,
119 suggestion: fixed,
120 description: EmptyEnumBracketsVariant.fix_message().unwrap().to_string(),
121 import_addition_paths: None,
122 })
123}