diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-11 19:53:10 -0800 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-12 12:44:31 -0800 |
| commit | 6864792df002a4430634ea6ae096dd7e524560c2 (patch) | |
| tree | ed58a4df4bd2110bf783b693ad69245280fbadd4 /src/librustc/plugin | |
| parent | 6b784bacbfb3135bd34cd994023ac1e841ad9ceb (diff) | |
| download | rust-6864792df002a4430634ea6ae096dd7e524560c2.tar.gz rust-6864792df002a4430634ea6ae096dd7e524560c2.zip | |
Separate macro and plugin loading
Now they just share a bit of code internal to creader. Resolves #22198 to my satisfaction.
Diffstat (limited to 'src/librustc/plugin')
| -rw-r--r-- | src/librustc/plugin/load.rs | 179 |
1 files changed, 12 insertions, 167 deletions
diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 860bfaf4ce2..1895cbcb542 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -8,7 +8,7 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -//! Used by `rustc` when loading a plugin, or a crate with exported macros. +//! Used by `rustc` when loading a plugin. use session::Session; use metadata::creader::CrateReader; @@ -17,15 +17,10 @@ use plugin::registry::Registry; use std::mem; use std::env; use std::dynamic_lib::DynamicLibrary; -use std::collections::{HashSet, HashMap}; use std::borrow::ToOwned; use syntax::ast; -use syntax::attr; use syntax::codemap::{Span, COMMAND_LINE_SP}; -use syntax::parse::token; use syntax::ptr::P; -use syntax::visit; -use syntax::visit::Visitor; use syntax::attr::AttrMetaMethods; /// Pointer to a registrar function. @@ -37,51 +32,17 @@ pub struct PluginRegistrar { pub args: Vec<P<ast::MetaItem>>, } -/// Information about loaded plugins. -pub struct Plugins { - /// Imported macros. - pub macros: Vec<ast::MacroDef>, - /// Registrars, as function pointers. - pub registrars: Vec<PluginRegistrar>, -} - -pub struct PluginLoader<'a> { +struct PluginLoader<'a> { sess: &'a Session, - span_whitelist: HashSet<Span>, reader: CrateReader<'a>, - pub plugins: Plugins, -} - -impl<'a> PluginLoader<'a> { - fn new(sess: &'a Session) -> PluginLoader<'a> { - PluginLoader { - sess: sess, - reader: CrateReader::new(sess), - span_whitelist: HashSet::new(), - plugins: Plugins { - macros: vec!(), - registrars: vec!(), - }, - } - } + plugins: Vec<PluginRegistrar>, } /// Read plugin metadata and dynamically load registrar functions. pub fn load_plugins(sess: &Session, krate: &ast::Crate, - addl_plugins: Option<Vec<String>>) -> Plugins { + addl_plugins: Option<Vec<String>>) -> Vec<PluginRegistrar> { 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 item in &krate.module.items { - if let ast::ItemExternCrate(_) = item.node { - loader.span_whitelist.insert(item.span); - } - } - - visit::walk_crate(&mut loader, krate); - for attr in &krate.attrs { if !attr.check_name("plugin") { continue; @@ -112,140 +73,24 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, } } - return loader.plugins; -} - -pub type MacroSelection = HashMap<token::InternedString, Span>; - -// note that macros aren't expanded yet, and therefore macros can't add plugins. -impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { - fn visit_item(&mut self, item: &ast::Item) { - // We're only interested in `extern crate`. - match item.node { - ast::ItemExternCrate(_) => {} - _ => { - visit::walk_item(self, item); - return; - } - } - - // Parse the attributes relating to macro loading. - let mut import = Some(HashMap::new()); // None => load all - let mut reexport = HashMap::new(); - for attr in &item.attrs { - let mut used = true; - match &attr.name()[] { - "phase" => { - self.sess.span_err(attr.span, "#[phase] is deprecated"); - } - "plugin" => { - self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated"); - self.sess.span_help(attr.span, &format!("use a crate attribute instead, \ - i.e. #![plugin({})]", - item.ident.as_str())[]); - } - "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 let ast::MetaWord(ref name) = attr.node { - sel.insert(name.clone(), attr.span); - } else { - self.sess.span_err(attr.span, "bad macro import"); - } - } - } - } - "macro_reexport" => { - let names = match attr.meta_item_list() { - Some(names) => names, - None => { - self.sess.span_err(attr.span, "bad macro reexport"); - continue; - } - }; - - for attr in names { - if let ast::MetaWord(ref name) = attr.node { - reexport.insert(name.clone(), attr.span); - } else { - self.sess.span_err(attr.span, "bad macro reexport"); - } - } - } - _ => used = false, - } - if used { - attr::mark_used(attr); - } - } - - self.load_macros(item, import, reexport) - } - - fn visit_mac(&mut self, _: &ast::Mac) { - // bummer... can't see plugins inside macros. - // do nothing. - } + loader.plugins } impl<'a> PluginLoader<'a> { - pub fn load_macros<'b>(&mut self, - vi: &ast::Item, - import: Option<MacroSelection>, - reexport: MacroSelection) { - if let Some(sel) = import.as_ref() { - if sel.is_empty() && reexport.is_empty() { - return; - } - } - - if !self.span_whitelist.contains(&vi.span) { - self.sess.span_err(vi.span, "an `extern crate` loading macros must be at \ - the crate root"); - return; - } - - let macros = self.reader.read_exported_macros(vi); - let mut seen = HashSet::new(); - - for mut def in macros { - let name = token::get_ident(def.ident); - seen.insert(name.clone()); - - def.use_locally = match import.as_ref() { - None => true, - Some(sel) => sel.contains_key(&name), - }; - def.export = reexport.contains_key(&name); - self.plugins.macros.push(def); - } - - if let Some(sel) = import.as_ref() { - for (name, span) in sel.iter() { - if !seen.contains(name) { - self.sess.span_err(*span, "imported macro not found"); - } - } - } - - for (name, span) in reexport.iter() { - if !seen.contains(name) { - self.sess.span_err(*span, "reexported macro not found"); - } + fn new(sess: &'a Session) -> PluginLoader<'a> { + PluginLoader { + sess: sess, + reader: CrateReader::new(sess), + plugins: vec![], } } - pub fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) { + fn load_plugin(&mut self, span: Span, name: &str, args: Vec<P<ast::MetaItem>>) { let registrar = self.reader.find_plugin_registrar(span, name); if let Some((lib, symbol)) = registrar { let fun = self.dylink_registrar(span, lib, symbol); - self.plugins.registrars.push(PluginRegistrar { + self.plugins.push(PluginRegistrar { fun: fun, args: args, }); |
