// Copyright 2012-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.


//
// Unused import checking
//
// Although this is mostly a lint pass, it lives in here because it depends on
// resolve data structures and because it finalises the privacy information for
// `use` directives.
//

use std::ops::{Deref, DerefMut};

use Resolver;
use Namespace::{TypeNS, ValueNS};

use rustc::lint;
use rustc::middle::privacy::{DependsOn, LastImport, Used, Unused};
use syntax::ast;
use syntax::codemap::{Span, DUMMY_SP};

use rustc_front::hir;
use rustc_front::hir::{ViewPathGlob, ViewPathList, ViewPathSimple};
use rustc_front::intravisit::Visitor;

struct UnusedImportCheckVisitor<'a, 'b: 'a, 'tcx: 'b> {
    resolver: &'a mut Resolver<'b, 'tcx>,
}

// Deref and DerefMut impls allow treating UnusedImportCheckVisitor as Resolver.
impl<'a, 'b, 'tcx:'b> Deref for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
    type Target = Resolver<'b, 'tcx>;

    fn deref<'c>(&'c self) -> &'c Resolver<'b, 'tcx> {
        &*self.resolver
    }
}

impl<'a, 'b, 'tcx:'b> DerefMut for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
    fn deref_mut<'c>(&'c mut self) -> &'c mut Resolver<'b, 'tcx> {
        &mut *self.resolver
    }
}

impl<'a, 'b, 'tcx> UnusedImportCheckVisitor<'a, 'b, 'tcx> {
    // We have information about whether `use` (import) directives are actually
    // used now. If an import is not used at all, we signal a lint error. If an
    // import is only used for a single namespace, we remove the other namespace
    // from the recorded privacy information. That means in privacy.rs, we will
    // only check imports and namespaces which are used. In particular, this
    // means that if an import could name either a public or private item, we
    // will check the correct thing, dependent on how the import is used.
    fn finalize_import(&mut self, id: ast::NodeId, span: Span) {
        debug!("finalizing import uses for {:?}",
               self.session.codemap().span_to_snippet(span));

        if !self.used_imports.contains(&(id, TypeNS)) &&
           !self.used_imports.contains(&(id, ValueNS)) {
            self.session.add_lint(lint::builtin::UNUSED_IMPORTS,
                                  id,
                                  span,
                                  "unused import".to_string());
        }

        let mut def_map = self.def_map.borrow_mut();
        let path_res = if let Some(r) = def_map.get_mut(&id) {
            r
        } else {
            return;
        };
        let (v_priv, t_priv) = match path_res.last_private {
            LastImport { value_priv, type_priv, .. } => (value_priv, type_priv),
            _ => {
                panic!("we should only have LastImport for `use` directives")
            }
        };

        let mut v_used = if self.used_imports.contains(&(id, ValueNS)) {
            Used
        } else {
            Unused
        };
        let t_used = if self.used_imports.contains(&(id, TypeNS)) {
            Used
        } else {
            Unused
        };

        match (v_priv, t_priv) {
            // Since some items may be both in the value _and_ type namespaces (e.g., structs)
            // we might have two LastPrivates pointing at the same thing. There is no point
            // checking both, so lets not check the value one.
            (Some(DependsOn(def_v)), Some(DependsOn(def_t))) if def_v == def_t => v_used = Unused,
            _ => {}
        }

        path_res.last_private = LastImport {
            value_priv: v_priv,
            value_used: v_used,
            type_priv: t_priv,
            type_used: t_used,
        };
    }
}

impl<'a, 'b, 'v, 'tcx> Visitor<'v> for UnusedImportCheckVisitor<'a, 'b, 'tcx> {
    fn visit_item(&mut self, item: &hir::Item) {
        // Ignore is_public import statements because there's no way to be sure
        // whether they're used or not. Also ignore imports with a dummy span
        // because this means that they were generated in some fashion by the
        // compiler and we don't need to consider them.
        if item.vis == hir::Public || item.span == DUMMY_SP {
            return;
        }

        match item.node {
            hir::ItemExternCrate(_) => {
                if let Some(crate_num) = self.session.cstore.extern_mod_stmt_cnum(item.id) {
                    if !self.used_crates.contains(&crate_num) {
                        self.session.add_lint(lint::builtin::UNUSED_EXTERN_CRATES,
                                              item.id,
                                              item.span,
                                              "unused extern crate".to_string());
                    }
                }
            }
            hir::ItemUse(ref p) => {
                match p.node {
                    ViewPathSimple(_, _) => {
                        self.finalize_import(item.id, p.span)
                    }

                    ViewPathList(_, ref list) => {
                        for i in list {
                            self.finalize_import(i.node.id(), i.span);
                        }
                    }
                    ViewPathGlob(_) => {
                        if !self.used_imports.contains(&(item.id, TypeNS)) &&
                           !self.used_imports.contains(&(item.id, ValueNS)) {
                            self.session
                                .add_lint(lint::builtin::UNUSED_IMPORTS,
                                          item.id,
                                          p.span,
                                          "unused import".to_string());
                        }
                    }
                }
            }
            _ => {}
        }
    }
}

pub fn check_crate(resolver: &mut Resolver, krate: &hir::Crate) {
    let mut visitor = UnusedImportCheckVisitor { resolver: resolver };
    krate.visit_all_items(&mut visitor);
}
