Skip to content

Commit a4b8bb8

Browse files
committed
warn on macro_use attr
cargo dev update lints use if_chain clean up alot, span_lint_and_sugg find imported macros for sugg
1 parent ff0993c commit a4b8bb8

File tree

5 files changed

+80
-10
lines changed

5 files changed

+80
-10
lines changed

clippy_lints/src/macro_use.rs

Lines changed: 58 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,39 @@
1-
use crate::utils::{snippet, span_lint_and_sugg};
1+
use crate::utils::{snippet, span_lint_and_sugg, in_macro};
22
use if_chain::if_chain;
33
use rustc_ast::ast;
4+
use rustc_data_structures::fx::FxHashSet;
45
use rustc_errors::Applicability;
56
use rustc_lint::{EarlyContext, EarlyLintPass};
6-
use rustc_session::{declare_lint_pass, declare_tool_lint};
7-
use rustc_span::edition::Edition;
7+
use rustc_session::{impl_lint_pass, declare_tool_lint};
8+
use rustc_span::{edition::Edition, Span};
89

910
declare_clippy_lint! {
1011
/// **What it does:** Checks for `#[macro_use] use...`.
1112
///
1213
/// **Why is this bad?** Since the Rust 2018 edition you can import
1314
/// macro's directly, this is considered idiomatic.
1415
///
15-
/// **Known problems:** This lint does not generate an auto-applicable suggestion.
16+
/// **Known problems:** None.
1617
///
1718
/// **Example:**
1819
/// ```rust
1920
/// #[macro_use]
2021
/// use lazy_static;
2122
/// ```
22-
pub MACRO_USE_IMPORTS,
23+
pub MACRO_USE_IMPORT,
2324
pedantic,
2425
"#[macro_use] is no longer needed"
2526
}
2627

27-
declare_lint_pass!(MacroUseImports => [MACRO_USE_IMPORTS]);
28+
#[derive(Default)]
29+
pub struct MacroUseImport {
30+
collected: FxHashSet<Span>,
31+
}
32+
33+
impl_lint_pass!(MacroUseImport => [MACRO_USE_IMPORT]);
34+
35+
impl EarlyLintPass for MacroUseImport {
2836

29-
impl EarlyLintPass for MacroUseImports {
3037
fn check_item(&mut self, ecx: &EarlyContext<'_>, item: &ast::Item) {
3138
if_chain! {
3239
if ecx.sess.opts.edition == Edition::Edition2018;
@@ -36,18 +43,59 @@ impl EarlyLintPass for MacroUseImports {
3643
.iter()
3744
.find(|attr| attr.ident().map(|s| s.to_string()) == Some("macro_use".to_string()));
3845
then {
46+
let import_path = snippet(ecx, use_tree.span, "_");
47+
let mac_names = find_used_macros(ecx, &import_path);
3948
let msg = "`macro_use` attributes are no longer needed in the Rust 2018 edition";
40-
let help = format!("use {}::<macro name>", snippet(ecx, use_tree.span, "_"));
49+
let help = format!("use {}::<macro name>", import_path);
4150
span_lint_and_sugg(
4251
ecx,
43-
MACRO_USE_IMPORTS,
52+
MACRO_USE_IMPORT,
4453
mac_attr.span,
4554
msg,
46-
"remove the attribute and import the macro directly, try",
55+
// "remove the attribute and import the macro directly, try",
56+
"",
4757
help,
4858
Applicability::HasPlaceholders,
4959
);
5060
}
5161
}
5262
}
63+
64+
fn check_expr(&mut self, ecx: &EarlyContext<'_>, expr: &ast::Expr) {
65+
if in_macro(expr.span) {
66+
let name = snippet(ecx, ecx.sess.source_map().span_until_char(expr.span.source_callsite(), '!'), "_");
67+
if let Some(callee) = expr.span.source_callee() {
68+
if self.collected.insert(callee.def_site) {
69+
println!("EXPR {:#?}", name);
70+
}
71+
}
72+
}
73+
}
74+
fn check_stmt(&mut self, ecx: &EarlyContext<'_>, stmt: &ast::Stmt) {
75+
if in_macro(stmt.span) {
76+
let name = snippet(ecx, ecx.sess.source_map().span_until_char(stmt.span.source_callsite(), '!'), "_");
77+
if let Some(callee) = stmt.span.source_callee() {
78+
println!("EXPR {:#?}", name);
79+
}
80+
}
81+
}
82+
fn check_pat(&mut self, ecx: &EarlyContext<'_>, pat: &ast::Pat) {
83+
if in_macro(pat.span) {
84+
let name = snippet(ecx, ecx.sess.source_map().span_until_char(pat.span.source_callsite(), '!'), "_");
85+
if let Some(callee) = pat.span.source_callee() {
86+
println!("EXPR {:#?}", name);
87+
}
88+
}
89+
}
90+
}
91+
92+
fn find_used_macros(ecx: &EarlyContext<'_>, path: &str) {
93+
for it in ecx.krate.module.items.iter() {
94+
if in_macro(it.span) {
95+
// println!("{:#?}", it)
96+
}
97+
}
98+
for x in ecx.sess.imported_macro_spans.borrow().iter() {
99+
// println!("{:?}", x);
100+
}
53101
}

macro_use_import

2.69 MB
Binary file not shown.

tests/ui/macro_use_import.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
// compile-flags: --edition 2018
2+
#![warn(clippy::macro_use_import)]
3+
4+
use std::collections::HashMap;
5+
#[macro_use]
6+
use std::prelude;
7+
8+
fn main() {
9+
let _ = HashMap::<u8, u8>::new();
10+
serde_if_integer128!("");
11+
println!();
12+
}

tests/ui/macro_use_import.stderr

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
error: `macro_use` attributes are no longer needed in the Rust 2018 edition
2+
--> $DIR/macro_use_import.rs:5:1
3+
|
4+
LL | #[macro_use]
5+
| ^^^^^^^^^^^^ help: remove the attribute and import the macro directly, try: `use std::prelude::<macro name>`
6+
|
7+
= note: `-D clippy::macro-use-import` implied by `-D warnings`
8+
9+
error: aborting due to previous error
10+

tests/ui/macro_use_import.stdout

Whitespace-only changes.

0 commit comments

Comments
 (0)