Skip to content

Commit 0a9401f

Browse files
fix empty after lint on impl/trait items
Co-authored-by: Guillaume Gomez <guillaume1.gomez@gmail.com>
1 parent 24487b1 commit 0a9401f

File tree

7 files changed

+141
-38
lines changed

7 files changed

+141
-38
lines changed

compiler/rustc_lint/src/early.rs

+8
Original file line numberDiff line numberDiff line change
@@ -246,6 +246,14 @@ impl<'ast, 'ecx, 'tcx, T: EarlyLintPass> ast_visit::Visitor<'ast>
246246
}
247247
}
248248
ast_visit::walk_assoc_item(cx, item, ctxt);
249+
match ctxt {
250+
ast_visit::AssocCtxt::Trait => {
251+
lint_callback!(cx, check_trait_item_post, item);
252+
}
253+
ast_visit::AssocCtxt::Impl => {
254+
lint_callback!(cx, check_impl_item_post, item);
255+
}
256+
}
249257
});
250258
}
251259

compiler/rustc_lint/src/passes.rs

+2
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,9 @@ macro_rules! early_lint_methods {
161161
c: rustc_span::Span,
162162
d_: rustc_ast::NodeId);
163163
fn check_trait_item(a: &rustc_ast::AssocItem);
164+
fn check_trait_item_post(a: &rustc_ast::AssocItem);
164165
fn check_impl_item(a: &rustc_ast::AssocItem);
166+
fn check_impl_item_post(a: &rustc_ast::AssocItem);
165167
fn check_variant(a: &rustc_ast::Variant);
166168
fn check_attribute(a: &rustc_ast::Attribute);
167169
fn check_attributes(a: &[rustc_ast::Attribute]);

src/tools/clippy/clippy_lints/src/empty_line_after.rs

+76-37
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@ use clippy_utils::source::{SpanRangeExt, snippet_indent};
33
use clippy_utils::tokenize_with_text;
44
use itertools::Itertools;
55
use rustc_ast::token::CommentKind;
6-
use rustc_ast::{AttrKind, AttrStyle, Attribute, Crate, Item, ItemKind, ModKind, NodeId};
6+
use rustc_ast::{AssocItemKind, AttrKind, AttrStyle, Attribute, Crate, Item, ItemKind, ModKind, NodeId};
77
use rustc_errors::{Applicability, Diag, SuggestionStyle};
88
use rustc_lexer::TokenKind;
99
use rustc_lint::{EarlyContext, EarlyLintPass, LintContext};
1010
use rustc_session::impl_lint_pass;
1111
use rustc_span::symbol::kw;
12-
use rustc_span::{BytePos, ExpnKind, InnerSpan, Span, SpanData, Symbol};
12+
use rustc_span::{BytePos, ExpnKind, Ident, InnerSpan, Span, SpanData, Symbol};
1313

1414
declare_clippy_lint! {
1515
/// ### What it does
@@ -92,7 +92,7 @@ struct ItemInfo {
9292
kind: &'static str,
9393
name: Symbol,
9494
span: Span,
95-
mod_items: Vec<NodeId>,
95+
mod_items: Option<NodeId>,
9696
}
9797

9898
pub struct EmptyLineAfter {
@@ -347,7 +347,7 @@ impl EmptyLineAfter {
347347
fn suggest_inner(&self, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) {
348348
if let Some(parent) = self.items.iter().rev().nth(1)
349349
&& (parent.kind == "module" || parent.kind == "crate")
350-
&& parent.mod_items.first() == Some(&id)
350+
&& parent.mod_items == Some(id)
351351
{
352352
let desc = if parent.kind == "module" {
353353
"parent module"
@@ -367,48 +367,35 @@ impl EmptyLineAfter {
367367
);
368368
}
369369
}
370-
}
371370

372-
impl EarlyLintPass for EmptyLineAfter {
373-
fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
371+
fn check_item_kind(
372+
&mut self,
373+
cx: &EarlyContext<'_>,
374+
kind: &ItemKind,
375+
ident: &Ident,
376+
span: Span,
377+
attrs: &[Attribute],
378+
id: NodeId,
379+
) {
374380
self.items.push(ItemInfo {
375-
kind: "crate",
376-
name: kw::Crate,
377-
span: krate.spans.inner_span.with_hi(krate.spans.inner_span.lo()),
378-
mod_items: krate
379-
.items
380-
.iter()
381-
.filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
382-
.map(|i| i.id)
383-
.collect::<Vec<_>>(),
384-
});
385-
}
386-
387-
fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) {
388-
self.items.pop();
389-
}
390-
391-
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
392-
self.items.push(ItemInfo {
393-
kind: item.kind.descr(),
394-
name: item.ident.name,
395-
span: if item.span.contains(item.ident.span) {
396-
item.span.with_hi(item.ident.span.hi())
381+
kind: kind.descr(),
382+
name: ident.name,
383+
span: if span.contains(ident.span) {
384+
span.with_hi(ident.span.hi())
397385
} else {
398-
item.span.with_hi(item.span.lo())
386+
span.with_hi(span.lo())
399387
},
400-
mod_items: match item.kind {
401-
ItemKind::Mod(_, ModKind::Loaded(ref items, _, _, _)) => items
388+
mod_items: match kind {
389+
ItemKind::Mod(_, ModKind::Loaded(items, _, _, _)) => items
402390
.iter()
403391
.filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
404392
.map(|i| i.id)
405-
.collect::<Vec<_>>(),
406-
_ => Vec::new(),
393+
.next(),
394+
_ => None,
407395
},
408396
});
409397

410-
let mut outer = item
411-
.attrs
398+
let mut outer = attrs
412399
.iter()
413400
.filter(|attr| attr.style == AttrStyle::Outer && !attr.span.from_expansion())
414401
.map(|attr| Stop::from_attr(cx, attr))
@@ -448,6 +435,58 @@ impl EarlyLintPass for EmptyLineAfter {
448435
}
449436
}
450437

451-
self.check_gaps(cx, &gaps, item.id);
438+
self.check_gaps(cx, &gaps, id);
439+
}
440+
}
441+
442+
impl EarlyLintPass for EmptyLineAfter {
443+
fn check_crate(&mut self, _: &EarlyContext<'_>, krate: &Crate) {
444+
self.items.push(ItemInfo {
445+
kind: "crate",
446+
name: kw::Crate,
447+
span: krate.spans.inner_span.with_hi(krate.spans.inner_span.lo()),
448+
mod_items: krate
449+
.items
450+
.iter()
451+
.filter(|i| !matches!(i.span.ctxt().outer_expn_data().kind, ExpnKind::AstPass(_)))
452+
.map(|i| i.id)
453+
.next(),
454+
});
455+
}
456+
457+
fn check_item_post(&mut self, _: &EarlyContext<'_>, _: &Item) {
458+
self.items.pop();
459+
}
460+
fn check_impl_item_post(&mut self, _: &EarlyContext<'_>, _: &Item<AssocItemKind>) {
461+
self.items.pop();
462+
}
463+
fn check_trait_item_post(&mut self, _: &EarlyContext<'_>, _: &Item<AssocItemKind>) {
464+
self.items.pop();
465+
}
466+
467+
fn check_impl_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>) {
468+
self.check_item_kind(
469+
cx,
470+
&item.kind.clone().into(),
471+
&item.ident,
472+
item.span,
473+
&item.attrs,
474+
item.id,
475+
);
476+
}
477+
478+
fn check_trait_item(&mut self, cx: &EarlyContext<'_>, item: &Item<AssocItemKind>) {
479+
self.check_item_kind(
480+
cx,
481+
&item.kind.clone().into(),
482+
&item.ident,
483+
item.span,
484+
&item.attrs,
485+
item.id,
486+
);
487+
}
488+
489+
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &Item) {
490+
self.check_item_kind(cx, &item.kind, &item.ident, item.span, &item.attrs, item.id);
452491
}
453492
}

