warn on macro_use attr
cargo dev update lints use if_chain clean up alot, span_lint_and_sugg find imported macros for sugg
This commit is contained in:
parent
ff0993c5e9
commit
a4b8bb88f2
@ -1,10 +1,11 @@
|
||||
use crate::utils::{snippet, span_lint_and_sugg};
|
||||
use crate::utils::{snippet, span_lint_and_sugg, in_macro};
|
||||
use if_chain::if_chain;
|
||||
use rustc_ast::ast;
|
||||
use rustc_data_structures::fx::FxHashSet;
|
||||
use rustc_errors::Applicability;
|
||||
use rustc_lint::{EarlyContext, EarlyLintPass};
|
||||
use rustc_session::{declare_lint_pass, declare_tool_lint};
|
||||
use rustc_span::edition::Edition;
|
||||
use rustc_session::{impl_lint_pass, declare_tool_lint};
|
||||
use rustc_span::{edition::Edition, Span};
|
||||
|
||||
declare_clippy_lint! {
|
||||
/// **What it does:** Checks for `#[macro_use] use...`.
|
||||
@ -12,21 +13,27 @@ declare_clippy_lint! {
|
||||
/// **Why is this bad?** Since the Rust 2018 edition you can import
|
||||
/// macro's directly, this is considered idiomatic.
|
||||
///
|
||||
/// **Known problems:** This lint does not generate an auto-applicable suggestion.
|
||||
/// **Known problems:** None.
|
||||
///
|
||||
/// **Example:**
|
||||
/// ```rust
|
||||
/// #[macro_use]
|
||||
/// use lazy_static;
|
||||
/// ```
|
||||
pub MACRO_USE_IMPORTS,
|
||||
pub MACRO_USE_IMPORT,
|
||||
pedantic,
|
||||
"#[macro_use] is no longer needed"
|
||||
}
|
||||
|
||||
declare_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]);
|
||||
#[derive(Default)]
|
||||
pub struct MacroUseImport {
|
||||
collected: FxHashSet<Span>,
|
||||
}
|
||||
|
||||
impl_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]);
|
||||
|
||||
impl EarlyLintPass for MacroUseImport {
|
||||
|
||||
impl EarlyLintPass for MacroUseImports {
|
||||
fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) {
|
||||
if_chain! {
|
||||
if ecx.sess.opts.edition == Edition::Edition2018;
|
||||
@ -36,18 +43,59 @@ impl EarlyLintPass for MacroUseImports {
|
||||
.iter()
|
||||
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
|
||||
then {
|
||||
let import_path = snippet(ecx, use_tree.span, "_");
|
||||
let mac_names = find_used_macros(ecx, &import_path);
|
||||
let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition";
|
||||
let help = format!("use {}::<macro name>", snippet(ecx, use_tree.span, "_"));
|
||||
let help = format!("use {}::<macro name>", import_path);
|
||||
span_lint_and_sugg(
|
||||
ecx,
|
||||
MACRO_USE_IMPORTS,
|
||||
MACRO_USE_IMPORT,
|
||||
mac_attr.span,
|
||||
msg,
|
||||
"remove the attribute and import the macro directly, try",
|
||||
// "remove the attribute and import the macro directly, try",
|
||||
"",
|
||||
help,
|
||||
Applicability::HasPlaceholders,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn check_expr(&mut self, ecx: &EarlyContext<'_>, expr: &ast::Expr) {
|
||||
if in_macro(expr.span) {
|
||||
let name = snippet(ecx, ecx.sess.source_map().span_until_char(expr.span.source_callsite(), '!'), "_");
|
||||
if let Some(callee) = expr.span.source_callee() {
|
||||
if self.collected.insert(callee.def_site) {
|
||||
println!("EXPR {:#?}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
fn check_stmt(&mut self, ecx: &EarlyContext<'_>, stmt: &ast::Stmt) {
|
||||
if in_macro(stmt.span) {
|
||||
let name = snippet(ecx, ecx.sess.source_map().span_until_char(stmt.span.source_callsite(), '!'), "_");
|
||||
if let Some(callee) = stmt.span.source_callee() {
|
||||
println!("EXPR {:#?}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
fn check_pat(&mut self, ecx: &EarlyContext<'_>, pat: &ast::Pat) {
|
||||
if in_macro(pat.span) {
|
||||
let name = snippet(ecx, ecx.sess.source_map().span_until_char(pat.span.source_callsite(), '!'), "_");
|
||||
if let Some(callee) = pat.span.source_callee() {
|
||||
println!("EXPR {:#?}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn find_used_macros(ecx: &EarlyContext<'_>, path: &str) {
|
||||
for it in ecx.krate.module.items.iter() {
|
||||
if in_macro(it.span) {
|
||||
// println!("{:#?}", it)
|
||||
}
|
||||
}
|
||||
for x in ecx.sess.imported_macro_spans.borrow().iter() {
|
||||
// println!("{:?}", x);
|
||||
}
|
||||
}
|
||||
|
BIN
macro_use_import
Executable file
BIN
macro_use_import
Executable file
Binary file not shown.
12
tests/ui/macro_use_import.rs
Normal file
12
tests/ui/macro_use_import.rs
Normal file
@ -0,0 +1,12 @@
|
||||
// compile-flags: --edition 2018
|
||||
#![warn(clippy::macro_use_import)]
|
||||
|
||||
use std::collections::HashMap;
|
||||
#[macro_use]
|
||||
use std::prelude;
|
||||
|
||||
fn main() {
|
||||
let _ = HashMap::<u8, u8>::new();
|
||||
serde_if_integer128!("");
|
||||
println!();
|
||||
}
|
10
tests/ui/macro_use_import.stderr
Normal file
10
tests/ui/macro_use_import.stderr
Normal file
@ -0,0 +1,10 @@
|
||||
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
|
||||
--> $DIR/macro_use_import.rs:5:1
|
||||
|
|
||||
LL | #[macro_use]
|
||||
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>`
|
||||
|
|
||||
= note: `-D clippy::macro-use-import` implied by `-D warnings`
|
||||
|
||||
error: aborting due to previous error
|
||||
|
0
tests/ui/macro_use_import.stdout
Normal file
0
tests/ui/macro_use_import.stdout
Normal file
Loading…
x
Reference in New Issue
Block a user