diff options
| author | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-06 13:56:38 -0800 |
|---|---|---|
| committer | Keegan McAllister <kmcallister@mozilla.com> | 2015-02-09 13:27:27 -0800 |
| commit | 93b642d9743edea728ef08b2d6fd17229caaad43 (patch) | |
| tree | b88ec4e6fac283b95735e7c34dac6760e53a2874 /src/librustc/plugin | |
| parent | 0ba9e1fa52627404a1e5b90f745f96a872a0c564 (diff) | |
| download | rust-93b642d9743edea728ef08b2d6fd17229caaad43.tar.gz rust-93b642d9743edea728ef08b2d6fd17229caaad43.zip | |
Use a crate attribute to load plugins
#[plugin] #[no_link] extern crate bleh;
becomes a crate attribute
#![plugin(bleh)]
The feature gate is still required.
It's almost never correct to link a plugin into the resulting library /
executable, because it will bring all of libsyntax and librustc with it.
However if you really want this behavior, you can get it with a separate
`extern crate` item in addition to the `plugin` attribute.
Fixes #21043.
Fixes #20769.
[breaking-change]
Diffstat (limited to 'src/librustc/plugin')
| -rw-r--r-- | src/librustc/plugin/load.rs | 97 | ||||
| -rw-r--r-- | src/librustc/plugin/mod.rs | 7 | ||||
| -rw-r--r-- | src/librustc/plugin/registry.rs | 13 |
3 files changed, 64 insertions, 53 deletions
diff --git a/src/librustc/plugin/load.rs b/src/librustc/plugin/load.rs index 1a15e169d6a..08f5486fd38 100644 --- a/src/librustc/plugin/load.rs +++ b/src/librustc/plugin/load.rs @@ -18,9 +18,10 @@ use std::mem; use std::env; use std::dynamic_lib::DynamicLibrary; use std::collections::HashSet; +use std::borrow::ToOwned; use syntax::ast; use syntax::attr; -use syntax::codemap::Span; +use syntax::codemap::{Span, COMMAND_LINE_SP}; use syntax::parse::token; use syntax::ptr::P; use syntax::visit; @@ -33,7 +34,7 @@ pub type PluginRegistrarFun = pub struct PluginRegistrar { pub fun: PluginRegistrarFun, - pub args: P<ast::MetaItem>, + pub args: Vec<P<ast::MetaItem>>, } /// Information about loaded plugins. @@ -81,10 +82,34 @@ pub fn load_plugins(sess: &Session, krate: &ast::Crate, visit::walk_crate(&mut loader, krate); + for attr in &krate.attrs { + if !attr.check_name("plugin") { + continue; + } + + let plugins = match attr.meta_item_list() { + Some(xs) => xs, + None => { + sess.span_err(attr.span, "malformed plugin attribute"); + continue; + } + }; + + for plugin in plugins { + if plugin.value_str().is_some() { + sess.span_err(attr.span, "malformed plugin attribute"); + continue; + } + + let args = plugin.meta_item_list().map(ToOwned::to_owned).unwrap_or_default(); + loader.load_plugin(CrateOrString::Str(plugin.span, &*plugin.name()), + args); + } + } + if let Some(plugins) = addl_plugins { for plugin in plugins { - loader.load_plugin(CrateOrString::Str(&plugin), - None, None, None) + loader.load_plugin(CrateOrString::Str(COMMAND_LINE_SP, &plugin), vec![]); } } @@ -104,21 +129,16 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } // 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 &item.attrs { let mut used = true; match &attr.name()[] { "phase" => { - self.sess.span_err(attr.span, "#[phase] is deprecated; use \ - #[macro_use], #[plugin], and/or #[no_link]"); + self.sess.span_err(attr.span, "#[phase] is deprecated"); } "plugin" => { - if plugin_attr.is_some() { - self.sess.span_err(attr.span, "#[plugin] specified multiple times"); - } - plugin_attr = Some(attr.node.value.clone()); + self.sess.span_err(attr.span, "#[plugin] on `extern crate` is deprecated"); } "macro_use" => { let names = attr.meta_item_list(); @@ -160,10 +180,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } } - self.load_plugin(CrateOrString::Krate(item), - plugin_attr, - macro_selection, - Some(reexport)) + self.load_macros(item, macro_selection, Some(reexport)) } fn visit_mac(&mut self, _: &ast::Mac) { @@ -173,38 +190,25 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> { } impl<'a> PluginLoader<'a> { - pub fn load_plugin<'b>(&mut self, - c: CrateOrString<'b>, - plugin_attr: Option<P<ast::MetaItem>>, + pub fn load_macros<'b>(&mut self, + vi: &ast::Item, 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(), reexport.as_ref()) { - (Some(sel), Some(re)) => sel.len() != 0 || re.len() != 0, - _ => true, - }; - let load_registrar = plugin_attr.is_some(); - - 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 let (Some(sel), Some(re)) = (macro_selection.as_ref(), reexport.as_ref()) { + if sel.is_empty() && re.is_empty() { + return; } - } + } - if load_macros || load_registrar { - let pmd = self.reader.read_plugin_metadata(c); - if load_macros { - macros = pmd.exported_macros(); - } - if load_registrar { - registrar = pmd.plugin_registrar(); - } + 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; } - for mut def in macros { + let pmd = self.reader.read_plugin_metadata(CrateOrString::Krate(vi)); + + for mut def in pmd.exported_macros() { let name = token::get_ident(def.ident); def.use_locally = match macro_selection.as_ref() { None => true, @@ -217,12 +221,21 @@ impl<'a> PluginLoader<'a> { }; self.plugins.macros.push(def); } + } + + pub fn load_plugin<'b>(&mut self, + c: CrateOrString<'b>, + args: Vec<P<ast::MetaItem>>) { + let registrar = { + let pmd = self.reader.read_plugin_metadata(c); + pmd.plugin_registrar() + }; if let Some((lib, symbol)) = registrar { let fun = self.dylink_registrar(c, lib, symbol); self.plugins.registrars.push(PluginRegistrar { fun: fun, - args: plugin_attr.unwrap(), + args: args, }); } } diff --git a/src/librustc/plugin/mod.rs b/src/librustc/plugin/mod.rs index fd8873454b4..711ed43fe06 100644 --- a/src/librustc/plugin/mod.rs +++ b/src/librustc/plugin/mod.rs @@ -44,14 +44,9 @@ //! //! ```rust //! #![feature(plugin)] -//! -//! #[plugin] -//! extern crate myplugin; +//! #![plugin(myplugin)] //! ``` //! -//! If you don't need the plugin crate available at runtime, use -//! `#[no_link]` as well. -//! //! See [the compiler plugin guide](../../guide-plugin.html) //! for more examples. diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs index f6fb1c2d419..12634204f8b 100644 --- a/src/librustc/plugin/registry.rs +++ b/src/librustc/plugin/registry.rs @@ -37,7 +37,7 @@ pub struct Registry<'a> { pub sess: &'a Session, #[doc(hidden)] - pub args_hidden: Option<P<ast::MetaItem>>, + pub args_hidden: Option<Vec<P<ast::MetaItem>>>, #[doc(hidden)] pub krate_span: Span, @@ -65,11 +65,14 @@ impl<'a> Registry<'a> { } } - /// Get the `#[plugin]` attribute used to load this plugin. + /// Get the plugin's arguments, if any. /// - /// This gives access to arguments passed via `#[plugin=...]` or - /// `#[plugin(...)]`. - pub fn args<'b>(&'b self) -> &'b P<ast::MetaItem> { + /// These are specified inside the `plugin` crate attribute as + /// + /// ```no_run + /// #![plugin(my_plugin_name(... args ...))] + /// ``` + pub fn args<'b>(&'b self) -> &'b Vec<P<ast::MetaItem>> { self.args_hidden.as_ref().expect("args not set") } |
