90 lines
4 KiB
Rust
90 lines
4 KiB
Rust
use super::USELESS_ATTRIBUTE;
|
|
use super::utils::{is_lint_level, is_word, namespace_and_lint};
|
|
use clippy_utils::diagnostics::span_lint_and_then;
|
|
use clippy_utils::source::{SpanRangeExt, first_line_of_span};
|
|
use rustc_ast::{Attribute, Item, ItemKind};
|
|
use rustc_errors::Applicability;
|
|
use rustc_lint::{EarlyContext, LintContext};
|
|
use rustc_middle::lint::in_external_macro;
|
|
use rustc_span::sym;
|
|
|
|
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 {
|
|
if in_external_macro(cx.sess(), attr.span) {
|
|
return;
|
|
}
|
|
if let Some(lint_list) = &attr.meta_item_list() {
|
|
if attr.ident().is_some_and(|ident| is_lint_level(ident.name, attr.id)) {
|
|
for lint in lint_list {
|
|
match item.kind {
|
|
ItemKind::Use(..) => {
|
|
let (namespace @ (Some(sym::clippy) | None), Some(name)) = namespace_and_lint(lint) else {
|
|
return;
|
|
};
|
|
|
|
if namespace.is_none()
|
|
&& matches!(
|
|
name.as_str(),
|
|
"ambiguous_glob_reexports"
|
|
| "dead_code"
|
|
| "deprecated"
|
|
| "hidden_glob_reexports"
|
|
| "unreachable_pub"
|
|
| "unused"
|
|
| "unused_braces"
|
|
| "unused_import_braces"
|
|
| "unused_imports"
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
|
|
if namespace == Some(sym::clippy)
|
|
&& matches!(
|
|
name.as_str(),
|
|
"wildcard_imports"
|
|
| "enum_glob_use"
|
|
| "redundant_pub_crate"
|
|
| "macro_use_imports"
|
|
| "unsafe_removed_from_name"
|
|
| "module_name_repetitions"
|
|
| "single_component_path_imports"
|
|
| "disallowed_types"
|
|
| "unused_trait_names"
|
|
)
|
|
{
|
|
return;
|
|
}
|
|
},
|
|
ItemKind::ExternCrate(..) => {
|
|
if is_word(lint, sym::unused_imports) && skip_unused_imports {
|
|
return;
|
|
}
|
|
if is_word(lint, sym!(unused_extern_crates)) {
|
|
return;
|
|
}
|
|
},
|
|
_ => {},
|
|
}
|
|
}
|
|
let line_span = first_line_of_span(cx, attr.span);
|
|
|
|
if let Some(src) = line_span.get_source_text(cx) {
|
|
if src.contains("#[") {
|
|
#[expect(clippy::collapsible_span_lint_calls)]
|
|
span_lint_and_then(cx, USELESS_ATTRIBUTE, line_span, "useless lint attribute", |diag| {
|
|
diag.span_suggestion(
|
|
line_span,
|
|
"if you just forgot a `!`, use",
|
|
src.replacen("#[", "#![", 1),
|
|
Applicability::MaybeIncorrect,
|
|
);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|