Skip to content

Commit f3d6d74

Browse files
Convert clippy to use the new parsed representation
1 parent 9ec42dd commit f3d6d74

File tree

10 files changed

+72
-57
lines changed

10 files changed

+72
-57
lines changed

src/tools/clippy/clippy_lints/src/attrs/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ mod utils;
1616
use clippy_config::Conf;
1717
use clippy_utils::diagnostics::span_lint_and_help;
1818
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
19-
use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind};
19+
use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind, AttrItemKind};
2020
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
2121
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
2222
use rustc_session::impl_lint_pass;
@@ -604,7 +604,7 @@ impl EarlyLintPass for PostExpansionEarlyAttributes {
604604

605605
if attr.has_name(sym::ignore)
606606
&& match &attr.kind {
607-
AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrArgs::Eq { .. }),
607+
AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrItemKind::Unparsed(AttrArgs::Eq { .. })),
608608
AttrKind::DocComment(..) => true,
609609
}
610610
{

src/tools/clippy/clippy_lints/src/attrs/should_panic_without_expect.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,19 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
22
use clippy_utils::diagnostics::span_lint_and_sugg;
33
use rustc_ast::token::{Token, TokenKind};
44
use rustc_ast::tokenstream::TokenTree;
5-
use rustc_ast::{AttrArgs, AttrKind};
5+
use rustc_ast::{AttrArgs, AttrKind, AttrItemKind};
66
use rustc_errors::Applicability;
77
use rustc_lint::EarlyContext;
88
use rustc_span::sym;
99

1010
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
1111
if let AttrKind::Normal(normal_attr) = &attr.kind {
12-
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
12+
if let AttrItemKind::Unparsed(AttrArgs::Eq { .. }) = &normal_attr.item.args {
1313
// `#[should_panic = ".."]` found, good
1414
return;
1515
}
1616

17-
if let AttrArgs::Delimited(args) = &normal_attr.item.args
17+
if let AttrItemKind::Unparsed(AttrArgs::Delimited(args)) = &normal_attr.item.args
1818
&& let mut tt_iter = args.tokens.iter()
1919
&& let Some(TokenTree::Token(
2020
Token {

src/tools/clippy/clippy_lints/src/cfg_not_test.rs

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
11
use clippy_utils::diagnostics::span_lint_and_then;
2-
use rustc_ast::MetaItemInner;
32
use rustc_lint::{EarlyContext, EarlyLintPass};
43
use rustc_session::declare_lint_pass;
4+
use rustc_ast::AttrItemKind;
5+
use rustc_ast::EarlyParsedAttribute;
6+
use rustc_span::sym;
7+
use rustc_ast::attr::data_structures::CfgEntry;
58

69
declare_clippy_lint! {
710
/// ### What it does
@@ -32,29 +35,34 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]);
3235

3336
impl EarlyLintPass for CfgNotTest {
3437
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
35-
if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) {
36-
span_lint_and_then(
37-
cx,
38-
CFG_NOT_TEST,
39-
attr.span,
40-
"code is excluded from test builds",
41-
|diag| {
42-
diag.help("consider not excluding any code from test builds");
43-
diag.note_once("this could increase code coverage despite not actually being tested");
44-
},
45-
);
38+
if attr.has_name(sym::cfg_trace) {
39+
let AttrItemKind::Parsed(EarlyParsedAttribute::CfgTrace(cfg)) = &attr.get_normal_item().args else {
40+
unreachable!()
41+
};
42+
43+
if contains_not_test(&cfg, false) {
44+
span_lint_and_then(
45+
cx,
46+
CFG_NOT_TEST,
47+
attr.span,
48+
"code is excluded from test builds",
49+
|diag| {
50+
diag.help("consider not excluding any code from test builds");
51+
diag.note_once("this could increase code coverage despite not actually being tested");
52+
},
53+
);
54+
}
4655
}
4756
}
4857
}
4958

50-
fn contains_not_test(list: Option<&[MetaItemInner]>, not: bool) -> bool {
51-
list.is_some_and(|list| {
52-
list.iter().any(|item| {
53-
item.ident().is_some_and(|ident| match ident.name {
54-
rustc_span::sym::not => contains_not_test(item.meta_item_list(), !not),
55-
rustc_span::sym::test => not,
56-
_ => contains_not_test(item.meta_item_list(), not),
57-
})
58-
})
59-
})
59+
fn contains_not_test(cfg: &CfgEntry, not: bool) -> bool {
60+
match cfg {
61+
CfgEntry::All(subs, _) | CfgEntry::Any(subs, _) => subs.iter().any(|item| {
62+
contains_not_test(item, not)
63+
}),
64+
CfgEntry::Not(sub, _) => contains_not_test(sub, !not),
65+
CfgEntry::NameValue { name: sym::test, .. } => not,
66+
_ => false
67+
}
6068
}

src/tools/clippy/clippy_lints/src/doc/include_in_doc_without_cfg.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
use clippy_utils::diagnostics::span_lint_and_sugg;
22
use clippy_utils::source::snippet_opt;
3-
use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute};
3+
use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute, AttrItemKind};
44
use rustc_errors::Applicability;
55
use rustc_lint::EarlyContext;
66

@@ -11,7 +11,7 @@ pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
1111
if !attr.span.from_expansion()
1212
&& let AttrKind::Normal(ref item) = attr.kind
1313
&& attr.doc_str().is_some()
14-
&& let AttrArgs::Eq { expr: meta, .. } = &item.item.args
14+
&& let AttrItemKind::Unparsed(AttrArgs::Eq { expr: meta, .. }) = &item.item.args
1515
&& !attr.span.contains(meta.span)
1616
// Since the `include_str` is already expanded at this point, we can only take the
1717
// whole attribute snippet and then modify for our suggestion.

src/tools/clippy/clippy_lints/src/incompatible_msrv.rs

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use rustc_middle::ty::{self, TyCtxt};
99
use rustc_session::impl_lint_pass;
1010
use rustc_span::def_id::{CrateNum, DefId};
1111
use rustc_span::{ExpnKind, Span};
12+
use rustc_hir::attrs::AttributeKind;
13+
use rustc_hir::find_attr;
1214

1315
declare_clippy_lint! {
1416
/// ### What it does
@@ -268,11 +270,6 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv {
268270
/// attribute.
269271
fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool {
270272
cx.tcx.hir_parent_id_iter(hir_id).any(|id| {
271-
cx.tcx.hir_attrs(id).iter().any(|attr| {
272-
matches!(
273-
attr.ident().map(|ident| ident.name),
274-
Some(sym::cfg_trace | sym::cfg_attr_trace)
275-
)
276-
})
273+
find_attr!(cx.tcx.hir_attrs(id), AttributeKind::CfgTrace(..) | AttributeKind::CfgAttrTrace)
277274
})
278275
}

src/tools/clippy/clippy_lints/src/large_include_file.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use rustc_ast::AttrItemKind;
12
use clippy_config::Conf;
23
use clippy_utils::diagnostics::span_lint_and_then;
34
use clippy_utils::macros::root_macro_call_first_node;
@@ -92,7 +93,7 @@ impl EarlyLintPass for LargeIncludeFile {
9293
&& let AttrKind::Normal(ref item) = attr.kind
9394
&& let Some(doc) = attr.doc_str()
9495
&& doc.as_str().len() as u64 > self.max_file_size
95-
&& let AttrArgs::Eq { expr: meta, .. } = &item.item.args
96+
&& let AttrItemKind::Unparsed(AttrArgs::Eq { expr: meta, .. }) = &item.item.args
9697
&& !attr.span.contains(meta.span)
9798
// Since the `include_str` is already expanded at this point, we can only take the
9899
// whole attribute snippet and then modify for our suggestion.

src/tools/clippy/clippy_lints/src/methods/is_empty.rs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ use clippy_utils::res::MaybeResPath;
55
use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context};
66
use rustc_hir::{Expr, HirId};
77
use rustc_lint::{LateContext, LintContext};
8-
use rustc_span::sym;
8+
use rustc_hir::attrs::AttributeKind;
9+
use rustc_hir::find_attr;
910

1011
use super::CONST_IS_EMPTY;
1112

@@ -40,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
4041
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
4142
cx.tcx
4243
.hir_parent_id_iter(id)
43-
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace)))
44+
.any(|id| find_attr!(cx.tcx.hir_attrs(id), AttributeKind::CfgTrace(..)))
4445
}
4546

