//! Used by `rustc` when loading a plugin.

use rustc::middle::cstore::MetadataLoader;
use rustc::session::Session;
use rustc_metadata::locator;
use crate::Registry;

use std::borrow::ToOwned;
use std::env;
use std::mem;
use std::path::PathBuf;
use syntax::ast::{Crate, Ident};
use syntax::struct_span_err;
use syntax::symbol::sym;
use syntax_pos::Span;

use rustc_error_codes::*;

/// Pointer to a registrar function.
type PluginRegistrarFn = fn(&mut Registry<'_>);

fn call_malformed_plugin_attribute(sess: &Session, span: Span) {
    struct_span_err!(sess, span, E0498, "malformed `plugin` attribute")
        .span_label(span, "malformed attribute")
        .emit();
}

/// Read plugin metadata and dynamically load registrar functions.
pub fn load_plugins(sess: &Session,
                    metadata_loader: &dyn MetadataLoader,
                    krate: &Crate) -> Vec<PluginRegistrarFn> {
    let mut plugins = Vec::new();

    for attr in &krate.attrs {
        if !attr.check_name(sym::plugin) {
            continue;
        }

        for plugin in attr.meta_item_list().unwrap_or_default() {
            match plugin.ident() {
                Some(ident) if plugin.is_word() =>
                    load_plugin(&mut plugins, sess, metadata_loader, ident),
                _ => call_malformed_plugin_attribute(sess, plugin.span()),
            }
        }
    }

    plugins
}

fn load_plugin(plugins: &mut Vec<PluginRegistrarFn>,
               sess: &Session,
               metadata_loader: &dyn MetadataLoader,
               ident: Ident) {
    let registrar = locator::find_plugin_registrar(sess, metadata_loader, ident.span, ident.name);

    if let Some((lib, disambiguator)) = registrar {
        let symbol = sess.generate_plugin_registrar_symbol(disambiguator);
        let fun = dylink_registrar(sess, ident.span, lib, symbol);
        plugins.push(fun);
    }
}

// Dynamically link a registrar function into the compiler process.
fn dylink_registrar(sess: &Session,
                    span: Span,
                    path: PathBuf,
                    symbol: String) -> PluginRegistrarFn {
    use rustc_metadata::dynamic_lib::DynamicLibrary;

    // Make sure the path contains a / or the linker will search for it.
    let path = env::current_dir().unwrap().join(&path);

    let lib = match DynamicLibrary::open(Some(&path)) {
        Ok(lib) => lib,
        // this is fatal: there are almost certainly macros we need
        // inside this crate, so continue would spew "macro undefined"
        // errors
        Err(err) => {
            sess.span_fatal(span, &err)
        }
    };

    unsafe {
        let registrar =
            match lib.symbol(&symbol) {
                Ok(registrar) => {
                    mem::transmute::<*mut u8, PluginRegistrarFn>(registrar)
                }
                // again fatal if we can't register macros
                Err(err) => {
                    sess.span_fatal(span, &err)
                }
            };

        // Intentionally leak the dynamic library. We can't ever unload it
        // since the library can make things that will live arbitrarily long
        // (e.g., an @-box cycle or a thread).
        mem::forget(lib);

        registrar
    }
}
