mirror of
https://github.com/rust-lang/rust-clippy
synced 2024-11-22 20:53:21 +00:00
Fix is_from_proc_macro attr
This commit is contained in:
parent
cefa31a524
commit
59ecf4d073
5 changed files with 83 additions and 15 deletions
|
@ -63,8 +63,8 @@ fn span_matches_pat(sess: &Session, span: Span, start_pat: Pat, end_pat: Pat) ->
|
||||||
Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
|
Pat::Num => start_str.as_bytes().first().map_or(false, u8::is_ascii_digit),
|
||||||
} && match end_pat {
|
} && match end_pat {
|
||||||
Pat::Str(text) => end_str.ends_with(text),
|
Pat::Str(text) => end_str.ends_with(text),
|
||||||
Pat::MultiStr(texts) => texts.iter().any(|s| start_str.ends_with(s)),
|
Pat::MultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
|
||||||
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| start_str.starts_with(s)),
|
Pat::OwnedMultiStr(texts) => texts.iter().any(|s| end_str.ends_with(s)),
|
||||||
Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
|
Pat::Sym(sym) => end_str.ends_with(sym.as_str()),
|
||||||
Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit),
|
Pat::Num => end_str.as_bytes().last().map_or(false, u8::is_ascii_hexdigit),
|
||||||
})
|
})
|
||||||
|
@ -333,26 +333,32 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) {
|
||||||
match attr.kind {
|
match attr.kind {
|
||||||
AttrKind::Normal(..) => {
|
AttrKind::Normal(..) => {
|
||||||
if let Some(ident) = attr.ident() {
|
if let Some(ident) = attr.ident() {
|
||||||
// TODO: I feel like it's likely we can use `Cow` instead but this will require quite a bit of
|
|
||||||
// refactoring
|
|
||||||
// NOTE: This will likely have false positives, like `allow = 1`
|
// NOTE: This will likely have false positives, like `allow = 1`
|
||||||
(
|
let ident_string = ident.to_string();
|
||||||
Pat::OwnedMultiStr(vec![ident.to_string(), "#".to_owned()]),
|
if attr.style == AttrStyle::Outer {
|
||||||
Pat::Str(""),
|
(
|
||||||
)
|
Pat::OwnedMultiStr(vec!["#[".to_owned() + &ident_string, ident_string]),
|
||||||
|
Pat::Str(""),
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
(
|
||||||
|
Pat::OwnedMultiStr(vec!["#![".to_owned() + &ident_string, ident_string]),
|
||||||
|
Pat::Str(""),
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
(Pat::Str("#"), Pat::Str("]"))
|
(Pat::Str("#"), Pat::Str("]"))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AttrKind::DocComment(_kind @ CommentKind::Line, ..) => {
|
AttrKind::DocComment(_kind @ CommentKind::Line, ..) => {
|
||||||
if matches!(attr.style, AttrStyle::Outer) {
|
if attr.style == AttrStyle::Outer {
|
||||||
(Pat::Str("///"), Pat::Str(""))
|
(Pat::Str("///"), Pat::Str(""))
|
||||||
} else {
|
} else {
|
||||||
(Pat::Str("//!"), Pat::Str(""))
|
(Pat::Str("//!"), Pat::Str(""))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
AttrKind::DocComment(_kind @ CommentKind::Block, ..) => {
|
AttrKind::DocComment(_kind @ CommentKind::Block, ..) => {
|
||||||
if matches!(attr.style, AttrStyle::Outer) {
|
if attr.style == AttrStyle::Outer {
|
||||||
(Pat::Str("/**"), Pat::Str("*/"))
|
(Pat::Str("/**"), Pat::Str("*/"))
|
||||||
} else {
|
} else {
|
||||||
(Pat::Str("/*!"), Pat::Str("*/"))
|
(Pat::Str("/*!"), Pat::Str("*/"))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//@aux-build:proc_macros.rs
|
//@aux-build:proc_macros.rs
|
||||||
|
//@aux-build:proc_macro_derive.rs
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![warn(clippy::allow_attributes)]
|
#![warn(clippy::allow_attributes)]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
@ -65,3 +66,9 @@ fn deny_allow_attributes() -> Option<u8> {
|
||||||
allow?;
|
allow?;
|
||||||
Some(42)
|
Some(42)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edge case where the generated tokens spans match on #[repr(transparent)] which tricks the proc
|
||||||
|
// macro check
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(proc_macro_derive::AllowLintSameSpan)] // This macro generates tokens with the same span as the whole struct and repr
|
||||||
|
struct IgnoreDerived;
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
//@aux-build:proc_macros.rs
|
//@aux-build:proc_macros.rs
|
||||||
|
//@aux-build:proc_macro_derive.rs
|
||||||
#![allow(unused)]
|
#![allow(unused)]
|
||||||
#![warn(clippy::allow_attributes)]
|
#![warn(clippy::allow_attributes)]
|
||||||
#![no_main]
|
#![no_main]
|
||||||
|
@ -65,3 +66,9 @@ fn deny_allow_attributes() -> Option<u8> {
|
||||||
allow?;
|
allow?;
|
||||||
Some(42)
|
Some(42)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Edge case where the generated tokens spans match on #[repr(transparent)] which tricks the proc
|
||||||
|
// macro check
|
||||||
|
#[repr(transparent)]
|
||||||
|
#[derive(proc_macro_derive::AllowLintSameSpan)] // This macro generates tokens with the same span as the whole struct and repr
|
||||||
|
struct IgnoreDerived;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
error: #[allow] attribute found
|
error: #[allow] attribute found
|
||||||
--> tests/ui/allow_attributes.rs:12:3
|
--> tests/ui/allow_attributes.rs:13:3
|
||||||
|
|
|
|
||||||
LL | #[allow(dead_code)]
|
LL | #[allow(dead_code)]
|
||||||
| ^^^^^ help: replace it with: `expect`
|
| ^^^^^ help: replace it with: `expect`
|
||||||
|
@ -8,19 +8,19 @@ LL | #[allow(dead_code)]
|
||||||
= help: to override `-D warnings` add `#[allow(clippy::allow_attributes)]`
|
= help: to override `-D warnings` add `#[allow(clippy::allow_attributes)]`
|
||||||
|
|
||||||
error: #[allow] attribute found
|
error: #[allow] attribute found
|
||||||
--> tests/ui/allow_attributes.rs:21:30
|
--> tests/ui/allow_attributes.rs:22:30
|
||||||
|
|
|
|
||||||
LL | #[cfg_attr(panic = "unwind", allow(dead_code))]
|
LL | #[cfg_attr(panic = "unwind", allow(dead_code))]
|
||||||
| ^^^^^ help: replace it with: `expect`
|
| ^^^^^ help: replace it with: `expect`
|
||||||
|
|
||||||
error: #[allow] attribute found
|
error: #[allow] attribute found
|
||||||
--> tests/ui/allow_attributes.rs:52:7
|
--> tests/ui/allow_attributes.rs:53:7
|
||||||
|
|
|
|
||||||
LL | #[allow(unused)]
|
LL | #[allow(unused)]
|
||||||
| ^^^^^ help: replace it with: `expect`
|
| ^^^^^ help: replace it with: `expect`
|
||||||
|
|
||||||
error: #[allow] attribute found
|
error: #[allow] attribute found
|
||||||
--> tests/ui/allow_attributes.rs:52:7
|
--> tests/ui/allow_attributes.rs:53:7
|
||||||
|
|
|
|
||||||
LL | #[allow(unused)]
|
LL | #[allow(unused)]
|
||||||
| ^^^^^ help: replace it with: `expect`
|
| ^^^^^ help: replace it with: `expect`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#![feature(repr128, proc_macro_quote)]
|
#![feature(repr128, proc_macro_quote, proc_macro_span)]
|
||||||
#![allow(incomplete_features)]
|
#![allow(incomplete_features)]
|
||||||
#![allow(clippy::field_reassign_with_default)]
|
#![allow(clippy::field_reassign_with_default)]
|
||||||
#![allow(clippy::eq_op)]
|
#![allow(clippy::eq_op)]
|
||||||
|
@ -182,3 +182,51 @@ pub fn non_canonical_clone_derive(_: TokenStream) -> TokenStream {
|
||||||
impl Copy for NonCanonicalClone {}
|
impl Copy for NonCanonicalClone {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Derive macro that generates the following but where all generated spans are set to the entire
|
||||||
|
// input span.
|
||||||
|
//
|
||||||
|
// ```
|
||||||
|
// #[allow(clippy::missing_const_for_fn)]
|
||||||
|
// fn check() {}
|
||||||
|
// ```
|
||||||
|
#[proc_macro_derive(AllowLintSameSpan)]
|
||||||
|
pub fn allow_lint_same_span_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let mut iter = input.into_iter();
|
||||||
|
let first = iter.next().unwrap();
|
||||||
|
let last = iter.last().unwrap();
|
||||||
|
let span = first.span().join(last.span()).unwrap();
|
||||||
|
let span_help = |mut t: TokenTree| -> TokenTree {
|
||||||
|
t.set_span(span);
|
||||||
|
t
|
||||||
|
};
|
||||||
|
// Generate the TokenStream but setting all the spans to the entire input span
|
||||||
|
<TokenStream as FromIterator<TokenTree>>::from_iter([
|
||||||
|
span_help(Punct::new('#', Spacing::Alone).into()),
|
||||||
|
span_help(
|
||||||
|
Group::new(
|
||||||
|
Delimiter::Bracket,
|
||||||
|
<TokenStream as FromIterator<TokenTree>>::from_iter([
|
||||||
|
Ident::new("allow", span).into(),
|
||||||
|
span_help(
|
||||||
|
Group::new(
|
||||||
|
Delimiter::Parenthesis,
|
||||||
|
<TokenStream as FromIterator<TokenTree>>::from_iter([
|
||||||
|
Ident::new("clippy", span).into(),
|
||||||
|
span_help(Punct::new(':', Spacing::Joint).into()),
|
||||||
|
span_help(Punct::new(':', Spacing::Alone).into()),
|
||||||
|
Ident::new("missing_const_for_fn", span).into(),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
)
|
||||||
|
.into(),
|
||||||
|
),
|
||||||
|
Ident::new("fn", span).into(),
|
||||||
|
Ident::new("check", span).into(),
|
||||||
|
span_help(Group::new(Delimiter::Parenthesis, TokenStream::new()).into()),
|
||||||
|
span_help(Group::new(Delimiter::Brace, TokenStream::new()).into()),
|
||||||
|
])
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in a new issue