Skip to content

Commit

Permalink
test(core): properly test destructuring match
Browse files Browse the repository at this point in the history
  • Loading branch information
0xLucqs committed Aug 8, 2024
1 parent e9a0f8b commit 3e55ed5
Show file tree
Hide file tree
Showing 8 changed files with 365 additions and 73 deletions.
2 changes: 1 addition & 1 deletion crates/cairo-lint-core/src/fix.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ impl Fixer {
"{}if let {} = {} {{ {} }}",
node.get_text(db).chars().take_while(|c| c.is_whitespace()).collect::<String>(),
pattern,
match_expr.expr(db).as_syntax_node().get_text(db),
match_expr.expr(db).as_syntax_node().get_text_without_trivia(db),
first_expr.expression(db).as_syntax_node().get_text_without_trivia(db),
)
}
Expand Down
21 changes: 15 additions & 6 deletions crates/cairo-lint-core/src/plugin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,18 +27,23 @@ pub enum CairoLintKind {

pub fn diagnostic_kind_from_message(message: &str) -> CairoLintKind {
match message {
CairoLint::IF_LET => CairoLintKind::IfLet,
CairoLint::DESTRUCT_IF_LET => CairoLintKind::IfLet,
CairoLint::IF => CairoLintKind::If,
_ => CairoLintKind::Unknown,
}
}

impl CairoLint {
const IF_LET: &'static str =
const DESTRUCT_IF_LET: &'static str =
"you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`";
const IF: &'static str = "you seem to be trying to use `match` for an equality check. Consider using `if`";

pub fn check_match(&self, db: &dyn SyntaxGroup, match_expr: &ExprMatch, diagnostics: &mut Vec<PluginDiagnostic>) {
pub fn check_match_destruct(
&self,
db: &dyn SyntaxGroup,
match_expr: &ExprMatch,
diagnostics: &mut Vec<PluginDiagnostic>,
) {
let arms = match_expr.arms(db).deref().elements(db);
let mut is_single_armed = false;
let mut is_destructuring = false;
Expand All @@ -50,6 +55,9 @@ impl CairoLint {
let tuple_expr = match arm.expression(db) {
Expr::Block(block_expr) => {
let statements = block_expr.statements(db).elements(db);
if statements.is_empty() {
is_single_armed = true;
}
if statements.len() == 1 {
match &statements[0] {
Statement::Expr(statement_expr) => {
Expand All @@ -68,7 +76,8 @@ impl CairoLint {
Expr::Tuple(tuple_expr) => Some(tuple_expr),
_ => None,
};
is_single_armed = tuple_expr.is_some_and(|list| list.expressions(db).elements(db).is_empty());
is_single_armed = tuple_expr.is_some_and(|list| list.expressions(db).elements(db).is_empty())
|| is_single_armed;
}

Pattern::Enum(pat) => {
Expand All @@ -89,7 +98,7 @@ impl CairoLint {
}),
(true, true) => diagnostics.push(PluginDiagnostic {
stable_ptr: match_expr.stable_ptr().untyped(),
message: Self::IF_LET.to_string(),
message: Self::DESTRUCT_IF_LET.to_string(),
severity: Severity::Warning,
}),
(_, _) => (),
Expand All @@ -111,7 +120,7 @@ impl AnalyzerPlugin for CairoLint {
let descendants = func.as_syntax_node().descendants(db.upcast());
for descendant in descendants.into_iter() {
match descendant.kind(db.upcast()) {
SyntaxKind::ExprMatch => self.check_match(
SyntaxKind::ExprMatch => self.check_match_destruct(
db.upcast(),
&ExprMatch::from_syntax_node(db.upcast(), descendant),
&mut diags,
Expand Down
321 changes: 321 additions & 0 deletions crates/cairo-lint-core/tests/test_files/destruct_if_let
Original file line number Diff line number Diff line change
@@ -0,0 +1,321 @@
//! > simple destructuring match with scope

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
Option::Some(a) => println!("{a}"),
_ => {},
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| Option::Some(a) => println!("{a}"),
| _ => {},
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > simple destructuring match with scope second arm

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
_ => {},
Option::Some(a) => println!("{a}"),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| _ => {},
| Option::Some(a) => println!("{a}"),
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > simple destructuring match with unit in scope

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
Option::Some(a) => println!("{a}"),
_ => { () },
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| Option::Some(a) => println!("{a}"),
| _ => { () },
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > nested destructuring match

//! > cairo_code
fn main() {
let variable = Option::Some(Option::Some(1_felt252));
match variable {
Option::Some(a) => match a {
Option::Some(b) => println!("{b}"),
_ => (),
},
_ => (),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| Option::Some(a) => match a {
| Option::Some(b) => println!("{b}"),
| _ => (),
| },
| _ => (),
| }
|___^

warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:4:22
\ Option::Some(a) => match a {
| Option::Some(b) => println!("{b}"),
| _ => (),
| }
|___^

//! > fixed
Contains nested diagnostics can't fix it

//! > ==========================================================================

//! > nested destructuring match twisted differently

//! > cairo_code
fn main() {
let variable = Option::Some(Option::Some(1_felt252));
match variable {
_ => (),
Option::Some(a) => match a {
Option::Some(b) => println!("{b}"),
_ => (),
},
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| _ => (),
| Option::Some(a) => match a {
| Option::Some(b) => println!("{b}"),
| _ => (),
| },
| }
|___^

warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:5:22
\ Option::Some(a) => match a {
| Option::Some(b) => println!("{b}"),
| _ => (),
| }
|___^

//! > fixed
Contains nested diagnostics can't fix it

//! > ==========================================================================

//! > nested destructuring match twisted

//! > cairo_code
fn main() {
let variable = Option::Some(Option::Some(1_felt252));
match variable {
Option::Some(a) => match a {
_ => (),
Option::Some(b) => println!("{b}"),
},
_ => (),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| Option::Some(a) => match a {
| _ => (),
| Option::Some(b) => println!("{b}"),
| },
| _ => (),
| }
|___^

warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:4:22
\ Option::Some(a) => match a {
| _ => (),
| Option::Some(b) => println!("{b}"),
| }
|___^

//! > fixed
Contains nested diagnostics can't fix it

//! > ==========================================================================

//! > simple destructuring match second arm

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
_ => (),
Option::Some(a) => println!("{a}"),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| _ => (),
| Option::Some(a) => println!("{a}"),
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > simple destructuring match with unit in scope second arm

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
_ => { () },
Option::Some(a) => println!("{a}"),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| _ => { () },
| Option::Some(a) => println!("{a}"),
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > simple destructuring match

//! > cairo_code
fn main() {
let variable = Option::Some(1_felt252);
match variable {
Option::Some(a) => println!("{a}"),
_ => (),
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| Option::Some(a) => println!("{a}"),
| _ => (),
| }
|___^

//! > fixed
fn main() {
let variable = Option::Some(1_felt252);
if let Option::Some(a) = variable { println!("{a}") };
}

//! > ==========================================================================

//! > nested destructuring match second arm

//! > cairo_code
fn main() {
let variable = Option::Some(Option::Some(1_felt252));
match variable {
_ => (),
Option::Some(a) => match a {
_ => (),
Option::Some(b) => println!("{b}"),
},
};
}

//! > diagnostics
warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:3:2
\ match variable {
| _ => (),
| Option::Some(a) => match a {
| _ => (),
| Option::Some(b) => println!("{b}"),
| },
| }
|___^

warning: Plugin diagnostic: you seem to be trying to use `match` for destructuring a single pattern. Consider using `if let`
--> lib.cairo:5:22
\ Option::Some(a) => match a {
| _ => (),
| Option::Some(b) => println!("{b}"),
| }
|___^

//! > fixed
Contains nested diagnostics can't fix it
Loading

0 comments on commit 3e55ed5

Please sign in to comment.