1- use crate :: utils:: { snippet, span_lint_and_sugg} ;
1+ use crate :: utils:: { snippet, span_lint_and_sugg, in_macro } ;
22use if_chain:: if_chain;
33use rustc_ast:: ast;
4+ use rustc_data_structures:: fx:: FxHashSet ;
45use rustc_errors:: Applicability ;
56use 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
910declare_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}
0 commit comments