| use super::{ALLOW_ATTRIBUTES_WITHOUT_REASON, Attribute}; |
| use clippy_utils::diagnostics::span_lint_and_then; |
| use clippy_utils::is_from_proc_macro; |
| use rustc_ast::{MetaItemInner, MetaItemKind}; |
| use rustc_lint::{EarlyContext, LintContext}; |
| use rustc_span::sym; |
| use rustc_span::symbol::Symbol; |
| |
| 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 |
| && item.path == sym::reason |
| { |
| return; |
| } |
| |
| // Check if the attribute is in an external macro and therefore out of the developer's control |
| if attr.span.in_external_macro(cx.sess().source_map()) || is_from_proc_macro(cx, attr) { |
| return; |
| } |
| |
| #[expect(clippy::collapsible_span_lint_calls, reason = "rust-clippy#7797")] |
| span_lint_and_then( |
| cx, |
| ALLOW_ATTRIBUTES_WITHOUT_REASON, |
| attr.span, |
| format!("`{name}` attribute without specifying a reason"), |
| |diag| { |
| diag.help("try adding a reason at the end with `, reason = \"..\"`"); |
| }, |
| ); |
| } |