diff options
| author | Jonathan Dönszelmann <jonathan@donsz.nl> | 2025-02-06 21:44:00 +0100 |
|---|---|---|
| committer | Jana Dönszelmann <jana@donsz.nl> | 2025-02-07 16:47:26 +0100 |
| commit | 4044c1aa496e39e4fc1ec34d646d84ea639253ad (patch) | |
| tree | 30d826ef33280b06afb4ae54e50aead4f44c471a | |
| parent | 42453bd73a39ef96727774159d300f0a27aec73d (diff) | |
| download | rust-4044c1aa496e39e4fc1ec34d646d84ea639253ad.tar.gz rust-4044c1aa496e39e4fc1ec34d646d84ea639253ad.zip | |
fix empty after lint on impl/trait items
Co-authored-by: Guillaume Gomez <guillaume1.gomez@gmail.com>
| -rw-r--r-- | clippy_lints/src/empty_line_after.rs | 113 | ||||
| -rw-r--r-- | tests/ui/empty_line_after/doc_comments.1.fixed | 9 | ||||
| -rw-r--r-- | tests/ui/empty_line_after/doc_comments.2.fixed | 9 | ||||
| -rw-r--r-- | tests/ui/empty_line_after/doc_comments.rs | 10 | ||||
| -rw-r--r-- | tests/ui/empty_line_after/doc_comments.stderr | 13 |
5 files changed, 116 insertions, 38 deletions
diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index 4f1c6186cfe..89ddd885b6e 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/clippy_lints/src/empty_line_after.rs @@ -3,13 +3,13 @@ use clippy_utils::source::{SpanRangeExt, snippet_indent}; use clippy_utils::tokenize_with_text; use itertools::Itertools; use rustc_ast::token::CommentKind; -use rustc_ast::{AttrKind, AttrStyle, Attribute, Crate, Item, ItemKind, ModKind, NodeId}; +use rustc_ast::{AssocItemKind, AttrKind, AttrStyle, Attribute, Crate, Item, ItemKind, ModKind, NodeId}; use rustc_errors::{Applicability, Diag, SuggestionStyle}; use rustc_lexer::TokenKind; use rustc_lint::{EarlyContext, EarlyLintPass, LintContext}; use rustc_session::impl_lint_pass; use rustc_span::symbol::kw; -use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData, Symbol}; +use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol}; declare_clippy_lint! { /// ### What it does @@ -92,7 +92,7 @@ struct ItemInfo { kind: &'static str, name: Symbol, span: Span, - mod_items: Vec<NodeId>, + mod_items: Option<NodeId>, } pub struct EmptyLineAfter { @@ -347,7 +347,7 @@ impl EmptyLineAfter { fn suggest_inner(&self, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) { if let Some(parent) = self.items.iter().rev().nth(1) && (parent.kind == "module" || parent.kind == "crate") - && parent.mod_items.first() == Some(&id) + && parent.mod_items == Some(id) { let desc = if parent.kind == "module" { "parent module" @@ -367,48 +367,35 @@ impl EmptyLineAfter { ); } } -} -impl EarlyLintPass for EmptyLineAfter { - fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) { + fn check_item_kind( + &mut self, + cx: &EarlyContext<'_>, + kind: &ItemKind, + ident: &Ident, + span: Span, + attrs: &[Attribute], + id: NodeId, + ) { self.items.push(ItemInfo { - kind: "crate", - name: kw::Crate, - span: krate.spans.inner_span.with_hi(krate.spans.inner_span.lo()), - mod_items: krate - .items - .iter() - .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_))) - .map(|i| i.id) - .collect::<Vec<_>>(), - }); - } - - fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) { - self.items.pop(); - } - - fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { - self.items.push(ItemInfo { - kind: item.kind.descr(), - name: item.ident.name, - span: if item.span.contains(item.ident.span) { - item.span.with_hi(item.ident.span.hi()) + kind: kind.descr(), + name: ident.name, + span: if span.contains(ident.span) { + span.with_hi(ident.span.hi()) } else { - item.span.with_hi(item.span.lo()) + span.with_hi(span.lo()) }, - mod_items: match item.kind { - ItemKind::Mod(_, ModKind::Loaded(ref items, _, _, _)) => items + mod_items: match kind { + ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items .iter() .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_))) .map(|i| i.id) - .collect::<Vec<_>>(), - _ => Vec::new(), + .next(), + _ => None, }, }); - let mut outer = item - .attrs + let mut outer = attrs .iter() .filter(|attr| attr.style == AttrStyle::Outer && !attr.span.from_expansion()) .map(|attr| Stop::from_attr(cx, attr)) @@ -448,6 +435,58 @@ impl EarlyLintPass for EmptyLineAfter { } } - self.check_gaps(cx, &gaps, item.id); + self.check_gaps(cx, &gaps, id); + } +} + +impl EarlyLintPass for EmptyLineAfter { + fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) { + self.items.push(ItemInfo { + kind: "crate", + name: kw::Crate, + span: krate.spans.inner_span.with_hi(krate.spans.inner_span.lo()), + mod_items: krate + .items + .iter() + .filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_))) + .map(|i| i.id) + .next(), + }); + } + + fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) { + self.items.pop(); + } + fn check_impl_item_post(&mut self, _: &EarlyContext<'_>, _: &Item<AssocItemKind>) { + self.items.pop(); + } + fn check_trait_item_post(&mut self, _: &EarlyContext<'_>, _: &Item<AssocItemKind>) { + self.items.pop(); + } + + fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>) { + self.check_item_kind( + cx, + &item.kind.clone().into(), + &item.ident, + item.span, + &item.attrs, + item.id, + ); + } + + fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>) { + self.check_item_kind( + cx, + &item.kind.clone().into(), + &item.ident, + item.span, + &item.attrs, + item.id, + ); + } + + fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) { + self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id); } } diff --git a/tests/ui/empty_line_after/doc_comments.1.fixed b/tests/ui/empty_line_after/doc_comments.1.fixed index fd6a94b6a80..3772b465fdb 100644 --- a/tests/ui/empty_line_after/doc_comments.1.fixed +++ b/tests/ui/empty_line_after/doc_comments.1.fixed @@ -132,4 +132,13 @@ pub struct BlockComment; ))] fn empty_line_in_cfg_attr() {} +trait Foo { + fn bar(); +} + +impl Foo for LineComment { + /// comment on assoc item + fn bar() {} +} + fn main() {} diff --git a/tests/ui/empty_line_after/doc_comments.2.fixed b/tests/ui/empty_line_after/doc_comments.2.fixed index 7a57dcd9233..3028d03b669 100644 --- a/tests/ui/empty_line_after/doc_comments.2.fixed +++ b/tests/ui/empty_line_after/doc_comments.2.fixed @@ -141,4 +141,13 @@ pub struct BlockComment; ))] fn empty_line_in_cfg_attr() {} +trait Foo { + fn bar(); +} + +impl Foo for LineComment { + /// comment on assoc item + fn bar() {} +} + fn main() {} diff --git a/tests/ui/empty_line_after/doc_comments.rs b/tests/ui/empty_line_after/doc_comments.rs index 1da761a5c3d..ae4ebc271fa 100644 --- a/tests/ui/empty_line_after/doc_comments.rs +++ b/tests/ui/empty_line_after/doc_comments.rs @@ -144,4 +144,14 @@ pub struct BlockComment; ))] fn empty_line_in_cfg_attr() {} +trait Foo { + fn bar(); +} + +impl Foo for LineComment { + /// comment on assoc item + + fn bar() {} +} + fn main() {} diff --git a/tests/ui/empty_line_after/doc_comments.stderr b/tests/ui/empty_line_after/doc_comments.stderr index d71c888e196..10189665f01 100644 --- a/tests/ui/empty_line_after/doc_comments.stderr +++ b/tests/ui/empty_line_after/doc_comments.stderr @@ -171,5 +171,16 @@ help: if the doc comment should not document `new_code2` comment it out LL | // /// Docs for `old_code2` | ++ -error: aborting due to 10 previous errors +error: empty line after doc comment + --> tests/ui/empty_line_after/doc_comments.rs:152:5 + | +LL | / /// comment on assoc item +LL | | + | |_^ +LL | fn bar() {} + | ------ the comment documents this function + | + = help: if the empty line is unintentional remove it + +error: aborting due to 11 previous errors |
