/* This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use std::collections::hash_map::Entry;
use std::collections::{HashMap, HashSet};
use std::fs::File;
use std::io::Read;
use std::path::{Path as FilePath, PathBuf as FilePathBuf};

use syn::ext::IdentExt;

use crate::bindgen::bitflags;
use crate::bindgen::cargo::{Cargo, PackageRef};
use crate::bindgen::config::{Config, ParseConfig};
use crate::bindgen::error::Error;
use crate::bindgen::ir::{
    AnnotationSet, Cfg, Constant, Documentation, Enum, Function, GenericParam, GenericParams,
    ItemMap, OpaqueItem, Path, Static, Struct, Type, Typedef, Union,
};
use crate::bindgen::utilities::{SynAbiHelpers, SynAttributeHelpers, SynItemFnHelpers};

const STD_CRATES: &[&str] = &[
    "std",
    "std_unicode",
    "alloc",
    "collections",
    "core",
    "proc_macro",
];

type ParseResult = Result<Parse, Error>;

/// Parses a single rust source file, not following `mod` or `extern crate`.
pub fn parse_src(src_file: &FilePath, config: &Config) -> ParseResult {
    let mod_name = src_file.file_stem().unwrap().to_str().unwrap();
    let mut config = config.clone();
    config.parse = ParseConfig {
        parse_deps: true,
        ..ParseConfig::default()
    };

    let mut context = Parser {
        binding_crate_name: mod_name.to_owned(),
        config: &config,
        lib: None,
        parsed_crates: HashSet::new(),
        cache_src: HashMap::new(),
        cache_expanded_crate: HashMap::new(),
        cfg_stack: Vec::new(),
        out: Parse::new(),
    };

    let pkg_ref = PackageRef {
        name: mod_name.to_owned(),
        version: None,
    };

    context.parse_mod(&pkg_ref, src_file, 0)?;
    Ok(context.out)
}

/// Recursively parses a rust library starting at the root crate's directory.
///
/// Inside a crate, `mod` and `extern crate` declarations are followed
/// and parsed. To find an external crate, the parser uses the `cargo metadata`
/// command to find the location of dependencies.
pub(crate) fn parse_lib(lib: Cargo, config: &Config) -> ParseResult {
    let mut context = Parser {
        binding_crate_name: lib.binding_crate_name().to_owned(),
        config,
        lib: Some(lib),
        parsed_crates: HashSet::new(),
        cache_src: HashMap::new(),
        cache_expanded_crate: HashMap::new(),
        cfg_stack: Vec::new(),
        out: Parse::new(),
    };

    let binding_crate = context.lib.as_ref().unwrap().binding_crate_ref();
    context.parse_crate(&binding_crate)?;
    Ok(context.out)
}

#[derive(Debug, Clone)]
struct Parser<'a> {
    binding_crate_name: String,
    lib: Option<Cargo>,
    config: &'a Config,

    parsed_crates: HashSet<String>,
    cache_src: HashMap<FilePathBuf, Vec<syn::Item>>,
    cache_expanded_crate: HashMap<String, Vec<syn::Item>>,

    cfg_stack: Vec<Cfg>,

    out: Parse,
}

impl<'a> Parser<'a> {
    fn should_parse_dependency(&self, pkg_name: &str) -> bool {
        if self.parsed_crates.contains(pkg_name) {
            return false;
        }

        if !self.config.parse.parse_deps {
            return false;
        }

        // Skip any whitelist or blacklist for expand
        if self
            .config
            .parse
            .expand
            .crates
            .iter()
            .any(|name| name == pkg_name)
        {
            return true;
        }

        // If we have a whitelist, check it
        if let Some(ref include) = self.config.parse.include {
            if !include.iter().any(|name| name == pkg_name) {
                debug!("Excluding crate {}", pkg_name);
                return false;
            }
        }

        // Check the blacklist
        !STD_CRATES.contains(&pkg_name)
            && !self
                .config
                .parse
                .exclude
                .iter()
                .any(|name| name == pkg_name)
    }

    fn parse_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
        assert!(self.lib.is_some());
        debug!("Parsing crate {}", pkg.name);
        self.parsed_crates.insert(pkg.name.clone());

        // Check if we should use cargo expand for this crate
        if self.config.parse.expand.crates.contains(&pkg.name) {
            self.parse_expand_crate(pkg)?;
        } else {
            // Parse the crate before the dependencies otherwise the same-named idents we
            // want to generate bindings for would be replaced by the ones provided
            // by the first dependency containing it.
            let crate_src = self.lib.as_ref().unwrap().find_crate_src(pkg);

            match crate_src {
                Some(crate_src) => self.parse_mod(pkg, crate_src.as_path(), 0)?,
                None => {
                    // This should be an error, but is common enough to just elicit a warning
                    warn!(
                        "Parsing crate `{}`: can't find lib.rs with `cargo metadata`. \
                        The crate may be available only on a particular platform, \
                        so consider setting `fetch_all_dependencies` in your cbindgen configuration.",
                        pkg.name
                    );
                }
            }
        }

        for (dep_pkg, cfg) in self.lib.as_ref().unwrap().dependencies(pkg) {
            if !self.should_parse_dependency(&dep_pkg.name) {
                continue;
            }

            if let Some(ref cfg) = cfg {
                self.cfg_stack.push(cfg.clone());
            }

            self.parse_crate(&dep_pkg)?;

            if cfg.is_some() {
                self.cfg_stack.pop();
            }
        }

        Ok(())
    }

    fn parse_expand_crate(&mut self, pkg: &PackageRef) -> Result<(), Error> {
        assert!(self.lib.is_some());

        let mod_items = {
            if !self.cache_expanded_crate.contains_key(&pkg.name) {
                let s = self
                    .lib
                    .as_ref()
                    .unwrap()
                    .expand_crate(
                        pkg,
                        self.config.parse.expand.all_features,
                        self.config.parse.expand.default_features,
                        &self.config.parse.expand.features,
                        self.config.parse.expand.profile,
                    )
                    .map_err(|x| Error::CargoExpand(pkg.name.clone(), x))?;
                let i = syn::parse_file(&s).map_err(|x| Error::ParseSyntaxError {
                    crate_name: pkg.name.clone(),
                    src_path: "".to_owned(),
                    error: x,
                })?;
                self.cache_expanded_crate.insert(pkg.name.clone(), i.items);
            }

            self.cache_expanded_crate.get(&pkg.name).unwrap().clone()
        };

        self.process_mod(
            pkg, None, None, &mod_items, 0, /* is_mod_rs = */ true,
            /* is_inline = */ false,
        )
    }

    fn parse_mod(
        &mut self,
        pkg: &PackageRef,
        mod_path: &FilePath,
        depth: usize,
    ) -> Result<(), Error> {
        let mod_items = match self.cache_src.entry(mod_path.to_path_buf()) {
            Entry::Vacant(vacant_entry) => {
                let mut s = String::new();
                let mut f = File::open(mod_path).map_err(|_| Error::ParseCannotOpenFile {
                    crate_name: pkg.name.clone(),
                    src_path: mod_path.to_str().unwrap().to_owned(),
                })?;

                f.read_to_string(&mut s)
                    .map_err(|_| Error::ParseCannotOpenFile {
                        crate_name: pkg.name.clone(),
                        src_path: mod_path.to_str().unwrap().to_owned(),
                    })?;

                let i = syn::parse_file(&s).map_err(|x| Error::ParseSyntaxError {
                    crate_name: pkg.name.clone(),
                    src_path: mod_path.to_string_lossy().into(),
                    error: x,
                })?;

                vacant_entry.insert(i.items).clone()
            }
            Entry::Occupied(occupied_entry) => occupied_entry.get().clone(),
        };

        // Compute module directory according to Rust 2018 rules
        let submod_dir_2018;

        let mod_dir = mod_path.parent().unwrap();

        let is_mod_rs = depth == 0 || mod_path.ends_with("mod.rs");
        let submod_dir = if is_mod_rs {
            mod_dir
        } else {
            submod_dir_2018 = mod_path
                .parent()
                .unwrap()
                .join(mod_path.file_stem().unwrap());
            &submod_dir_2018
        };

        self.process_mod(
            pkg,
            Some(mod_dir),
            Some(submod_dir),
            &mod_items,
            depth,
            /* is_inline = */ false,
            is_mod_rs,
        )
    }

    /// `mod_dir` is the path to the current directory of the module. It may be
    /// `None` for pre-expanded modules.
    ///
    /// `submod_dir` is the path to search submodules in by default, which might
    /// be different for rust 2018 for example.
    #[allow(clippy::too_many_arguments)]
    fn process_mod(
        &mut self,
        pkg: &PackageRef,
        mod_dir: Option<&FilePath>,
        submod_dir: Option<&FilePath>,
        items: &[syn::Item],
        depth: usize,
        is_inline: bool,
        is_in_mod_rs: bool,
    ) -> Result<(), Error> {
        debug_assert_eq!(mod_dir.is_some(), submod_dir.is_some());
        // We process the items first then the nested modules.
        let nested_modules = self.out.load_syn_crate_mod(
            self.config,
            &self.binding_crate_name,
            &pkg.name,
            Cfg::join(&self.cfg_stack).as_ref(),
            items,
        );

        for item in nested_modules {
            let next_mod_name = item.ident.unraw().to_string();
            let cfg = Cfg::load(&item.attrs);
            if let Some(ref cfg) = cfg {
                self.cfg_stack.push(cfg.clone());
            }

            if let Some((_, ref inline_items)) = item.content {
                // TODO(emilio): This should use #[path] attribute if present,
                // rather than next_mod_name.
                let next_submod_dir = submod_dir.map(|dir| dir.join(&next_mod_name));
                let next_mod_dir = mod_dir.map(|dir| dir.join(&next_mod_name));
                self.process_mod(
                    pkg,
                    next_mod_dir.as_deref(),
                    next_submod_dir.as_deref(),
                    inline_items,
                    depth,
                    /* is_inline = */ true,
                    is_in_mod_rs,
                )?;
            } else if let Some(mod_dir) = mod_dir {
                let submod_dir = submod_dir.unwrap();
                let next_mod_path1 = submod_dir.join(next_mod_name.clone() + ".rs");
                let next_mod_path2 = submod_dir.join(next_mod_name.clone()).join("mod.rs");

                if next_mod_path1.exists() {
                    self.parse_mod(pkg, next_mod_path1.as_path(), depth + 1)?;
                } else if next_mod_path2.exists() {
                    self.parse_mod(pkg, next_mod_path2.as_path(), depth + 1)?;
                } else {
                    // Last chance to find a module path
                    let mut path_attr_found = false;
                    for attr in &item.attrs {
                        if let Ok(syn::Meta::NameValue(syn::MetaNameValue { path, lit, .. })) =
                            attr.parse_meta()
                        {
                            match lit {
                                syn::Lit::Str(ref path_lit) if path.is_ident("path") => {
                                    path_attr_found = true;
                                    // https://doc.rust-lang.org/reference/items/modules.html#the-path-attribute
                                    //
                                    //     For path attributes on modules not inside inline module blocks, the file path
                                    //     is relative to the directory the source file is located.
                                    //
                                    //     For path attributes inside inline module blocks, the relative location of the
                                    //     file path depends on the kind of source file the path attribute is located
                                    //     in.  "mod-rs" source files are root modules (such as lib.rs or main.rs) and
                                    //     modules with files named mod.rs. "non-mod-rs" source files are all other
                                    //     module files.
                                    //
                                    //     Paths for path attributes inside inline module blocks in a mod-rs file are
                                    //     relative to the directory of the mod-rs file including the inline module
                                    //     components as directories. For non-mod-rs files, it is the same except the
                                    //     path starts with a directory with the name of the non-mod-rs module.
                                    //
                                    let base = if is_inline && !is_in_mod_rs {
                                        submod_dir
                                    } else {
                                        mod_dir
                                    };
                                    self.parse_mod(pkg, &base.join(path_lit.value()), depth + 1)?;
                                    break;
                                }
                                _ => (),
                            }
                        }
                    }

                    // This should be an error, but it's common enough to
                    // just elicit a warning
                    if !path_attr_found {
                        warn!(
                            "Parsing crate `{}`: can't find mod {}`.",
                            pkg.name, next_mod_name
                        );
                    }
                }
            } else {
                warn!(
                    "Parsing expanded crate `{}`: can't find mod {}`.",
                    pkg.name, next_mod_name
                );
            }

            if cfg.is_some() {
                self.cfg_stack.pop();
            }
        }

        Ok(())
    }
}

