@@ -25,13 +25,16 @@ use Resolver;
25
25
use Namespace :: { TypeNS , ValueNS } ;
26
26
27
27
use rustc:: lint;
28
+ use rustc:: util:: nodemap:: NodeMap ;
28
29
use syntax:: ast:: { self , ViewPathGlob , ViewPathList , ViewPathSimple } ;
29
30
use syntax:: visit:: { self , Visitor } ;
30
- use syntax_pos:: { Span , DUMMY_SP } ;
31
+ use syntax_pos:: { Span , MultiSpan , DUMMY_SP } ;
31
32
32
33
33
34
struct UnusedImportCheckVisitor < ' a , ' b : ' a > {
34
35
resolver : & ' a mut Resolver < ' b > ,
36
+ /// All the (so far) unused imports, grouped path list
37
+ unused_imports : NodeMap < NodeMap < Span > > ,
35
38
}
36
39
37
40
// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
@@ -52,23 +55,21 @@ impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> {
52
55
impl < ' a , ' b > UnusedImportCheckVisitor < ' a , ' b > {
53
56
// We have information about whether `use` (import) directives are actually
54
57
// used now. If an import is not used at all, we signal a lint error.
55
- fn check_import ( & mut self , id : ast:: NodeId , span : Span ) {
58
+ fn check_import ( & mut self , item_id : ast :: NodeId , id : ast:: NodeId , span : Span ) {
56
59
if !self . used_imports . contains ( & ( id, TypeNS ) ) &&
57
60
!self . used_imports . contains ( & ( id, ValueNS ) ) {
58
61
if self . maybe_unused_trait_imports . contains ( & id) {
59
62
// Check later.
60
63
return ;
61
64
}
62
- let msg = if let Ok ( snippet) = self . session . codemap ( ) . span_to_snippet ( span) {
63
- format ! ( "unused import: `{}`" , snippet)
64
- } else {
65
- "unused import" . to_string ( )
66
- } ;
67
- self . session . add_lint ( lint:: builtin:: UNUSED_IMPORTS , id, span, msg) ;
65
+ self . unused_imports . entry ( item_id) . or_insert_with ( NodeMap ) . insert ( id, span) ;
68
66
} else {
69
67
// This trait import is definitely used, in a way other than
70
68
// method resolution.
71
69
self . maybe_unused_trait_imports . remove ( & id) ;
70
+ if let Some ( i) = self . unused_imports . get_mut ( & item_id) {
71
+ i. remove ( & id) ;
72
+ }
72
73
}
73
74
}
74
75
}
@@ -98,16 +99,16 @@ impl<'a, 'b> Visitor for UnusedImportCheckVisitor<'a, 'b> {
98
99
ast:: ItemKind :: Use ( ref p) => {
99
100
match p. node {
100
101
ViewPathSimple ( ..) => {
101
- self . check_import ( item. id , p. span )
102
+ self . check_import ( item. id , item . id , p. span )
102
103
}
103
104
104
105
ViewPathList ( _, ref list) => {
105
106
for i in list {
106
- self . check_import ( i. node . id , i. span ) ;
107
+ self . check_import ( item . id , i. node . id , i. span ) ;
107
108
}
108
109
}
109
110
ViewPathGlob ( _) => {
110
- self . check_import ( item. id , p. span )
111
+ self . check_import ( item. id , item . id , p. span ) ;
111
112
}
112
113
}
113
114
}
@@ -117,6 +118,35 @@ impl<'a, 'b> Visitor for UnusedImportCheckVisitor<'a, 'b> {
117
118
}
118
119
119
120
pub fn check_crate ( resolver : & mut Resolver , krate : & ast:: Crate ) {
120
- let mut visitor = UnusedImportCheckVisitor { resolver : resolver } ;
121
+ let mut visitor = UnusedImportCheckVisitor {
122
+ resolver : resolver,
123
+ unused_imports : NodeMap ( ) ,
124
+ } ;
121
125
visit:: walk_crate ( & mut visitor, krate) ;
126
+
127
+ for ( id, spans) in & visitor. unused_imports {
128
+ let len = spans. len ( ) ;
129
+ let mut spans = spans. values ( ) . map ( |s| * s) . collect :: < Vec < Span > > ( ) ;
130
+ spans. sort ( ) ;
131
+ let ms = MultiSpan :: from_spans ( spans. clone ( ) ) ;
132
+ let mut span_snippets = spans. iter ( )
133
+ . filter_map ( |s| {
134
+ match visitor. session . codemap ( ) . span_to_snippet ( * s) {
135
+ Ok ( s) => Some ( format ! ( "`{}`" , s) ) ,
136
+ _ => None ,
137
+ }
138
+ } ) . collect :: < Vec < String > > ( ) ;
139
+ span_snippets. sort ( ) ;
140
+ let msg = format ! ( "unused import{}{}" ,
141
+ if len > 1 { "s" } else { "" } ,
142
+ if span_snippets. len( ) > 0 {
143
+ format!( ": {}" , span_snippets. join( ", " ) )
144
+ } else {
145
+ String :: new( )
146
+ } ) ;
147
+ visitor. session . add_lint ( lint:: builtin:: UNUSED_IMPORTS ,
148
+ * id,
149
+ ms,
150
+ msg) ;
151
+ }
122
152
}
0 commit comments