src/tools/clippy/tests/ui/empty_line_after/doc_comments.1.fixed

+14
Original file line numberDiff line numberDiff line change
@@ -132,4 +132,18 @@ pub struct BlockComment;
132132
))]
133133
fn empty_line_in_cfg_attr() {}
134134

135+
trait Foo {
136+
fn bar();
137+
}
138+
139+
impl Foo for LineComment {
140+
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
141+
///
142+
/// `Month::from_i64(n: i64)`: | `1` | `2` | ... | `12`
143+
/// ---------------------------| -------------------- | --------------------- | ... | -----
144+
/// ``: | Some(Month::January) | Some(Month::February) | ... |
145+
/// Some(Month::December)
146+
fn bar() {}
147+
}
148+
135149
fn main() {}

src/tools/clippy/tests/ui/empty_line_after/doc_comments.2.fixed

+14
Original file line numberDiff line numberDiff line change
@@ -141,4 +141,18 @@ pub struct BlockComment;
141141
))]
142142
fn empty_line_in_cfg_attr() {}
143143

144+
trait Foo {
145+
fn bar();
146+
}
147+
148+
impl Foo for LineComment {
149+
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
150+
///
151+
/// `Month::from_i64(n: i64)`: | `1` | `2` | ... | `12`
152+
/// ---------------------------| -------------------- | --------------------- | ... | -----
153+
/// ``: | Some(Month::January) | Some(Month::February) | ... |
154+
/// Some(Month::December)
155+
fn bar() {}
156+
}
157+
144158
fn main() {}

src/tools/clippy/tests/ui/empty_line_after/doc_comments.rs

+15
Original file line numberDiff line numberDiff line change
@@ -144,4 +144,19 @@ pub struct BlockComment;
144144
))]
145145
fn empty_line_in_cfg_attr() {}
146146

147+
trait Foo {
148+
fn bar();
149+
}
150+
151+
impl Foo for LineComment {
152+
/// Returns an `Option<Month>` from a i64, assuming a 1-index, January = 1.
153+
///
154+
/// `Month::from_i64(n: i64)`: | `1` | `2` | ... | `12`
155+
/// ---------------------------| -------------------- | --------------------- | ... | -----
156+
/// ``: | Some(Month::January) | Some(Month::February) | ... |
157+
/// Some(Month::December)
158+
159+
fn bar() {}
160+
}
161+
147162
fn main() {}

src/tools/clippy/tests/ui/empty_line_after/doc_comments.stderr

+12-1
Original file line numberDiff line numberDiff line change
@@ -171,5 +171,16 @@ help: if the doc comment should not document `new_code2` comment it out
171171
LL | // /// Docs for `old_code2`
172172
| ++
173173

174-
error: aborting due to 10 previous errors
174+
error: empty line after doc comment
175+
--> tests/ui/empty_line_after/doc_comments.rs:157:5
176+
|
177+
LL | / /// Some(Month::December)
178+
LL | |
179+
| |_^
180+
LL | fn bar() {}
181+
| ------ the comment documents this function
182+
|
183+
= help: if the empty line is unintentional remove it
184+
185+
error: aborting due to 11 previous errors
175186

0 commit comments

Comments
 (0)