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

//! Used by `rustc` when loading a crate with exported macros.

use creader::CrateReader;
use cstore::CStore;

use rustc::session::Session;

use std::collections::{HashSet, HashMap};
use syntax::parse::token;
use syntax::ast;
use syntax::attr;
use syntax::attr::AttrMetaMethods;
use syntax::ext;
use syntax_pos::Span;

pub struct MacroLoader<'a> {
    sess: &'a Session,
    reader: CrateReader<'a>,
}

impl<'a> MacroLoader<'a> {
    pub fn new(sess: &'a Session, cstore: &'a CStore, crate_name: &str) -> MacroLoader<'a> {
        MacroLoader {
            sess: sess,
            reader: CrateReader::new(sess, cstore, crate_name),
        }
    }
}

pub fn call_bad_macro_reexport(a: &Session, b: Span) {
    span_err!(a, b, E0467, "bad macro reexport");
}

pub type MacroSelection = HashMap<token::InternedString, Span>;

impl<'a> ext::base::MacroLoader for MacroLoader<'a> {
    fn load_crate(&mut self, extern_crate: &ast::Item, allows_macros: bool) -> Vec<ast::MacroDef> {
        // Parse the attributes relating to macros.
        let mut import = Some(HashMap::new());  // None => load all
        let mut reexport = HashMap::new();

        for attr in &extern_crate.attrs {
            let mut used = true;
            match &attr.name()[..] {
                "macro_use" => {
                    let names = attr.meta_item_list();
                    if names.is_none() {
                        // no names => load all
                        import = None;
                    }
                    if let (Some(sel), Some(names)) = (import.as_mut(), names) {
                        for attr in names {
                            if attr.is_word() {
                                sel.insert(attr.name().clone(), attr.span());
                            } else {
                                span_err!(self.sess, attr.span(), E0466, "bad macro import");
                            }
                        }
                    }
                }
                "macro_reexport" => {
                    let names = match attr.meta_item_list() {
                        Some(names) => names,
                        None => {
                            call_bad_macro_reexport(self.sess, attr.span);
                            continue;
                        }
                    };

                    for attr in names {
                        if attr.is_word() {
                            reexport.insert(attr.name().clone(), attr.span());
                        } else {
                            call_bad_macro_reexport(self.sess, attr.span());
                        }
                    }
                }
                _ => used = false,
            }
            if used {
                attr::mark_used(attr);
            }
        }

        self.load_macros(extern_crate, allows_macros, import, reexport)
    }
}

impl<'a> MacroLoader<'a> {
    fn load_macros<'b>(&mut self,
                       vi: &ast::Item,
                       allows_macros: bool,
                       import: Option<MacroSelection>,
                       reexport: MacroSelection)
                       -> Vec<ast::MacroDef> {
        if let Some(sel) = import.as_ref() {
            if sel.is_empty() && reexport.is_empty() {
                return Vec::new();
            }
        }

        if !allows_macros {
            span_err!(self.sess, vi.span, E0468,
                      "an `extern crate` loading macros must be at the crate root");
            return Vec::new();
        }

        let mut macros = Vec::new();
        let mut seen = HashSet::new();

        for mut def in self.reader.read_exported_macros(vi) {
            let name = def.ident.name.as_str();

            def.use_locally = match import.as_ref() {
                None => true,
                Some(sel) => sel.contains_key(&name),
            };
            def.export = reexport.contains_key(&name);
            def.allow_internal_unstable = attr::contains_name(&def.attrs,
                                                              "allow_internal_unstable");
            debug!("load_macros: loaded: {:?}", def);
            macros.push(def);
            seen.insert(name);
        }

        if let Some(sel) = import.as_ref() {
            for (name, span) in sel {
                if !seen.contains(&name) {
                    span_err!(self.sess, *span, E0469,
                              "imported macro not found");
                }
            }
        }

        for (name, span) in &reexport {
            if !seen.contains(&name) {
                span_err!(self.sess, *span, E0470,
                          "reexported macro not found");
            }
        }

        macros
    }
}