#[derive(Debug, Clone)]
pub struct Parse {
    pub constants: ItemMap<Constant>,
    pub globals: ItemMap<Static>,
    pub enums: ItemMap<Enum>,
    pub structs: ItemMap<Struct>,
    pub unions: ItemMap<Union>,
    pub opaque_items: ItemMap<OpaqueItem>,
    pub typedefs: ItemMap<Typedef>,
    pub functions: Vec<Function>,
}

impl Parse {
    pub fn new() -> Parse {
        Parse {
            constants: ItemMap::default(),
            globals: ItemMap::default(),
            enums: ItemMap::default(),
            structs: ItemMap::default(),
            unions: ItemMap::default(),
            opaque_items: ItemMap::default(),
            typedefs: ItemMap::default(),
            functions: Vec::new(),
        }
    }

    pub fn add_std_types(&mut self) {
        let mut add_opaque = |path: &str, generic_params: Vec<&str>| {
            let path = Path::new(path);
            let generic_params: Vec<_> = generic_params
                .into_iter()
                .map(GenericParam::new_type_param)
                .collect();
            self.opaque_items.try_insert(OpaqueItem::new(
                path,
                GenericParams(generic_params),
                None,
                AnnotationSet::new(),
                Documentation::none(),
            ))
        };

        add_opaque("String", vec![]);
        add_opaque("Box", vec!["T"]);
        add_opaque("RefCell", vec!["T"]);
        add_opaque("Rc", vec!["T"]);
        add_opaque("Arc", vec!["T"]);
        add_opaque("Result", vec!["T", "E"]);
        add_opaque("Option", vec!["T"]);
        add_opaque("NonNull", vec!["T"]);
        add_opaque("Vec", vec!["T"]);
        add_opaque("HashMap", vec!["K", "V", "Hasher"]);
        add_opaque("BTreeMap", vec!["K", "V"]);
        add_opaque("HashSet", vec!["T"]);
        add_opaque("BTreeSet", vec!["T"]);
        add_opaque("LinkedList", vec!["T"]);
        add_opaque("VecDeque", vec!["T"]);
        add_opaque("ManuallyDrop", vec!["T"]);
        add_opaque("MaybeUninit", vec!["T"]);
    }