4647
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization

src/tools/clippy/clippy_lints/src/new_without_default.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
99
use rustc_middle::ty::AssocKind;
1010
use rustc_session::impl_lint_pass;
1111
use rustc_span::sym;
12+
use rustc_hir::Attribute;
13+
use rustc_hir::attrs::AttributeKind;
1214

1315
declare_clippy_lint! {
1416
/// ### What it does
@@ -121,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
121123
let attrs_sugg = {
122124
let mut sugg = String::new();
123125
for attr in cx.tcx.hir_attrs(assoc_item_hir_id) {
124-
if !attr.has_name(sym::cfg_trace) {
126+
let Attribute::Parsed(AttributeKind::CfgTrace(attrs)) = attr else {
125127
// This might be some other attribute that the `impl Default` ought to inherit.
126128
// But it could also be one of the many attributes that:
127129
// - can't be put on an impl block -- like `#[inline]`
@@ -131,10 +133,13 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
131133
// reduce the applicability
132134
app = Applicability::MaybeIncorrect;
133135
continue;
136+
};
137+
138+
for (_, attr_span) in attrs {
139+
sugg.push_str(&snippet_with_applicability(cx.sess(), *attr_span, "_", &mut app));
140+
sugg.push('\n');
134141
}
135142

136-
sugg.push_str(&snippet_with_applicability(cx.sess(), attr.span(), "_", &mut app));
137-
sugg.push('\n');
138143
}
139144
sugg
140145
};

src/tools/clippy/clippy_utils/src/ast_utils/mod.rs

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -976,11 +976,19 @@ pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool {
976976
l.style == r.style
977977
&& match (&l.kind, &r.kind) {
978978
(DocComment(l1, l2), DocComment(r1, r2)) => l1 == r1 && l2 == r2,
979-
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_args(&l.item.args, &r.item.args),
979+
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_item_kind(&l.item.args, &r.item.args),
980980
_ => false,
981981
}
982982
}
983983

984+
pub fn eq_attr_item_kind(l: &AttrItemKind, r: &AttrItemKind) -> bool {
985+
match (l, r) {
986+
(AttrItemKind::Unparsed(l), AttrItemKind::Unparsed(r)) => eq_attr_args(l, r),
987+
(AttrItemKind::Parsed(_l), AttrItemKind::Parsed(_r)) => todo!(),
988+
_ => false,
989+
}
990+
}
991+
984992
pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
985993
use AttrArgs::*;
986994
match (l, r) {

src/tools/clippy/clippy_utils/src/lib.rs

Lines changed: 10 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,7 @@ use rustc_middle::ty::{
121121
self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt,
122122
TypeFlags, TypeVisitableExt, UintTy, UpvarCapture,
123123
};
124+
use rustc_hir::attrs::CfgEntry;
124125
use rustc_span::hygiene::{ExpnKind, MacroKind};
125126
use rustc_span::source_map::SourceMap;
126127
use rustc_span::symbol::{Ident, Symbol, kw};
@@ -2401,17 +2402,12 @@ pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool {
24012402
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
24022403
/// use [`is_in_cfg_test`]
24032404
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
2404-
tcx.hir_attrs(id).iter().any(|attr| {
2405-
if attr.has_name(sym::cfg_trace)
2406-
&& let Some(items) = attr.meta_item_list()
2407-
&& let [item] = &*items
2408-
&& item.has_name(sym::test)
2409-
{
2410-
true
2411-
} else {
2412-
false
2413-
}
2414-
})
2405+
if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), AttributeKind::CfgTrace(cfgs) => cfgs)
2406+
&& cfgs.iter().any(|(cfg, _)| { matches!(cfg, CfgEntry::NameValue { name: sym::test, ..})}) {
2407+
true
2408+
} else {
2409+
false
2410+
}
24152411
}
24162412

24172413
/// Checks if any parent node of `HirId` has `#[cfg(test)]` attribute applied
@@ -2426,11 +2422,10 @@ pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool {
24262422

24272423
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
24282424
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
2429-
tcx.has_attr(def_id, sym::cfg_trace)
2430-
|| tcx
2425+
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::CfgTrace(..))
2426+
|| find_attr!(tcx
24312427
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
2432-
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
2433-
.any(|attr| attr.has_name(sym::cfg_trace))
2428+
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)), AttributeKind::CfgTrace(..))
24342429
}
24352430

24362431
/// Walks up the HIR tree from the given expression in an attempt to find where the value is

0 commit comments

Comments
 (0)