diff --git a/crates/cairo-lint-core/src/lints/mod.rs b/crates/cairo-lint-core/src/lints/mod.rs index f32c03e9..84d39ac1 100644 --- a/crates/cairo-lint-core/src/lints/mod.rs +++ b/crates/cairo-lint-core/src/lints/mod.rs @@ -1 +1,2 @@ +pub mod operator; pub mod single_match; diff --git a/crates/cairo-lint-core/src/lints/operator.rs b/crates/cairo-lint-core/src/lints/operator.rs new file mode 100644 index 00000000..d141de8c --- /dev/null +++ b/crates/cairo-lint-core/src/lints/operator.rs @@ -0,0 +1,28 @@ +use cairo_lang_defs::plugin::PluginDiagnostic; +use cairo_lang_diagnostics::Severity; +use cairo_lang_syntax::node::ast::{BinaryOperator, Expr, ExprBinary}; +use cairo_lang_syntax::node::db::SyntaxGroup; +use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode}; + +pub const ERASE_OP: &str = "This operation will always result in zero and can be simplified."; + +pub fn check_expr(db: &dyn SyntaxGroup, expr: &ExprBinary) -> Option { + let lhs = expr.lhs(db); + let rhs = expr.rhs(db); + + if is_zero_literal(db, &lhs) || is_zero_literal(db, &rhs) { + let op = expr.op(db); + if matches!(op, BinaryOperator::Mul(_) | BinaryOperator::Div(_) | BinaryOperator::And(_)) { + return Some(PluginDiagnostic { + stable_ptr: expr.stable_ptr().untyped(), + message: ERASE_OP.to_string(), + severity: Severity::Error, + }); + } + } + None +} + +fn is_zero_literal(db: &dyn SyntaxGroup, expr: &Expr) -> bool { + matches!(expr, Expr::Literal(lit) if lit.text(db) == "0") +} diff --git a/crates/cairo-lint-core/src/plugin.rs b/crates/cairo-lint-core/src/plugin.rs index 46204d47..50ed433e 100644 --- a/crates/cairo-lint-core/src/plugin.rs +++ b/crates/cairo-lint-core/src/plugin.rs @@ -6,8 +6,7 @@ use cairo_lang_syntax::node::ast::{BinaryOperator, ExprBinary, ExprMatch}; use cairo_lang_syntax::node::kind::SyntaxKind; use cairo_lang_syntax::node::{Terminal, TypedStablePtr, TypedSyntaxNode}; -use crate::erasing_op::EraseOp; -use crate::lints::single_match; +use crate::lints::{operator, single_match}; pub fn cairo_lint_plugin_suite() -> PluginSuite { let mut suite = PluginSuite::default(); @@ -30,7 +29,7 @@ pub fn diagnostic_kind_from_message(message: &str) -> CairoLintKind { single_match::DESTRUCT_MATCH => CairoLintKind::DestructMatch, single_match::MATCH_FOR_EQUALITY => CairoLintKind::MatchForEquality, "operation can be simplifield to zero" => CairoLintKind::EraseOp, - CairoLint::ERASE_OP => CairoLintKind::EraseOp, + operator::ERASE_OP => CairoLintKind::EraseOp, _ => CairoLintKind::Unknown, } } @@ -57,7 +56,7 @@ impl AnalyzerPlugin for CairoLint { ), SyntaxKind::ExprBinary => { let binary_expr = ExprBinary::from_syntax_node(db.upcast(), descendant); - if let Some(diagnostic) = self.check_expr(db.upcast(), &binary_expr) { + if let Some(diagnostic) = operator::check_expr(db.upcast(), &binary_expr) { diags.push(diagnostic); } } diff --git a/crates/cairo-lint-core/tests/test_files/erasing_op b/crates/cairo-lint-core/tests/test_files/erasing_op deleted file mode 100644 index 11651205..00000000 --- a/crates/cairo-lint-core/tests/test_files/erasing_op +++ /dev/null @@ -1,10 +0,0 @@ -//! > always in zero - -//! > cairo_code -fn main() { - let x = 1; - let _result = 0 * x; - let _result = 0 / x; - let _result = x & 0; -} - diff --git a/crates/cairo-lint-core/tests/test_files/operator/erasing_op b/crates/cairo-lint-core/tests/test_files/operator/erasing_op new file mode 100644 index 00000000..c3895c7a --- /dev/null +++ b/crates/cairo-lint-core/tests/test_files/operator/erasing_op @@ -0,0 +1,33 @@ +//! > always in zero + +//! > cairo_code +fn main() { + let x: u32 = 1; + let _result = 0 * x; + let _result = 0 / x; + let _result = x & 0; +} + +//! > diagnostics +warning: Plugin diagnostic: This operation will always result in zero and can be simplified. + --> lib.cairo:3:19 + let _result = 0 * x; + ^***^ + +warning: Plugin diagnostic: This operation will always result in zero and can be simplified. + --> lib.cairo:4:19 + let _result = 0 / x; + ^***^ + +warning: Plugin diagnostic: This operation will always result in zero and can be simplified. + --> lib.cairo:5:19 + let _result = x & 0; + ^***^ + +//! > fixed +fn main() { + let x: u32 = 1; + let _result = 0 * x; + let _result = 0 / x; + let _result = x & 0; +} diff --git a/crates/cairo-lint-core/tests/tests.rs b/crates/cairo-lint-core/tests/tests.rs index 76c2cfca..32e5ea30 100644 --- a/crates/cairo-lint-core/tests/tests.rs +++ b/crates/cairo-lint-core/tests/tests.rs @@ -34,4 +34,4 @@ test_file!( "simple destructuring match with comment in scope" ); -test_file!(erasing_op, "always in zero" ); \ No newline at end of file +test_file!(operator, erasing_op, "always in zero");