]>
Commit | Line | Data |
---|---|---|
1a4d82fc JJ |
1 | // Copyright 2012-2014 The Rust Project Developers. See the COPYRIGHT |
2 | // file at the top-level directory of this distribution and at | |
3 | // http://rust-lang.org/COPYRIGHT. | |
4 | // | |
5 | // Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or | |
6 | // http://www.apache.org/licenses/LICENSE-2.0> or the MIT license | |
7 | // <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your | |
8 | // option. This file may not be copied, modified, or distributed | |
9 | // except according to those terms. | |
10 | ||
11 | ||
12 | // | |
13 | // Unused import checking | |
14 | // | |
15 | // Although this is mostly a lint pass, it lives in here because it depends on | |
16 | // resolve data structures and because it finalises the privacy information for | |
17 | // `use` directives. | |
18 | // | |
a7813a04 XL |
19 | // Unused trait imports can't be checked until the method resolution. We save |
20 | // candidates here, and do the acutal check in librustc_typeck/check_unused.rs. | |
1a4d82fc JJ |
21 | |
22 | use std::ops::{Deref, DerefMut}; | |
23 | ||
24 | use Resolver; | |
25 | use Namespace::{TypeNS, ValueNS}; | |
26 | ||
27 | use rustc::lint; | |
a7813a04 XL |
28 | use syntax::ast::{self, ViewPathGlob, ViewPathList, ViewPathSimple}; |
29 | use syntax::visit::{self, Visitor}; | |
3157f602 | 30 | use syntax_pos::{Span, DUMMY_SP}; |
e9174d1e | 31 | |
1a4d82fc | 32 | |
a7813a04 XL |
33 | struct UnusedImportCheckVisitor<'a, 'b: 'a> { |
34 | resolver: &'a mut Resolver<'b>, | |
1a4d82fc JJ |
35 | } |
36 | ||
37 | // Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver. | |
a7813a04 XL |
38 | impl<'a, 'b> Deref for UnusedImportCheckVisitor<'a, 'b> { |
39 | type Target = Resolver<'b>; | |
1a4d82fc | 40 | |
a7813a04 | 41 | fn deref<'c>(&'c self) -> &'c Resolver<'b> { |
1a4d82fc JJ |
42 | &*self.resolver |
43 | } | |
44 | } | |
45 | ||
a7813a04 XL |
46 | impl<'a, 'b> DerefMut for UnusedImportCheckVisitor<'a, 'b> { |
47 | fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b> { | |
1a4d82fc JJ |
48 | &mut *self.resolver |
49 | } | |
50 | } | |
51 | ||
a7813a04 | 52 | impl<'a, 'b> UnusedImportCheckVisitor<'a, 'b> { |
92a42be0 | 53 | // We have information about whether `use` (import) directives are actually |
54a0048b SL |
54 | // 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) { | |
1a4d82fc JJ |
56 | if !self.used_imports.contains(&(id, TypeNS)) && |
57 | !self.used_imports.contains(&(id, ValueNS)) { | |
a7813a04 XL |
58 | if self.maybe_unused_trait_imports.contains(&id) { |
59 | // Check later. | |
60 | return; | |
61 | } | |
c30ab7b3 SL |
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); | |
a7813a04 XL |
68 | } else { |
69 | // This trait import is definitely used, in a way other than | |
70 | // method resolution. | |
71 | self.maybe_unused_trait_imports.remove(&id); | |
1a4d82fc | 72 | } |
1a4d82fc JJ |
73 | } |
74 | } | |
75 | ||
3157f602 | 76 | impl<'a, 'b> Visitor for UnusedImportCheckVisitor<'a, 'b> { |
a7813a04 XL |
77 | fn visit_item(&mut self, item: &ast::Item) { |
78 | visit::walk_item(self, item); | |
1a4d82fc JJ |
79 | // Ignore is_public import statements because there's no way to be sure |
80 | // whether they're used or not. Also ignore imports with a dummy span | |
81 | // because this means that they were generated in some fashion by the | |
82 | // compiler and we don't need to consider them. | |
a7813a04 | 83 | if item.vis == ast::Visibility::Public || item.span.source_equal(&DUMMY_SP) { |
1a4d82fc JJ |
84 | return; |
85 | } | |
86 | ||
85aaf69f | 87 | match item.node { |
a7813a04 | 88 | ast::ItemKind::ExternCrate(_) => { |
92a42be0 | 89 | if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) { |
1a4d82fc JJ |
90 | if !self.used_crates.contains(&crate_num) { |
91 | self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES, | |
85aaf69f SL |
92 | item.id, |
93 | item.span, | |
1a4d82fc JJ |
94 | "unused extern crate".to_string()); |
95 | } | |
96 | } | |
92a42be0 | 97 | } |
a7813a04 | 98 | ast::ItemKind::Use(ref p) => { |
1a4d82fc | 99 | match p.node { |
9e0c209e | 100 | ViewPathSimple(..) => { |
54a0048b | 101 | self.check_import(item.id, p.span) |
1a4d82fc JJ |
102 | } |
103 | ||
85aaf69f SL |
104 | ViewPathList(_, ref list) => { |
105 | for i in list { | |
9e0c209e | 106 | self.check_import(i.node.id, i.span); |
1a4d82fc JJ |
107 | } |
108 | } | |
85aaf69f | 109 | ViewPathGlob(_) => { |
54a0048b | 110 | self.check_import(item.id, p.span) |
1a4d82fc JJ |
111 | } |
112 | } | |
113 | } | |
85aaf69f | 114 | _ => {} |
1a4d82fc | 115 | } |
1a4d82fc JJ |
116 | } |
117 | } | |
118 | ||
a7813a04 | 119 | pub fn check_crate(resolver: &mut Resolver, krate: &ast::Crate) { |
1a4d82fc | 120 | let mut visitor = UnusedImportCheckVisitor { resolver: resolver }; |
a7813a04 | 121 | visit::walk_crate(&mut visitor, krate); |
1a4d82fc | 122 | } |