diff options
| author | granddaifuku <daifukuformac@gmail.com> | 2024-03-25 02:17:56 +0900 |
|---|---|---|
| committer | granddaifuku <daifukuformac@gmail.com> | 2024-03-25 02:17:56 +0900 |
| commit | 2a62200b8d5ba65d583199a296c3fbbf8e58aa25 (patch) | |
| tree | 7f1bd1ba52bb03f4bc4acdc7af49ba225c8fb921 | |
| parent | 95c62ffae9bbce793f68a6f1473e3fc24af19bdd (diff) | |
| download | rust-2a62200b8d5ba65d583199a296c3fbbf8e58aa25.tar.gz rust-2a62200b8d5ba65d583199a296c3fbbf8e58aa25.zip | |
fix: suspicious_else_formatting false positive when else is included in comments
| -rw-r--r-- | clippy_lints/src/formatting.rs | 43 | ||||
| -rw-r--r-- | tests/ui/suspicious_else_formatting.rs | 28 |
2 files changed, 70 insertions, 1 deletions
diff --git a/clippy_lints/src/formatting.rs b/clippy_lints/src/formatting.rs index c3ef6f180c9..5b8d4ea8956 100644 --- a/clippy_lints/src/formatting.rs +++ b/clippy_lints/src/formatting.rs @@ -214,7 +214,7 @@ fn check_else(cx: &EarlyContext<'_>, expr: &Expr) { // the snippet should look like " else \n " with maybe comments anywhere // it’s bad when there is a ‘\n’ after the “else” && let Some(else_snippet) = snippet_opt(cx, else_span) - && let Some((pre_else, post_else)) = else_snippet.split_once("else") + && let Some((pre_else, post_else)) = split_once_with_else(&else_snippet) && let Some((_, post_else_post_eol)) = post_else.split_once('\n') { // Allow allman style braces `} \n else \n {` @@ -323,3 +323,44 @@ fn is_block(expr: &Expr) -> bool { fn is_if(expr: &Expr) -> bool { matches!(expr.kind, ExprKind::If(..)) } + +fn split_once_with_else(base: &str) -> Option<(&str, &str)> { + let else_str = "else"; + + let indices: Vec<_> = base.match_indices(else_str).map(|(i, _)| i).collect(); + + match indices.len() { + 0 => return None, + 1 => return base.split_once(else_str), + _ => {}, + } + + let mut i = 0; + let mut is_in_comment = false; + + for line in base.lines() { + if let Some(else_pos) = line.find(else_str) { + if let Some(pos) = line.find("//") { + if pos > else_pos { + return Some(base.split_at(indices[i])); + } + } else if let Some(pos) = line.find("/*") { + if pos > else_pos { + return Some(base.split_at(indices[i])); + } + is_in_comment = true; + } else if let Some(pos) = line.find("*/") { + if pos < else_pos { + return Some(base.split_at(indices[i])); + } + is_in_comment = false; + } else if !is_in_comment { + return Some(base.split_at(indices[i])); + } + + i += 1; + } + } + + None +} diff --git a/tests/ui/suspicious_else_formatting.rs b/tests/ui/suspicious_else_formatting.rs index c0856427eae..3d5c892eb60 100644 --- a/tests/ui/suspicious_else_formatting.rs +++ b/tests/ui/suspicious_else_formatting.rs @@ -120,6 +120,34 @@ fn main() { /* whelp */ { } + + // #12497 Don't trigger lint as rustfmt wants it + if true { + println!("true"); + } + /*else if false { +}*/ + else { + println!("false"); + } + + if true { + println!("true"); + } // else if false {} + else { + println!("false"); + } + + if true { + println!("true"); + } /* if true { + println!("true"); +} + */ + else { + println!("false"); + } + } // #7650 - Don't lint. Proc-macro using bad spans for `if` expressions. |
