Move two attribute lints to be early pass (post expansion)

This commit is contained in:
Jonathan Dönszelmann 2024-11-04 14:55:07 +01:00
parent ca87b535a0
commit f4b72dcff0
No known key found for this signature in database
15 changed files with 122 additions and 112 deletions

View File

@ -3,11 +3,11 @@
use clippy_utils::is_from_proc_macro;
use rustc_ast::{AttrStyle, Attribute};
use rustc_errors::Applicability;
use rustc_lint::{LateContext, LintContext};
use rustc_lint::{EarlyContext, LintContext};
use rustc_middle::lint::in_external_macro;
// Separate each crate's features.
pub fn check<'cx>(cx: &LateContext<'cx>, attr: &'cx Attribute) {
pub fn check<'cx>(cx: &EarlyContext<'cx>, attr: &'cx Attribute) {
if !in_external_macro(cx.sess(), attr.span)
&& let AttrStyle::Outer = attr.style
&& let Some(ident) = attr.ident()

View File

@ -2,12 +2,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::is_from_proc_macro;
use rustc_ast::{MetaItemInner, MetaItemKind};
use rustc_lint::{LateContext, LintContext};
use rustc_lint::{EarlyContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_span::sym;
use rustc_span::symbol::Symbol;
pub(super) fn check<'cx>(cx: &LateContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
pub(super) fn check<'cx>(cx: &EarlyContext<'cx>, name: Symbol, items: &[MetaItemInner], attr: &'cx Attribute) {
// Check if the reason is present
if let Some(item) = items.last().and_then(MetaItemInner::meta_item)
&& let MetaItemKind::NameValue(_) = &item.kind

View File

@ -2,11 +2,11 @@
use super::utils::extract_clippy_lint;
use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_then};
use rustc_ast::MetaItemInner;
use rustc_lint::{LateContext, Level, LintContext};
use rustc_lint::{EarlyContext, Level, LintContext};
use rustc_span::symbol::Symbol;
use rustc_span::{DUMMY_SP, sym};
pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner]) {
pub(super) fn check(cx: &EarlyContext<'_>, name: Symbol, items: &[MetaItemInner]) {
for lint in items {
if let Some(lint_name) = extract_clippy_lint(lint) {
if lint_name.as_str() == "restriction" && name != sym::allow {
@ -23,7 +23,7 @@ pub(super) fn check(cx: &LateContext<'_>, name: Symbol, items: &[MetaItemInner])
}
}
pub(super) fn check_command_line(cx: &LateContext<'_>) {
pub(super) fn check_command_line(cx: &EarlyContext<'_>) {
for (name, level) in &cx.sess().opts.lint_opts {
if name == "clippy::restriction" && *level > Level::Allow {
span_lint_and_then(

View File

@ -1,11 +1,11 @@
use super::DEPRECATED_SEMVER;
use clippy_utils::diagnostics::span_lint;
use rustc_ast::{LitKind, MetaItemLit};
use rustc_lint::LateContext;
use rustc_lint::EarlyContext;
use rustc_span::Span;
use semver::Version;
pub(super) fn check(cx: &LateContext<'_>, span: Span, lit: &MetaItemLit) {
pub(super) fn check(cx: &EarlyContext<'_>, span: Span, lit: &MetaItemLit) {
if let LitKind::Str(is, _) = lit.kind {
if is.as_str() == "TBD" || Version::parse(is.as_str()).is_ok() {
return;

View File

@ -2,12 +2,12 @@
use clippy_utils::diagnostics::span_lint_and_then;
use rustc_ast::{Attribute, MetaItem};
use rustc_data_structures::fx::FxHashMap;
use rustc_lint::LateContext;
use rustc_lint::EarlyContext;
use rustc_span::{Span, sym};
use std::collections::hash_map::Entry;
fn emit_if_duplicated(
cx: &LateContext<'_>,
cx: &EarlyContext<'_>,
attr: &MetaItem,
attr_paths: &mut FxHashMap<String, Span>,
complete_path: String,
@ -26,7 +26,7 @@ fn emit_if_duplicated(
}
fn check_duplicated_attr(
cx: &LateContext<'_>,
cx: &EarlyContext<'_>,
attr: &MetaItem,
attr_paths: &mut FxHashMap<String, Span>,
parent: &mut Vec<String>,
@ -65,7 +65,7 @@ fn check_duplicated_attr(
}
}
pub fn check(cx: &LateContext<'_>, attrs: &[Attribute]) {
pub fn check(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
let mut attr_paths = FxHashMap::default();
for attr in attrs {

View File

@ -3,7 +3,7 @@
use rustc_ast::{AttrKind, AttrStyle, Attribute};
use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::Lrc;
use rustc_lint::{LateContext, LintContext};
use rustc_lint::{EarlyContext, LintContext};
use rustc_span::source_map::SourceMap;
use rustc_span::{SourceFile, Span, Symbol};
@ -32,7 +32,7 @@ fn from(value: &AttrKind) -> Self {
}
}
pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute]) {
pub(super) fn check(cx: &EarlyContext<'_>, item_span: Span, attrs: &[Attribute]) {
let mut inner_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
let mut outer_attr_kind: FxHashSet<SimpleAttrKind> = FxHashSet::default();
@ -64,7 +64,7 @@ pub(super) fn check(cx: &LateContext<'_>, item_span: Span, attrs: &[Attribute])
}
}
fn lint_mixed_attrs(cx: &LateContext<'_>, attrs: &[Attribute]) {
fn lint_mixed_attrs(cx: &EarlyContext<'_>, attrs: &[Attribute]) {
let mut attrs_iter = attrs.iter().filter(|attr| !attr.span.from_expansion());
let span = if let (Some(first), Some(last)) = (attrs_iter.next(), attrs_iter.last()) {
first.span.with_hi(last.span.hi())

View File

@ -14,8 +14,8 @@
use clippy_config::Conf;
use clippy_config::msrvs::{self, Msrv};
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind};
use rustc_hir::{ImplItem, Item, ItemKind, TraitItem};
use rustc_ast::{Attribute, MetaItemInner, MetaItemKind, self as ast};
use rustc_hir::{ImplItem, Item, TraitItem};
use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass};
use rustc_session::impl_lint_pass;
use rustc_span::sym;
@ -414,15 +414,7 @@ pub struct Attributes {
}
impl_lint_pass!(Attributes => [
ALLOW_ATTRIBUTES,
ALLOW_ATTRIBUTES_WITHOUT_REASON,
INLINE_ALWAYS,
DEPRECATED_SEMVER,
USELESS_ATTRIBUTE,
BLANKET_CLIPPY_RESTRICTION_LINTS,
SHOULD_PANIC_WITHOUT_EXPECT,
MIXED_ATTRIBUTES_STYLE,
DUPLICATED_ATTRIBUTES,
]);
impl Attributes {
@ -434,53 +426,11 @@ pub fn new(conf: &'static Conf) -> Self {
}
impl<'tcx> LateLintPass<'tcx> for Attributes {
fn check_crate(&mut self, cx: &LateContext<'tcx>) {
blanket_clippy_restriction_lints::check_command_line(cx);
duplicated_attributes::check(cx, cx.tcx.hir().krate_attrs());
}
fn check_attribute(&mut self, cx: &LateContext<'tcx>, attr: &'tcx Attribute) {
if let Some(items) = &attr.meta_item_list() {
if let Some(ident) = attr.ident() {
if is_lint_level(ident.name, attr.id) {
blanket_clippy_restriction_lints::check(cx, ident.name, items);
}
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
allow_attributes::check(cx, attr);
}
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
{
allow_attributes_without_reason::check(cx, ident.name, items, attr);
}
if items.is_empty() || !attr.has_name(sym::deprecated) {
return;
}
for item in items {
if let MetaItemInner::MetaItem(mi) = &item
&& let MetaItemKind::NameValue(lit) = &mi.kind
&& mi.has_name(sym::since)
{
deprecated_semver::check(cx, item.span(), lit);
}
}
}
}
if attr.has_name(sym::should_panic) {
should_panic_without_expect::check(cx, attr);
}
}
fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) {
let attrs = cx.tcx.hir().attrs(item.hir_id());
if is_relevant_item(cx, item) {
inline_always::check(cx, item.span, item.ident.name, attrs);
}
match item.kind {
ItemKind::ExternCrate(..) | ItemKind::Use(..) => useless_attribute::check(cx, item, attrs),
_ => {},
}
mixed_attributes_style::check(cx, item.span, attrs);
duplicated_attributes::check(cx, attrs);
}
fn check_impl_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx ImplItem<'_>) {
@ -526,3 +476,77 @@ fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
extract_msrv_attr!(EarlyContext);
}
pub struct PostExpansionEarlyAttributes {
msrv: Msrv,
}
impl PostExpansionEarlyAttributes {
pub fn new(conf: &'static Conf) -> Self {
Self {
msrv: conf.msrv.clone(),
}
}
}
impl_lint_pass!(PostExpansionEarlyAttributes => [
ALLOW_ATTRIBUTES,
ALLOW_ATTRIBUTES_WITHOUT_REASON,
DEPRECATED_SEMVER,
USELESS_ATTRIBUTE,
BLANKET_CLIPPY_RESTRICTION_LINTS,
SHOULD_PANIC_WITHOUT_EXPECT,
MIXED_ATTRIBUTES_STYLE,
DUPLICATED_ATTRIBUTES,
]);
impl EarlyLintPass for PostExpansionEarlyAttributes {
fn check_crate(&mut self, cx: &EarlyContext<'_>, krate: &ast::Crate) {
blanket_clippy_restriction_lints::check_command_line(cx);
duplicated_attributes::check(cx, &krate.attrs);
}
fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &Attribute) {
if let Some(items) = &attr.meta_item_list() {
if let Some(ident) = attr.ident() {
if matches!(ident.name, sym::allow) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION) {
allow_attributes::check(cx, attr);
}
if matches!(ident.name, sym::allow | sym::expect) && self.msrv.meets(msrvs::LINT_REASONS_STABILIZATION)
{
allow_attributes_without_reason::check(cx, ident.name, items, attr);
}
if is_lint_level(ident.name, attr.id) {
blanket_clippy_restriction_lints::check(cx, ident.name, items);
}
if items.is_empty() || !attr.has_name(sym::deprecated) {
return;
}
for item in items {
if let MetaItemInner::MetaItem(mi) = &item
&& let MetaItemKind::NameValue(lit) = &mi.kind
&& mi.has_name(sym::since)
{
deprecated_semver::check(cx, item.span(), lit);
}
}
}
}
if attr.has_name(sym::should_panic) {
should_panic_without_expect::check(cx, attr);
}
}
fn check_item(&mut self, cx: &EarlyContext<'_>, item: &'_ ast::Item) {
match item.kind {
ast::ItemKind::ExternCrate(..) | ast::ItemKind::Use(..) => useless_attribute::check(cx, item, &item.attrs),
_ => {},
}
mixed_attributes_style::check(cx, item.span, &item.attrs);
duplicated_attributes::check(cx, &item.attrs);
}
extract_msrv_attr!(EarlyContext);
}

View File

@ -4,12 +4,12 @@
use rustc_ast::tokenstream::TokenTree;
use rustc_ast::{AttrArgs, AttrArgsEq, AttrKind};
use rustc_errors::Applicability;
use rustc_lint::LateContext;
use rustc_lint::EarlyContext;
use rustc_span::sym;
pub(super) fn check(cx: &LateContext<'_>, attr: &Attribute) {
pub(super) fn check(cx: &EarlyContext<'_>, attr: &Attribute) {
if let AttrKind::Normal(normal_attr) = &attr.kind {
if let AttrArgs::Eq(_, AttrArgsEq::Hir(_)) = &normal_attr.item.args {
if let AttrArgs::Eq(_, AttrArgsEq::Ast(_)) = &normal_attr.item.args {
// `#[should_panic = ".."]` found, good
return;
}

View File

@ -1,15 +1,15 @@
use super::utils::{extract_clippy_lint, is_lint_level, is_word};
use super::{Attribute, USELESS_ATTRIBUTE};
use super::USELESS_ATTRIBUTE;
use clippy_utils::diagnostics::span_lint_and_then;
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
use rustc_ast::MetaItemInner;
use rustc_errors::Applicability;
use rustc_hir::{Item, ItemKind};
use rustc_lint::{LateContext, LintContext};
use rustc_ast::{Item, ItemKind, Attribute};
use rustc_lint::{EarlyContext, LintContext};
use rustc_middle::lint::in_external_macro;
use rustc_span::sym;
pub(super) fn check(cx: &LateContext<'_>, item: &Item<'_>, attrs: &[Attribute]) {
pub(super) fn check(cx: &EarlyContext<'_>, item: &Item, attrs: &[Attribute]) {
let skip_unused_imports = attrs.iter().any(|attr| attr.has_name(sym::macro_use));
for attr in attrs {

View File

@ -412,6 +412,8 @@
pub fn register_pre_expansion_lints(store: &mut rustc_lint::LintStore, conf: &'static Conf) {
// NOTE: Do not add any more pre-expansion passes. These should be removed eventually.
store.register_pre_expansion_pass(move || Box::new(attrs::EarlyAttributes::new(conf)));
store.register_early_pass(move || Box::new(attrs::PostExpansionEarlyAttributes::new(conf)));
}
#[derive(Default)]

View File

@ -21,7 +21,7 @@
ImplItem, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, MatchSource, MutTy, Node, Path, QPath, Safety,
TraitItem, TraitItemKind, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource,
};
use rustc_lint::{LateContext, LintContext};
use rustc_lint::{LateContext, LintContext, EarlyContext};
use rustc_middle::ty::TyCtxt;
use rustc_session::Session;
use rustc_span::symbol::{Ident, kw};
@ -429,11 +429,12 @@ fn span(&self) -> Span {
impl_with_search_pat!((_cx: LateContext<'tcx>, self: FieldDef<'_>) => field_def_search_pat(self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Variant<'_>) => variant_search_pat(self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ty<'_>) => ty_search_pat(self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Attribute) => attr_search_pat(self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Ident) => ident_search_pat(*self));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Lit) => lit_search_pat(&self.node));
impl_with_search_pat!((_cx: LateContext<'tcx>, self: Path<'_>) => path_search_pat(self));
impl_with_search_pat!((_cx: EarlyContext<'tcx>, self: Attribute) => attr_search_pat(self));
impl<'cx> WithSearchPat<'cx> for (&FnKind<'cx>, &Body<'cx>, HirId, Span) {
type Context = LateContext<'cx>;

View File

@ -19,13 +19,5 @@ error: #[allow] attribute found
LL | #[allow(unused)]
| ^^^^^ help: replace it with: `expect`
error: #[allow] attribute found
--> tests/ui/allow_attributes.rs:52:7
|
LL | #[allow(unused)]
| ^^^^^ help: replace it with: `expect`
|
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 4 previous errors
error: aborting due to 3 previous errors

View File

@ -43,14 +43,5 @@ LL | #[allow(unused)]
|
= help: try adding a reason at the end with `, reason = ".."`
error: `allow` attribute without specifying a reason
--> tests/ui/allow_attributes_without_reason.rs:46:5
|
LL | #[allow(unused)]
| ^^^^^^^^^^^^^^^^
|
= help: try adding a reason at the end with `, reason = ".."`
= note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
error: aborting due to 6 previous errors
error: aborting due to 5 previous errors

View File

@ -1,12 +1,3 @@
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
--> tests/ui/attrs.rs:5:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::inline-always` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
error: the since field must contain a semver-compliant version
--> tests/ui/attrs.rs:27:14
|
@ -22,5 +13,14 @@ error: the since field must contain a semver-compliant version
LL | #[deprecated(since = "1")]
| ^^^^^^^^^^^
error: you have declared `#[inline(always)]` on `test_attr_lint`. This is usually a bad idea
--> tests/ui/attrs.rs:5:1
|
LL | #[inline(always)]
| ^^^^^^^^^^^^^^^^^
|
= note: `-D clippy::inline-always` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::inline_always)]`
error: aborting due to 3 previous errors

View File

@ -1,3 +1,10 @@
error: `clippy::restriction` is not meant to be enabled as a group
|
= note: because of the command line `--warn clippy::restriction`
= help: enable the restriction lints you need individually
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
error: `clippy::restriction` is not meant to be enabled as a group
--> tests/ui/blanket_clippy_restriction_lints.rs:6:9
|
@ -5,8 +12,6 @@ LL | #![warn(clippy::restriction)]
| ^^^^^^^^^^^^^^^^^^^
|
= help: enable the restriction lints you need individually
= note: `-D clippy::blanket-clippy-restriction-lints` implied by `-D warnings`
= help: to override `-D warnings` add `#[allow(clippy::blanket_clippy_restriction_lints)]`
error: `clippy::restriction` is not meant to be enabled as a group
--> tests/ui/blanket_clippy_restriction_lints.rs:8:9
@ -24,10 +29,5 @@ LL | #![forbid(clippy::restriction)]
|
= help: enable the restriction lints you need individually
error: `clippy::restriction` is not meant to be enabled as a group
|
= note: because of the command line `--warn clippy::restriction`
= help: enable the restriction lints you need individually
error: aborting due to 4 previous errors