Convert clippy to use the new parsed representation
This commit is contained in:
parent
8df2c6de9a
commit
f1ce0dd4de
10 changed files with 72 additions and 57 deletions
|
|
@ -16,7 +16,7 @@ mod utils;
|
|||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::span_lint_and_help;
|
||||
use clippy_utils::msrvs::{self, Msrv, MsrvStack};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind};
|
||||
use rustc_ast::{self as ast, AttrArgs, AttrKind, Attribute, MetaItemInner, MetaItemKind, AttrItemKind};
|
||||
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
|
||||
use rustc_session::impl_lint_pass;
|
||||
|
|
@ -604,7 +604,7 @@ impl EarlyLintPass for PostExpansionEarlyAttributes {
|
|||
|
||||
if attr.has_name(sym::ignore)
|
||||
&& match &attr.kind {
|
||||
AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrArgs::Eq { .. }),
|
||||
AttrKind::Normal(normal_attr) => !matches!(normal_attr.item.args, AttrItemKind::Unparsed(AttrArgs::Eq { .. })),
|
||||
AttrKind::DocComment(..) => true,
|
||||
}
|
||||
{
|
||||
|
|
|
|||
|
|
@ -2,19 +2,19 @@ use super::{Attribute, SHOULD_PANIC_WITHOUT_EXPECT};
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use rustc_ast::token::{Token, TokenKind};
|
||||
use rustc_ast::tokenstream::TokenTree;
|
||||
use rustc_ast::{AttrArgs, AttrKind};
|
||||
use rustc_ast::{AttrArgs, AttrKind, AttrItemKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
use rustc_span::sym;
|
||||
|
||||
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
|
||||
if let AttrKind::Normal(normal_attr) = &attr.kind {
|
||||
if let AttrArgs::Eq { .. } = &normal_attr.item.args {
|
||||
if let AttrItemKind::Unparsed(AttrArgs::Eq { .. }) = &normal_attr.item.args {
|
||||
// `#[should_panic = ".."]` found, good
|
||||
return;
|
||||
}
|
||||
|
||||
if let AttrArgs::Delimited(args) = &normal_attr.item.args
|
||||
if let AttrItemKind::Unparsed(AttrArgs::Delimited(args)) = &normal_attr.item.args
|
||||
&& let mut tt_iter = args.tokens.iter()
|
||||
&& let Some(TokenTree::Token(
|
||||
Token {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,10 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use rustc_ast::MetaItemInner;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::declare_lint_pass;
|
||||
use rustc_ast::AttrItemKind;
|
||||
use rustc_ast::EarlyParsedAttribute;
|
||||
use rustc_span::sym;
|
||||
use rustc_ast::attr::data_structures::CfgEntry;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -32,29 +35,34 @@ declare_lint_pass!(CfgNotTest => [CFG_NOT_TEST]);
|
|||
|
||||
impl EarlyLintPass for CfgNotTest {
|
||||
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &rustc_ast::Attribute) {
|
||||
if attr.has_name(rustc_span::sym::cfg_trace) && contains_not_test(attr.meta_item_list().as_deref(), false) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
CFG_NOT_TEST,
|
||||
attr.span,
|
||||
"code is excluded from test builds",
|
||||
|diag| {
|
||||
diag.help("consider not excluding any code from test builds");
|
||||
diag.note_once("this could increase code coverage despite not actually being tested");
|
||||
},
|
||||
);
|
||||
if attr.has_name(sym::cfg_trace) {
|
||||
let AttrItemKind::Parsed(EarlyParsedAttribute::CfgTrace(cfg)) = &attr.get_normal_item().args else {
|
||||
unreachable!()
|
||||
};
|
||||
|
||||
if contains_not_test(&cfg, false) {
|
||||
span_lint_and_then(
|
||||
cx,
|
||||
CFG_NOT_TEST,
|
||||
attr.span,
|
||||
"code is excluded from test builds",
|
||||
|diag| {
|
||||
diag.help("consider not excluding any code from test builds");
|
||||
diag.note_once("this could increase code coverage despite not actually being tested");
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn contains_not_test(list: Option<&[MetaItemInner]>, not: bool) -> bool {
|
||||
list.is_some_and(|list| {
|
||||
list.iter().any(|item| {
|
||||
item.ident().is_some_and(|ident| match ident.name {
|
||||
rustc_span::sym::not => contains_not_test(item.meta_item_list(), !not),
|
||||
rustc_span::sym::test => not,
|
||||
_ => contains_not_test(item.meta_item_list(), not),
|
||||
})
|
||||
})
|
||||
})
|
||||
fn contains_not_test(cfg: &CfgEntry, not: bool) -> bool {
|
||||
match cfg {
|
||||
CfgEntry::All(subs, _) | CfgEntry::Any(subs, _) => subs.iter().any(|item| {
|
||||
contains_not_test(item, not)
|
||||
}),
|
||||
CfgEntry::Not(sub, _) => contains_not_test(sub, !not),
|
||||
CfgEntry::NameValue { name: sym::test, .. } => not,
|
||||
_ => false
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
use clippy_utils::diagnostics::span_lint_and_sugg;
|
||||
use clippy_utils::source::snippet_opt;
|
||||
use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute};
|
||||
use rustc_ast::{AttrArgs, AttrKind, AttrStyle, Attribute, AttrItemKind};
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::EarlyContext;
|
||||
|
||||
|
|
@ -11,7 +11,7 @@ pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
|
|||
if !attr.span.from_expansion()
|
||||
&& let AttrKind::Normal(ref item) = attr.kind
|
||||
&& attr.doc_str().is_some()
|
||||
&& let AttrArgs::Eq { expr: meta, .. } = &item.item.args
|
||||
&& let AttrItemKind::Unparsed(AttrArgs::Eq { expr: meta, .. }) = &item.item.args
|
||||
&& !attr.span.contains(meta.span)
|
||||
// Since the `include_str` is already expanded at this point, we can only take the
|
||||
// whole attribute snippet and then modify for our suggestion.
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use rustc_middle::ty::{self, TyCtxt};
|
|||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::def_id::{CrateNum, DefId};
|
||||
use rustc_span::{ExpnKind, Span};
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::find_attr;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -268,11 +270,6 @@ impl<'tcx> LateLintPass<'tcx> for IncompatibleMsrv {
|
|||
/// attribute.
|
||||
fn is_under_cfg_attribute(cx: &LateContext<'_>, hir_id: HirId) -> bool {
|
||||
cx.tcx.hir_parent_id_iter(hir_id).any(|id| {
|
||||
cx.tcx.hir_attrs(id).iter().any(|attr| {
|
||||
matches!(
|
||||
attr.name(),
|
||||
Some(sym::cfg_trace | sym::cfg_attr_trace)
|
||||
)
|
||||
})
|
||||
find_attr!(cx.tcx.hir_attrs(id), AttributeKind::CfgTrace(..) | AttributeKind::CfgAttrTrace)
|
||||
})
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
use rustc_ast::AttrItemKind;
|
||||
use clippy_config::Conf;
|
||||
use clippy_utils::diagnostics::span_lint_and_then;
|
||||
use clippy_utils::macros::root_macro_call_first_node;
|
||||
|
|
@ -92,7 +93,7 @@ impl EarlyLintPass for LargeIncludeFile {
|
|||
&& let AttrKind::Normal(ref item) = attr.kind
|
||||
&& let Some(doc) = attr.doc_str()
|
||||
&& doc.as_str().len() as u64 > self.max_file_size
|
||||
&& let AttrArgs::Eq { expr: meta, .. } = &item.item.args
|
||||
&& let AttrItemKind::Unparsed(AttrArgs::Eq { expr: meta, .. }) = &item.item.args
|
||||
&& !attr.span.contains(meta.span)
|
||||
// Since the `include_str` is already expanded at this point, we can only take the
|
||||
// whole attribute snippet and then modify for our suggestion.
|
||||
|
|
|
|||
|
|
@ -5,7 +5,8 @@ use clippy_utils::res::MaybeResPath;
|
|||
use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context};
|
||||
use rustc_hir::{Expr, HirId};
|
||||
use rustc_lint::{LateContext, LintContext};
|
||||
use rustc_span::sym;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
use rustc_hir::find_attr;
|
||||
|
||||
use super::CONST_IS_EMPTY;
|
||||
|
||||
|
|
@ -40,7 +41,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &'_ Expr<'_>, receiver: &Expr<'_
|
|||
fn is_under_cfg(cx: &LateContext<'_>, id: HirId) -> bool {
|
||||
cx.tcx
|
||||
.hir_parent_id_iter(id)
|
||||
.any(|id| cx.tcx.hir_attrs(id).iter().any(|attr| attr.has_name(sym::cfg_trace)))
|
||||
.any(|id| find_attr!(cx.tcx.hir_attrs(id), AttributeKind::CfgTrace(..)))
|
||||
}
|
||||
|
||||
/// Similar to [`clippy_utils::expr_or_init`], but does not go up the chain if the initialization
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ use rustc_lint::{LateContext, LateLintPass, LintContext};
|
|||
use rustc_middle::ty::AssocKind;
|
||||
use rustc_session::impl_lint_pass;
|
||||
use rustc_span::sym;
|
||||
use rustc_hir::Attribute;
|
||||
use rustc_hir::attrs::AttributeKind;
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// ### What it does
|
||||
|
|
@ -121,7 +123,7 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
|||
let attrs_sugg = {
|
||||
let mut sugg = String::new();
|
||||
for attr in cx.tcx.hir_attrs(assoc_item_hir_id) {
|
||||
if !attr.has_name(sym::cfg_trace) {
|
||||
let Attribute::Parsed(AttributeKind::CfgTrace(attrs)) = attr else {
|
||||
// This might be some other attribute that the `impl Default` ought to inherit.
|
||||
// But it could also be one of the many attributes that:
|
||||
// - can't be put on an impl block -- like `#[inline]`
|
||||
|
|
@ -131,10 +133,13 @@ impl<'tcx> LateLintPass<'tcx> for NewWithoutDefault {
|
|||
// reduce the applicability
|
||||
app = Applicability::MaybeIncorrect;
|
||||
continue;
|
||||
};
|
||||
|
||||
for (_, attr_span) in attrs {
|
||||
sugg.push_str(&snippet_with_applicability(cx.sess(), *attr_span, "_", &mut app));
|
||||
sugg.push('\n');
|
||||
}
|
||||
|
||||
sugg.push_str(&snippet_with_applicability(cx.sess(), attr.span(), "_", &mut app));
|
||||
sugg.push('\n');
|
||||
}
|
||||
sugg
|
||||
};
|
||||
|
|
|
|||
|
|
@ -976,11 +976,19 @@ pub fn eq_attr(l: &Attribute, r: &Attribute) -> bool {
|
|||
l.style == r.style
|
||||
&& match (&l.kind, &r.kind) {
|
||||
(DocComment(l1, l2), DocComment(r1, r2)) => l1 == r1 && l2 == r2,
|
||||
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_args(&l.item.args, &r.item.args),
|
||||
(Normal(l), Normal(r)) => eq_path(&l.item.path, &r.item.path) && eq_attr_item_kind(&l.item.args, &r.item.args),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eq_attr_item_kind(l: &AttrItemKind, r: &AttrItemKind) -> bool {
|
||||
match (l, r) {
|
||||
(AttrItemKind::Unparsed(l), AttrItemKind::Unparsed(r)) => eq_attr_args(l, r),
|
||||
(AttrItemKind::Parsed(_l), AttrItemKind::Parsed(_r)) => todo!(),
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn eq_attr_args(l: &AttrArgs, r: &AttrArgs) -> bool {
|
||||
use AttrArgs::*;
|
||||
match (l, r) {
|
||||
|
|
|
|||
|
|
@ -121,6 +121,7 @@ use rustc_middle::ty::{
|
|||
self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt,
|
||||
TypeFlags, TypeVisitableExt, UintTy, UpvarCapture,
|
||||
};
|
||||
use rustc_hir::attrs::CfgEntry;
|
||||
use rustc_span::hygiene::{ExpnKind, MacroKind};
|
||||
use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::symbol::{Ident, Symbol, kw};
|
||||
|
|
@ -2401,17 +2402,12 @@ pub fn is_test_function(tcx: TyCtxt<'_>, fn_def_id: LocalDefId) -> bool {
|
|||
/// This only checks directly applied attributes, to see if a node is inside a `#[cfg(test)]` parent
|
||||
/// use [`is_in_cfg_test`]
|
||||
pub fn is_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool {
|
||||
tcx.hir_attrs(id).iter().any(|attr| {
|
||||
if attr.has_name(sym::cfg_trace)
|
||||
&& let Some(items) = attr.meta_item_list()
|
||||
&& let [item] = &*items
|
||||
&& item.has_name(sym::test)
|
||||
{
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
})
|
||||
if let Some(cfgs) = find_attr!(tcx.hir_attrs(id), AttributeKind::CfgTrace(cfgs) => cfgs)
|
||||
&& cfgs.iter().any(|(cfg, _)| { matches!(cfg, CfgEntry::NameValue { name: sym::test, ..})}) {
|
||||
true
|
||||
} else {
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
/// 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 {
|
|||
|
||||
/// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied.
|
||||
pub fn inherits_cfg(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool {
|
||||
tcx.has_attr(def_id, sym::cfg_trace)
|
||||
|| tcx
|
||||
find_attr!(tcx.get_all_attrs(def_id), AttributeKind::CfgTrace(..))
|
||||
|| find_attr!(tcx
|
||||
.hir_parent_iter(tcx.local_def_id_to_hir_id(def_id))
|
||||
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id))
|
||||
.any(|attr| attr.has_name(sym::cfg_trace))
|
||||
.flat_map(|(parent_id, _)| tcx.hir_attrs(parent_id)), AttributeKind::CfgTrace(..))
|
||||
}
|
||||
|
||||
/// Walks up the HIR tree from the given expression in an attempt to find where the value is
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue