Skip to content

Commit 2d32c14

Browse files
committed
Emit unused import lints in a multispan, closes #16132
1 parent 37c2bb8 commit 2d32c14

File tree

1 file changed

+24
-14
lines changed

1 file changed

+24
-14
lines changed

src/librustc_resolve/check_unused.rs

+24-14
Original file line numberDiff line numberDiff line change
@@ -18,21 +18,23 @@
1818
//
1919

2020
use std::ops::{Deref, DerefMut};
21+
use std::collections::HashMap;
2122

2223
use Resolver;
2324
use Namespace::{TypeNS, ValueNS};
2425

2526
use rustc::lint;
2627
use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused};
2728
use syntax::ast;
28-
use syntax::codemap::{Span, DUMMY_SP};
29+
use syntax::codemap::{Span, MultiSpan, DUMMY_SP};
2930

3031
use rustc_front::hir;
3132
use rustc_front::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
3233
use rustc_front::intravisit::Visitor;
3334

3435
struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> {
3536
resolver: &'a mut Resolver<'b, 'tcx>,
37+
unused_imports: HashMap<ast::NodeId, Vec<Span>>,
3638
}
3739

3840
// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
@@ -58,16 +60,13 @@ impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
5860
// only check imports and namespaces which are used. In particular, this
5961
// means that if an import could name either a public or private item, we
6062
// will check the correct thing, dependent on how the import is used.
61-
fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
63+
fn finalize_import(&mut self, item_id: ast::NodeId, id: ast::NodeId, span: Span) {
6264
debug!("finalizing import uses for {:?}",
6365
self.session.codemap().span_to_snippet(span));
6466

6567
if !self.used_imports.contains(&(id, TypeNS)) &&
6668
!self.used_imports.contains(&(id, ValueNS)) {
67-
self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
68-
id,
69-
span,
70-
"unused import".to_string());
69+
self.unused_imports.entry(item_id).or_insert_with(Vec::new).push(span);
7170
}
7271

7372
let mut def_map = self.def_map.borrow_mut();
@@ -135,22 +134,19 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
135134
hir::ItemUse(ref p) => {
136135
match p.node {
137136
ViewPathSimple(_, _) => {
138-
self.finalize_import(item.id, p.span)
137+
self.finalize_import(item.id, item.id, p.span)
139138
}
140139

141140
ViewPathList(_, ref list) => {
142141
for i in list {
143-
self.finalize_import(i.node.id(), i.span);
142+
self.finalize_import(item.id, i.node.id(), i.span);
144143
}
145144
}
146145
ViewPathGlob(_) => {
147146
if !self.used_imports.contains(&(item.id, TypeNS)) &&
148147
!self.used_imports.contains(&(item.id, ValueNS)) {
149-
self.session
150-
.add_lint(lint::builtin::UNUSED_IMPORTS,
151-
item.id,
152-
p.span,
153-
"unused import".to_string());
148+
self.unused_imports.entry(item.id).or_insert_with(Vec::new)
149+
.push(item.span);
154150
}
155151
}
156152
}
@@ -161,6 +157,20 @@ impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
161157
}
162158

163159
pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
164-
let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
160+
let mut visitor = UnusedImportCheckVisitor { resolver: resolver,
161+
unused_imports: HashMap::new() };
165162
krate.visit_all_items(&mut visitor);
163+
164+
for (id, spans) in &visitor.unused_imports {
165+
let ms = spans.iter().fold(MultiSpan::new(), |mut acc, &sp| { acc.push_merge(sp); acc });
166+
167+
visitor.session.add_lint(lint::builtin::UNUSED_IMPORTS,
168+
*id,
169+
ms,
170+
if spans.len() > 1 {
171+
"unused imports".to_string()
172+
} else {
173+
"unused import".to_string()
174+
});
175+
}
166176
}

0 commit comments

Comments
 (0)