]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/plugin/load.rs
rollup merge of #21830: japaric/for-cleanup
[rust.git] / src / librustc / plugin / load.rs
index e1f5c10a1a4e05a11531ca33bb140ca0da7f7cc8..dd0b0a63ced9de64a3b63eddf14ace3d25b26bc6 100644 (file)
@@ -15,7 +15,7 @@
 use plugin::registry::Registry;
 
 use std::mem;
-use std::os;
+use std::env;
 use std::dynamic_lib::DynamicLibrary;
 use std::collections::HashSet;
 use syntax::ast;
@@ -44,11 +44,11 @@ pub struct Plugins {
     pub registrars: Vec<PluginRegistrar>,
 }
 
-struct PluginLoader<'a> {
+pub struct PluginLoader<'a> {
     sess: &'a Session,
     span_whitelist: HashSet<Span>,
     reader: CrateReader<'a>,
-    plugins: Plugins,
+    pub plugins: Plugins,
 }
 
 impl<'a> PluginLoader<'a> {
@@ -67,47 +67,47 @@ fn new(sess: &'a Session) -> PluginLoader<'a> {
 
 /// Read plugin metadata and dynamically load registrar functions.
 pub fn load_plugins(sess: &Session, krate: &ast::Crate,
-                    addl_plugins: Option<Plugins>) -> Plugins {
+                    addl_plugins: Option<Vec<String>>) -> Plugins {
     let mut loader = PluginLoader::new(sess);
 
     // We need to error on `#[macro_use] extern crate` when it isn't at the
     // crate root, because `$crate` won't work properly. Identify these by
     // spans, because the crate map isn't set up yet.
-    for vi in krate.module.view_items.iter() {
-        loader.span_whitelist.insert(vi.span);
+    for item in &krate.module.items {
+        if let ast::ItemExternCrate(_) = item.node {
+            loader.span_whitelist.insert(item.span);
+        }
     }
 
     visit::walk_crate(&mut loader, krate);
 
-    let mut plugins = loader.plugins;
-
-    match addl_plugins {
-        Some(addl_plugins) => {
-            // Add in the additional plugins requested by the frontend
-            let Plugins { macros: addl_macros, registrars: addl_registrars } = addl_plugins;
-            plugins.macros.extend(addl_macros.into_iter());
-            plugins.registrars.extend(addl_registrars.into_iter());
+    if let Some(plugins) = addl_plugins {
+        for plugin in &plugins {
+            loader.load_plugin(CrateOrString::Str(plugin.as_slice()),
+                                                  None, None, None)
         }
-        None => ()
     }
 
-    return plugins;
+    return loader.plugins;
 }
 
 // note that macros aren't expanded yet, and therefore macros can't add plugins.
 impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
-    fn visit_view_item(&mut self, vi: &ast::ViewItem) {
+    fn visit_item(&mut self, item: &ast::Item) {
         // We're only interested in `extern crate`.
-        match vi.node {
-            ast::ViewItemExternCrate(..) => (),
-            _ => return,
+        match item.node {
+            ast::ItemExternCrate(_) => {}
+            _ => {
+                visit::walk_item(self, item);
+                return;
+            }
         }
 
         // Parse the attributes relating to macro / plugin loading.
         let mut plugin_attr = None;
         let mut macro_selection = Some(HashSet::new());  // None => load all
         let mut reexport = HashSet::new();
-        for attr in vi.attrs.iter() {
+        for attr in &item.attrs {
             let mut used = true;
             match attr.name().get() {
                 "phase" => {
@@ -127,7 +127,7 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem) {
                         macro_selection = None;
                     }
                     if let (Some(sel), Some(names)) = (macro_selection.as_mut(), names) {
-                        for name in names.iter() {
+                        for name in names {
                             if let ast::MetaWord(ref name) = name.node {
                                 sel.insert(name.clone());
                             } else {
@@ -145,7 +145,7 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem) {
                         }
                     };
 
-                    for name in names.iter() {
+                    for name in names {
                         if let ast::MetaWord(ref name) = name.node {
                             reexport.insert(name.clone());
                         } else {
@@ -160,22 +160,42 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem) {
             }
         }
 
+        self.load_plugin(CrateOrString::Krate(item),
+                         plugin_attr,
+                         macro_selection,
+                         Some(reexport))
+    }
+
+    fn visit_mac(&mut self, _: &ast::Mac) {
+        // bummer... can't see plugins inside macros.
+        // do nothing.
+    }
+}
+
+impl<'a> PluginLoader<'a> {
+    pub fn load_plugin<'b>(&mut self,
+                           c: CrateOrString<'b>,
+                           plugin_attr: Option<P<ast::MetaItem>>,
+                           macro_selection: Option<HashSet<token::InternedString>>,
+                           reexport: Option<HashSet<token::InternedString>>) {
         let mut macros = vec![];
         let mut registrar = None;
 
-        let load_macros = match macro_selection.as_ref() {
-            Some(sel) => sel.len() != 0 || reexport.len() != 0,
-            None => true,
+        let load_macros = match (macro_selection.as_ref(), reexport.as_ref()) {
+            (Some(sel), Some(re)) => sel.len() != 0 || re.len() != 0,
+            _ => true,
         };
         let load_registrar = plugin_attr.is_some();
 
-        if load_macros && !self.span_whitelist.contains(&vi.span) {
-            self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
-                                         the crate root");
-        }
+        if let CrateOrString::Krate(vi) = c {
+            if load_macros && !self.span_whitelist.contains(&vi.span) {
+                self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \
+                                             the crate root");
+            }
+       }
 
         if load_macros || load_registrar {
-            let pmd = self.reader.read_plugin_metadata(CrateOrString::Krate(vi));
+            let pmd = self.reader.read_plugin_metadata(c);
             if load_macros {
                 macros = pmd.exported_macros();
             }
@@ -184,18 +204,22 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem) {
             }
         }
 
-        for mut def in macros.into_iter() {
+        for mut def in macros {
             let name = token::get_ident(def.ident);
             def.use_locally = match macro_selection.as_ref() {
                 None => true,
                 Some(sel) => sel.contains(&name),
             };
-            def.export = reexport.contains(&name);
+            def.export = if let Some(ref re) = reexport {
+                re.contains(&name)
+            } else {
+                false // Don't reexport macros from crates loaded from the command line
+            };
             self.plugins.macros.push(def);
         }
 
         if let Some((lib, symbol)) = registrar {
-            let fun = self.dylink_registrar(vi, lib, symbol);
+            let fun = self.dylink_registrar(c, lib, symbol);
             self.plugins.registrars.push(PluginRegistrar {
                 fun: fun,
                 args: plugin_attr.unwrap(),
@@ -203,27 +227,26 @@ fn visit_view_item(&mut self, vi: &ast::ViewItem) {
         }
     }
 
-    fn visit_mac(&mut self, _: &ast::Mac) {
-        // bummer... can't see plugins inside macros.
-        // do nothing.
-    }
-}
-
-impl<'a> PluginLoader<'a> {
     // Dynamically link a registrar function into the compiler process.
-    fn dylink_registrar(&mut self,
-                        vi: &ast::ViewItem,
+    fn dylink_registrar<'b>(&mut self,
+                        c: CrateOrString<'b>,
                         path: Path,
                         symbol: String) -> PluginRegistrarFun {
         // Make sure the path contains a / or the linker will search for it.
-        let path = os::make_absolute(&path).unwrap();
+        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) => self.sess.span_fatal(vi.span, &err[])
+            Err(err) => {
+                if let CrateOrString::Krate(cr) = c {
+                    self.sess.span_fatal(cr.span, &err[])
+                } else {
+                    self.sess.fatal(&err[])
+                }
+            }
         };
 
         unsafe {
@@ -233,7 +256,13 @@ fn dylink_registrar(&mut self,
                         mem::transmute::<*mut u8,PluginRegistrarFun>(registrar)
                     }
                     // again fatal if we can't register macros
-                    Err(err) => self.sess.span_fatal(vi.span, &err[])
+                    Err(err) => {
+                        if let CrateOrString::Krate(cr) = c {
+                            self.sess.span_fatal(cr.span, &err[])
+                        } else {
+                            self.sess.fatal(&err[])
+                        }
+                    }
                 };
 
             // Intentionally leak the dynamic library. We can't ever unload it