    pub fn extend_with(&mut self, other: &Parse) {
        self.constants.extend_with(&other.constants);
        self.globals.extend_with(&other.globals);
        self.enums.extend_with(&other.enums);
        self.structs.extend_with(&other.structs);
        self.unions.extend_with(&other.unions);
        self.opaque_items.extend_with(&other.opaque_items);
        self.typedefs.extend_with(&other.typedefs);
        self.functions.extend_from_slice(&other.functions);
    }

    fn load_syn_crate_mod<'a>(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        items: &'a [syn::Item],
    ) -> Vec<&'a syn::ItemMod> {
        let mut impls_with_assoc_consts = Vec::new();
        let mut nested_modules = Vec::new();

        for item in items {
            if item.should_skip_parsing() {
                continue;
            }
            match item {
                syn::Item::ForeignMod(ref item) => {
                    self.load_syn_foreign_mod(
                        config,
                        binding_crate_name,
                        crate_name,
                        mod_cfg,
                        item,
                    );
                }
                syn::Item::Fn(ref item) => {
                    self.load_syn_fn(config, binding_crate_name, crate_name, mod_cfg, item);
                }
                syn::Item::Const(ref item) => {
                    self.load_syn_const(config, binding_crate_name, crate_name, mod_cfg, item);
                }
                syn::Item::Static(ref item) => {
                    self.load_syn_static(config, binding_crate_name, crate_name, mod_cfg, item);
                }
                syn::Item::Struct(ref item) => {
                    self.load_syn_struct(config, crate_name, mod_cfg, item);
                }
                syn::Item::Union(ref item) => {
                    self.load_syn_union(config, crate_name, mod_cfg, item);
                }
                syn::Item::Enum(ref item) => {
                    self.load_syn_enum(config, crate_name, mod_cfg, item);
                }
                syn::Item::Type(ref item) => {
                    self.load_syn_ty(crate_name, mod_cfg, item);
                }
                syn::Item::Impl(ref item_impl) => {
                    let has_assoc_const = item_impl
                        .items
                        .iter()
                        .any(|item| matches!(item, syn::ImplItem::Const(_)));
                    if has_assoc_const {
                        impls_with_assoc_consts.push(item_impl);
                    }

                    if let syn::Type::Path(ref path) = *item_impl.self_ty {
                        if let Some(type_name) = path.path.get_ident() {
                            for method in item_impl.items.iter().filter_map(|item| match item {
                                syn::ImplItem::Method(method) => Some(method),
                                _ => None,
                            }) {
                                self.load_syn_method(
                                    config,
                                    binding_crate_name,
                                    crate_name,
                                    mod_cfg,
                                    &Path::new(type_name.unraw().to_string()),
                                    method,
                                )
                            }
                        }
                    }
                }
                syn::Item::Macro(ref item) => {
                    self.load_builtin_macro(config, crate_name, mod_cfg, item)
                }
                syn::Item::Mod(ref item) => {
                    nested_modules.push(item);
                }
                _ => {}
            }
        }

        for item_impl in impls_with_assoc_consts {
            self.load_syn_assoc_consts_from_impl(crate_name, mod_cfg, item_impl)
        }

        nested_modules
    }

    fn load_syn_assoc_consts_from_impl(
        &mut self,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item_impl: &syn::ItemImpl,
    ) {
        let associated_constants = item_impl.items.iter().filter_map(|item| match item {
            syn::ImplItem::Const(ref associated_constant) => Some(associated_constant),
            _ => None,
        });
        self.load_syn_assoc_consts(
            crate_name,
            mod_cfg,
            &item_impl.self_ty,
            associated_constants,
        );
    }

    /// Enters a `extern "C" { }` declaration and loads function declarations.
    fn load_syn_foreign_mod(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemForeignMod,
    ) {
        if !item.abi.is_c() {
            info!("Skip {} - (extern block must be extern C).", crate_name);
            return;
        }

        for foreign_item in &item.items {
            if let syn::ForeignItem::Fn(ref function) = *foreign_item {
                if !config
                    .parse
                    .should_generate_top_level_item(crate_name, binding_crate_name)
                {
                    info!(
                        "Skip {}::{} - (fn's outside of the binding crate are not used).",
                        crate_name, &function.sig.ident
                    );
                    return;
                }
                let path = Path::new(function.sig.ident.unraw().to_string());
                match Function::load(path, None, &function.sig, true, &function.attrs, mod_cfg) {
                    Ok(func) => {
                        info!("Take {}::{}.", crate_name, &function.sig.ident);

                        self.functions.push(func);
                    }
                    Err(msg) => {
                        error!(
                            "Cannot use fn {}::{} ({}).",
                            crate_name, &function.sig.ident, msg
                        );
                    }
                }
            }
        }
    }

    /// Loads a `fn` declaration inside an `impl` block, if the type is a simple identifier
    fn load_syn_method(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        self_type: &Path,
        item: &syn::ImplItemMethod,
    ) {
        self.load_fn_declaration(
            config,
            binding_crate_name,
            crate_name,
            mod_cfg,
            item,
            Some(self_type),
            &item.sig,
            &item.vis,
            &item.attrs,
        )
    }

    /// Loads a `fn` declaration
    fn load_syn_fn(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemFn,
    ) {
        self.load_fn_declaration(
            config,
            binding_crate_name,
            crate_name,
            mod_cfg,
            item,
            None,
            &item.sig,
            &item.vis,
            &item.attrs,
        );
    }

    #[allow(clippy::too_many_arguments)]
    fn load_fn_declaration(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        named_symbol: &dyn SynItemFnHelpers,
        self_type: Option<&Path>,
        sig: &syn::Signature,
        vis: &syn::Visibility,
        attrs: &[syn::Attribute],
    ) {
        if !config
            .parse
            .should_generate_top_level_item(crate_name, binding_crate_name)
        {
            info!(
                "Skip {}::{} - (fn's outside of the binding crate are not used).",
                crate_name, &sig.ident
            );
            return;
        }

        let loggable_item_name = || {
            let mut items = Vec::with_capacity(3);
            items.push(crate_name.to_owned());
            if let Some(ref self_type) = self_type {
                items.push(self_type.to_string());
            }
            items.push(sig.ident.unraw().to_string());
            items.join("::")
        };

        let is_extern_c = sig.abi.is_omitted() || sig.abi.is_c();
        let exported_name = named_symbol.exported_name();

        if let syn::Visibility::Public(_) = vis {
            match (is_extern_c, exported_name) {
                (true, Some(exported_name)) => {
                    let path = Path::new(exported_name);
                    match Function::load(path, self_type, sig, false, attrs, mod_cfg) {
                        Ok(func) => {
                            info!("Take {}.", loggable_item_name());
                            self.functions.push(func);
                        }
                        Err(msg) => {
                            error!("Cannot use fn {} ({}).", loggable_item_name(), msg);
                        }
                    }
                }
                (true, None) => {
                    warn!(
                        "Skipping {} - (not `no_mangle`, and has no `export_name` attribute)",
                        loggable_item_name()
                    );
                }
                (false, Some(_exported_name)) => {
                    warn!("Skipping {} - (not `extern \"C\"`", loggable_item_name());
                }
                (false, None) => {}
            }
        } else {
            match (is_extern_c, exported_name) {
                (true, Some(..)) => {
                    warn!(
                        "Skipping {} - (not `pub` but is `extern \"C\"` and `no_mangle`)",
                        loggable_item_name()
                    );
                }
                (true, None) => {
                    warn!(
                        "Skipping {} - (not `pub` but is `extern \"C\"`)",
                        loggable_item_name()
                    );
                }
                (false, Some(..)) => {
                    warn!(
                        "Skipping {} - (not `pub` but is `no_mangle`)",
                        loggable_item_name()
                    );
                }
                (false, None) => {}
            }
        }
    }

    /// Loads associated `const` declarations
    fn load_syn_assoc_consts<'a, I>(
        &mut self,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        impl_ty: &syn::Type,
        items: I,
    ) where
        I: IntoIterator<Item = &'a syn::ImplItemConst>,
    {
        let ty = match Type::load(impl_ty) {
            Ok(ty) => ty,
            Err(e) => {
                warn!("Skipping associated constants for {:?}: {:?}", impl_ty, e);
                return;
            }
        };

        let ty = match ty {
            Some(ty) => ty,
            None => return,
        };

        let impl_path = match ty.get_root_path() {
            Some(p) => p,
            None => {
                warn!(
                    "Couldn't find path for {:?}, skipping associated constants",
                    ty
                );
                return;
            }
        };

        for item in items.into_iter() {
            if let syn::Visibility::Public(_) = item.vis {
            } else {
                warn!("Skip {}::{} - (not `pub`).", crate_name, &item.ident);
                return;
            }

            let path = Path::new(item.ident.unraw().to_string());
            match Constant::load(
                path,
                mod_cfg,
                &item.ty,
                &item.expr,
                &item.attrs,
                Some(impl_path.clone()),
            ) {
                Ok(constant) => {
                    info!("Take {}::{}::{}.", crate_name, impl_path, &item.ident);
                    let mut any = false;
                    self.structs.for_items_mut(&impl_path, |item| {
                        any = true;
                        item.add_associated_constant(constant.clone());
                    });
                    // Handle associated constants to other item types that are
                    // not structs like enums or such as regular constants.
                    if !any && !self.constants.try_insert(constant) {
                        error!(
                            "Conflicting name for constant {}::{}::{}.",
                            crate_name, impl_path, &item.ident,
                        );
                    }
                }
                Err(msg) => {
                    warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
                }
            }
        }
    }

    /// Loads a `const` declaration
    fn load_syn_const(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemConst,
    ) {
        if !config
            .parse
            .should_generate_top_level_item(crate_name, binding_crate_name)
        {
            info!(
                "Skip {}::{} - (const's outside of the binding crate are not used).",
                crate_name, &item.ident
            );
            return;
        }

        if let syn::Visibility::Public(_) = item.vis {
        } else {
            warn!("Skip {}::{} - (not `pub`).", crate_name, &item.ident);
            return;
        }

        let path = Path::new(item.ident.unraw().to_string());
        match Constant::load(path, mod_cfg, &item.ty, &item.expr, &item.attrs, None) {
            Ok(constant) => {
                info!("Take {}::{}.", crate_name, &item.ident);

                let full_name = constant.path.clone();
                if !self.constants.try_insert(constant) {
                    error!("Conflicting name for constant {}", full_name);
                }
            }
            Err(msg) => {
                warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
            }
        }
    }

    /// Loads a `static` declaration
    fn load_syn_static(
        &mut self,
        config: &Config,
        binding_crate_name: &str,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemStatic,
    ) {
        if !config
            .parse
            .should_generate_top_level_item(crate_name, binding_crate_name)
        {
            info!(
                "Skip {}::{} - (static's outside of the binding crate are not used).",
                crate_name, &item.ident
            );
            return;
        }

        if let syn::Visibility::Public(_) = item.vis {
            if item.is_no_mangle() {
                match Static::load(item, mod_cfg) {
                    Ok(constant) => {
                        info!("Take {}::{}.", crate_name, &item.ident);

                        self.globals.try_insert(constant);
                    }
                    Err(msg) => {
                        warn!("Skip {}::{} - ({})", crate_name, &item.ident, msg);
                    }
                }
            }
        }

        // TODO
        if let syn::Visibility::Public(_) = item.vis {
        } else {
            warn!("Skip {}::{} - (not `pub`).", crate_name, &item.ident);
        }
        if !item.is_no_mangle() {
            warn!("Skip {}::{} - (not `no_mangle`).", crate_name, &item.ident);
        }
    }

    /// Loads a `struct` declaration
    fn load_syn_struct(
        &mut self,
        config: &Config,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemStruct,
    ) {
        match Struct::load(&config.layout, item, mod_cfg) {
            Ok(st) => {
                info!("Take {}::{}.", crate_name, &item.ident);
                self.structs.try_insert(st);
            }
            Err(msg) => {
                info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg);
                let path = Path::new(item.ident.unraw().to_string());
                self.opaque_items.try_insert(
                    OpaqueItem::load(path, &item.generics, &item.attrs, mod_cfg).unwrap(),
                );
            }
        }
    }

    /// Loads a `union` declaration
    fn load_syn_union(
        &mut self,
        config: &Config,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemUnion,
    ) {
        match Union::load(&config.layout, item, mod_cfg) {
            Ok(st) => {
                info!("Take {}::{}.", crate_name, &item.ident);

                self.unions.try_insert(st);
            }
            Err(msg) => {
                info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg);
                let path = Path::new(item.ident.unraw().to_string());
                self.opaque_items.try_insert(
                    OpaqueItem::load(path, &item.generics, &item.attrs, mod_cfg).unwrap(),
                );
            }
        }
    }

    /// Loads a `enum` declaration
    fn load_syn_enum(
        &mut self,
        config: &Config,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemEnum,
    ) {
        match Enum::load(item, mod_cfg, config) {
            Ok(en) => {
                info!("Take {}::{}.", crate_name, &item.ident);
                self.enums.try_insert(en);
            }
            Err(msg) => {
                info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg);
                let path = Path::new(item.ident.unraw().to_string());
                self.opaque_items.try_insert(
                    OpaqueItem::load(path, &item.generics, &item.attrs, mod_cfg).unwrap(),
                );
            }
        }
    }

    /// Loads a `type` declaration
    fn load_syn_ty(&mut self, crate_name: &str, mod_cfg: Option<&Cfg>, item: &syn::ItemType) {
        match Typedef::load(item, mod_cfg) {
            Ok(st) => {
                info!("Take {}::{}.", crate_name, &item.ident);

                self.typedefs.try_insert(st);
            }
            Err(msg) => {
                info!("Take {}::{} - opaque ({}).", crate_name, &item.ident, msg);
                let path = Path::new(item.ident.unraw().to_string());
                self.opaque_items.try_insert(
                    OpaqueItem::load(path, &item.generics, &item.attrs, mod_cfg).unwrap(),
                );
            }
        }
    }

    fn load_builtin_macro(
        &mut self,
        config: &Config,
        crate_name: &str,
        mod_cfg: Option<&Cfg>,
        item: &syn::ItemMacro,
    ) {
        let name = match item.mac.path.segments.last() {
            Some(n) => n.ident.unraw().to_string(),
            None => return,
        };

        if name != "bitflags" || !config.macro_expansion.bitflags {
            return;
        }

        let bitflags = match bitflags::parse(item.mac.tokens.clone()) {
            Ok(b) => b,
            Err(e) => {
                warn!("Failed to parse bitflags invocation: {:?}", e);
                return;
            }
        };

        let (struct_, impl_) = bitflags.expand();
        self.load_syn_struct(config, crate_name, mod_cfg, &struct_);
        // We know that the expansion will only reference `struct_`, so it's
        // fine to just do it here instead of deferring it like we do with the
        // other calls to this function.
        self.load_syn_assoc_consts_from_impl(crate_name, mod_cfg, &impl_);
    }
}
