diff options
| author | Jason Newcomb <jsnewcomb@pm.me> | 2024-06-12 20:14:50 -0400 |
|---|---|---|
| committer | Jason Newcomb <jsnewcomb@pm.me> | 2024-07-07 16:41:36 -0400 |
| commit | ca5c2813eb7e988c4d2a25312f5749cf6686230e (patch) | |
| tree | 6c68303b82baccd24776c56220de0553bdeba2b7 | |
| parent | aef07100544f44c6813fc811e9f0440551ce418d (diff) | |
| download | rust-ca5c2813eb7e988c4d2a25312f5749cf6686230e.tar.gz rust-ca5c2813eb7e988c4d2a25312f5749cf6686230e.zip | |
`items_after_statements`: Do less work in the default case.
| -rw-r--r-- | clippy_lints/src/items_after_statements.rs | 59 |
1 files changed, 29 insertions, 30 deletions
diff --git a/clippy_lints/src/items_after_statements.rs b/clippy_lints/src/items_after_statements.rs index 39223c20470..a88d8e24fda 100644 --- a/clippy_lints/src/items_after_statements.rs +++ b/clippy_lints/src/items_after_statements.rs @@ -54,36 +54,35 @@ declare_lint_pass!(ItemsAfterStatements => [ITEMS_AFTER_STATEMENTS]); impl LateLintPass<'_> for ItemsAfterStatements { fn check_block(&mut self, cx: &LateContext<'_>, block: &Block<'_>) { - if in_external_macro(cx.sess(), block.span) { - return; - } - - // skip initial items - let stmts = block - .stmts - .iter() - .skip_while(|stmt| matches!(stmt.kind, StmtKind::Item(..))); - - // lint on all further items - for stmt in stmts { - if let StmtKind::Item(item_id) = stmt.kind { - let item = cx.tcx.hir().item(item_id); - if in_external_macro(cx.sess(), item.span) || !item.span.eq_ctxt(block.span) { - return; - } - if let ItemKind::Macro(..) = item.kind { - // do not lint `macro_rules`, but continue processing further statements - continue; - } - span_lint_hir( - cx, - ITEMS_AFTER_STATEMENTS, - item.hir_id(), - item.span, - "adding items after statements is confusing, since items exist from the \ - start of the scope", - ); - } + if block.stmts.len() > 1 { + let ctxt = block.span.ctxt(); + let mut in_external = None; + block + .stmts + .iter() + .skip_while(|stmt| matches!(stmt.kind, StmtKind::Item(..))) + .filter_map(|stmt| match stmt.kind { + StmtKind::Item(id) => Some(cx.tcx.hir().item(id)), + _ => None, + }) + // Ignore macros since they can only see previously defined locals. + .filter(|item| !matches!(item.kind, ItemKind::Macro(..))) + // Stop linting if macros define items. + .take_while(|item| item.span.ctxt() == ctxt) + // Don't use `next` due to the complex filter chain. + .for_each(|item| { + // Only do the macro check once, but delay it until it's needed. + if !*in_external.get_or_insert_with(|| in_external_macro(cx.sess(), block.span)) { + span_lint_hir( + cx, + ITEMS_AFTER_STATEMENTS, + item.hir_id(), + item.span, + "adding items after statements is confusing, since items exist from the \ + start of the scope", + ); + } + }); } } } |
