New lint : unused_extern_crate. #10385

This commit is contained in:
Victor Berger 2014-09-11 19:14:43 +02:00
parent 805cf81b77
commit 9f8ec427e5
4 changed files with 100 additions and 3 deletions

View File

@ -1525,6 +1525,9 @@ impl LintPass for Stability {
declare_lint!(pub UNUSED_IMPORTS, Warn,
"imports that are never used")
declare_lint!(pub UNUSED_EXTERN_CRATE, Allow,
"extern crates that are never used")
declare_lint!(pub UNNECESSARY_QUALIFICATION, Allow,
"detects unnecessarily qualified names")
@ -1569,6 +1572,7 @@ impl LintPass for HardwiredLints {
fn get_lints(&self) -> LintArray {
lint_array!(
UNUSED_IMPORTS,
UNUSED_EXTERN_CRATE,
UNNECESSARY_QUALIFICATION,
UNRECOGNIZED_LINT,
UNUSED_VARIABLE,

View File

@ -201,7 +201,7 @@ impl LintStore {
add_lint_group!(sess, "unused",
UNUSED_IMPORTS, UNUSED_VARIABLE, DEAD_ASSIGNMENT, DEAD_CODE,
UNUSED_MUT, UNREACHABLE_CODE)
UNUSED_MUT, UNREACHABLE_CODE, UNUSED_EXTERN_CRATE)
// We have one lint pass defined in this module.
self.register_pass(sess, false, box GatherNodeLevels as LintPassObject);

View File

@ -21,7 +21,7 @@ use middle::subst::{ParamSpace, FnSpace, TypeSpace};
use middle::ty::{ExplicitSelfCategory, StaticExplicitSelfCategory};
use util::nodemap::{NodeMap, DefIdSet, FnvHashMap};
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate};
use syntax::ast::{Arm, BindByRef, BindByValue, BindingMode, Block, Crate, CrateNum};
use syntax::ast::{DeclItem, DefId, Expr, ExprAgain, ExprBreak, ExprField};
use syntax::ast::{ExprFnBlock, ExprForLoop, ExprLoop, ExprWhile, ExprMethodCall};
use syntax::ast::{ExprPath, ExprProc, ExprStruct, ExprUnboxedFn, FnDecl};
@ -899,6 +899,7 @@ struct Resolver<'a> {
emit_errors: bool,
used_imports: HashSet<(NodeId, Namespace)>,
used_crates: HashSet<CrateNum>,
}
struct BuildReducedGraphVisitor<'a, 'b:'a> {
@ -987,6 +988,7 @@ impl<'a> Resolver<'a> {
export_map2: RefCell::new(NodeMap::new()),
trait_map: NodeMap::new(),
used_imports: HashSet::new(),
used_crates: HashSet::new(),
external_exports: DefIdSet::new(),
last_private: NodeMap::new(),
@ -2453,7 +2455,14 @@ impl<'a> Resolver<'a> {
debug!("(resolving single import) found \
import in ns {:?}", namespace);
let id = import_resolution.id(namespace);
// track used imports and extern crates as well
this.used_imports.insert((id, namespace));
match target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => {
this.used_crates.insert(kid);
},
_ => {}
}
return BoundResult(target_module, bindings);
}
}
@ -2496,6 +2505,11 @@ impl<'a> Resolver<'a> {
Some(module) => {
debug!("(resolving single import) found external \
module");
// track the module as used.
match module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
let name_bindings =
Rc::new(Resolver::create_name_bindings_from_module(
module));
@ -3030,6 +3044,14 @@ impl<'a> Resolver<'a> {
(_, _) => {
search_module = module_def.clone();
// track extern crates for unused_extern_crate lint
match module_def.def_id.get() {
Some(did) => {
self.used_crates.insert(did.krate);
}
_ => {}
}
// Keep track of the closest
// private module used when
// resolving this import chain.
@ -3213,7 +3235,12 @@ impl<'a> Resolver<'a> {
Some(target) => {
debug!("(resolving item in lexical scope) using \
import resolution");
// track used imports and extern crates as well
self.used_imports.insert((import_resolution.id(namespace), namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Success((target, false));
}
}
@ -3492,7 +3519,12 @@ impl<'a> Resolver<'a> {
Some(target) => {
debug!("(resolving name in module) resolved to \
import");
// track used imports and extern crates as well
self.used_imports.insert((import_resolution.id(namespace), namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Success((target, true));
}
}
@ -5061,7 +5093,14 @@ impl<'a> Resolver<'a> {
Some(def) => {
// Found it.
let id = import_resolution.id(namespace);
// track imports and extern crates as well
self.used_imports.insert((id, namespace));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => {
self.used_crates.insert(kid);
},
_ => {}
}
return ImportNameDefinition(def, LastMod(AllPublic));
}
None => {
@ -5085,6 +5124,8 @@ impl<'a> Resolver<'a> {
match module.def_id.get() {
None => {} // Continue.
Some(def_id) => {
// track used crates
self.used_crates.insert(def_id.krate);
let lp = if module.is_public {LastMod(AllPublic)} else {
LastMod(DependsOn(def_id))
};
@ -5168,6 +5209,10 @@ impl<'a> Resolver<'a> {
},
_ => (),
}
match containing_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
return Some(def);
}
@ -5787,6 +5832,10 @@ impl<'a> Resolver<'a> {
if self.trait_item_map.borrow().contains_key(&(name, did)) {
add_trait_info(&mut found_traits, did, name);
self.used_imports.insert((import.type_id, TypeNS));
match target.target_module.def_id.get() {
Some(DefId{krate: kid, ..}) => { self.used_crates.insert(kid); },
_ => {}
}
}
}
@ -5859,10 +5908,22 @@ impl<'a> Resolver<'a> {
if vi.span == DUMMY_SP { return }
match vi.node {
ViewItemExternCrate(..) => {} // ignore
ViewItemExternCrate(_, _, id) => {
match self.session.cstore.find_extern_mod_stmt_cnum(id)
{
Some(crate_num) => if !self.used_crates.contains(&crate_num) {
self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATE,
id,
vi.span,
"unused extern crate".to_string());
},
_ => {}
}
},
ViewItemUse(ref p) => {
match p.node {
ViewPathSimple(_, _, id) => self.finalize_import(id, p.span),
ViewPathList(_, ref list, _) => {
for i in list.iter() {
self.finalize_import(i.node.id(), i.span);

View File

@ -0,0 +1,32 @@
// Copyright 2014 The Rust Project Developers. See the COPYRIGHT
// file at the top-level directory of this distribution and at
// http://rust-lang.org/COPYRIGHT.
//
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
// option. This file may not be copied, modified, or distributed
// except according to those terms.
#![feature(globs)]
#![deny(unused_extern_crate)]
#![allow(unused_variable)]
extern crate libc; //~ ERROR: unused extern crate
extern crate "collections" as collecs; // no error, it is used
extern crate rand; // no error, the use marks it as used
// even if imported objects aren't used
extern crate time; // no error, the use * marks it as used
#[allow(unused_imports)]
use rand::isaac::IsaacRng;
use time::*;
fn main() {
let x: collecs::vec::Vec<uint> = Vec::new();
let y = now();
}