Skip to content

Commit d0163d3

Browse files
author
Keegan McAllister
committed
Pass the #[plugin(...)] meta item to the registrar
1 parent 416137e commit d0163d3

File tree

9 files changed

+195
-10
lines changed

9 files changed

+195
-10
lines changed

src/librustc/plugin/load.rs

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use std::collections::HashSet;
2121
use syntax::ast;
2222
use syntax::attr;
2323
use syntax::parse::token;
24+
use syntax::ptr::P;
2425
use syntax::visit;
2526
use syntax::visit::Visitor;
2627
use syntax::attr::AttrMetaMethods;
@@ -29,12 +30,17 @@ use syntax::attr::AttrMetaMethods;
2930
pub type PluginRegistrarFun =
3031
fn(&mut Registry);
3132

33+
pub struct PluginRegistrar {
34+
pub fun: PluginRegistrarFun,
35+
pub args: P<ast::MetaItem>,
36+
}
37+
3238
/// Information about loaded plugins.
3339
pub struct Plugins {
3440
/// Imported macros.
3541
pub macros: Vec<ast::MacroDef>,
3642
/// Registrars, as function pointers.
37-
pub registrars: Vec<PluginRegistrarFun>,
43+
pub registrars: Vec<PluginRegistrar>,
3844
}
3945

4046
struct PluginLoader<'a> {
@@ -87,7 +93,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
8793
}
8894

8995
// Parse the attributes relating to macro / plugin loading.
90-
let mut load_registrar = false;
96+
let mut plugin_attr = None;
9197
let mut macro_selection = Some(HashSet::new()); // None => load all
9298
let mut reexport = HashSet::new();
9399
for attr in vi.attrs.iter() {
@@ -97,7 +103,12 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
97103
self.sess.span_err(attr.span, "#[phase] is deprecated; use \
98104
#[macro_use], #[plugin], and/or #[no_link]");
99105
}
100-
"plugin" => load_registrar = true,
106+
"plugin" => {
107+
if plugin_attr.is_some() {
108+
self.sess.span_err(attr.span, "#[plugin] specified multiple times");
109+
}
110+
plugin_attr = Some(attr.node.value.clone());
111+
}
101112
"macro_use" => {
102113
let names = attr.meta_item_list();
103114
if names.is_none() {
@@ -145,6 +156,7 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
145156
Some(sel) => sel.len() != 0 || reexport.len() != 0,
146157
None => true,
147158
};
159+
let load_registrar = plugin_attr.is_some();
148160

149161
if load_macros || load_registrar {
150162
let pmd = self.reader.read_plugin_metadata(vi);
@@ -167,7 +179,11 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
167179
}
168180

169181
if let Some((lib, symbol)) = registrar {
170-
self.dylink_registrar(vi, lib, symbol);
182+
let fun = self.dylink_registrar(vi, lib, symbol);
183+
self.plugins.registrars.push(PluginRegistrar {
184+
fun: fun,
185+
args: plugin_attr.unwrap(),
186+
});
171187
}
172188
}
173189

@@ -179,7 +195,10 @@ impl<'a, 'v> Visitor<'v> for PluginLoader<'a> {
179195

180196
impl<'a> PluginLoader<'a> {
181197
// Dynamically link a registrar function into the compiler process.
182-
fn dylink_registrar(&mut self, vi: &ast::ViewItem, path: Path, symbol: String) {
198+
fn dylink_registrar(&mut self,
199+
vi: &ast::ViewItem,
200+
path: Path,
201+
symbol: String) -> PluginRegistrarFun {
183202
// Make sure the path contains a / or the linker will search for it.
184203
let path = os::make_absolute(&path).unwrap();
185204

@@ -201,13 +220,12 @@ impl<'a> PluginLoader<'a> {
201220
Err(err) => self.sess.span_fatal(vi.span, err[])
202221
};
203222

204-
self.plugins.registrars.push(registrar);
205-
206223
// Intentionally leak the dynamic library. We can't ever unload it
207224
// since the library can make things that will live arbitrarily long
208225
// (e.g. an @-box cycle or a task).
209226
mem::forget(lib);
210227

228+
registrar
211229
}
212230
}
213231
}

src/librustc/plugin/registry.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use syntax::ext::base::{IdentTT, Decorator, Modifier, MacroRulesTT};
1818
use syntax::ext::base::{MacroExpanderFn};
1919
use syntax::codemap::Span;
2020
use syntax::parse::token;
21+
use syntax::ptr::P;
2122
use syntax::ast;
2223

2324
use std::collections::HashMap;
@@ -35,6 +36,9 @@ pub struct Registry<'a> {
3536
/// from the plugin registrar.
3637
pub sess: &'a Session,
3738

39+
#[doc(hidden)]
40+
pub args_hidden: Option<P<ast::MetaItem>>,
41+
3842
#[doc(hidden)]
3943
pub krate_span: Span,
4044

@@ -53,13 +57,22 @@ impl<'a> Registry<'a> {
5357
pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
5458
Registry {
5559
sess: sess,
60+
args_hidden: None,
5661
krate_span: krate.span,
5762
syntax_exts: vec!(),
5863
lint_passes: vec!(),
5964
lint_groups: HashMap::new(),
6065
}
6166
}
6267

68+
/// Get the `#[plugin]` attribute used to load this plugin.
69+
///
70+
/// This gives access to arguments passed via `#[plugin=...]` or
71+
/// `#[plugin(...)]`.
72+
pub fn args<'b>(&'b self) -> &'b P<ast::MetaItem> {
73+
self.args_hidden.as_ref().expect("args not set")
74+
}
75+
6376
/// Register a syntax extension of any kind.
6477
///
6578
/// This is the most general hook into `libsyntax`'s expansion behavior.

src/librustc_driver/driver.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -218,7 +218,7 @@ pub fn phase_2_configure_and_expand(sess: &Session,
218218

219219
let mut registry = Registry::new(sess, &krate);
220220

221-
time(time_passes, "plugin registration", (), |_| {
221+
time(time_passes, "plugin registration", registrars, |registrars| {
222222
if sess.features.borrow().rustc_diagnostic_macros {
223223
registry.register_macro("__diagnostic_used",
224224
diagnostics::plugin::expand_diagnostic_used);
@@ -228,8 +228,9 @@ pub fn phase_2_configure_and_expand(sess: &Session,
228228
diagnostics::plugin::expand_build_diagnostic_array);
229229
}
230230

231-
for &registrar in registrars.iter() {
232-
registrar(&mut registry);
231+
for registrar in registrars.into_iter() {
232+
registry.args_hidden = Some(registrar.args);
233+
(registrar.fun)(&mut registry);
233234
}
234235
});
235236

src/test/auxiliary/plugin_args.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// force-host
12+
13+
#![feature(plugin_registrar)]
14+
15+
extern crate syntax;
16+
extern crate rustc;
17+
18+
use std::borrow::ToOwned;
19+
use syntax::ast;
20+
use syntax::codemap::Span;
21+
use syntax::ext::build::AstBuilder;
22+
use syntax::ext::base::{TTMacroExpander, ExtCtxt, MacResult, MacExpr, NormalTT};
23+
use syntax::parse::token;
24+
use syntax::print::pprust;
25+
use syntax::ptr::P;
26+
use rustc::plugin::Registry;
27+
28+
struct Expander {
29+
args: P<ast::MetaItem>,
30+
}
31+
32+
impl TTMacroExpander for Expander {
33+
fn expand<'cx>(&self,
34+
ecx: &'cx mut ExtCtxt,
35+
sp: Span,
36+
_: &[ast::TokenTree]) -> Box<MacResult+'cx> {
37+
38+
let attr = ecx.attribute(sp, self.args.clone());
39+
let src = pprust::attribute_to_string(&attr);
40+
let interned = token::intern_and_get_ident(src.as_slice());
41+
MacExpr::new(ecx.expr_str(sp, interned))
42+
}
43+
}
44+
45+
#[plugin_registrar]
46+
pub fn plugin_registrar(reg: &mut Registry) {
47+
let args = reg.args().clone();
48+
reg.register_syntax_extension(token::intern("plugin_args"),
49+
NormalTT(box Expander { args: args, }, None));
50+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
#[plugin]
12+
#[plugin] //~ ERROR #[plugin] specified multiple times
13+
extern crate std;
14+
15+
fn main() {}

src/test/run-pass/plugin-args-1.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:plugin_args.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin)]
15+
16+
#[no_link]
17+
#[plugin]
18+
extern crate plugin_args;
19+
20+
fn main() {
21+
assert_eq!(plugin_args!(), "#[plugin]");
22+
}

src/test/run-pass/plugin-args-2.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:plugin_args.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin)]
15+
16+
#[no_link]
17+
#[plugin()]
18+
extern crate plugin_args;
19+
20+
fn main() {
21+
assert_eq!(plugin_args!(), "#[plugin()]");
22+
}

src/test/run-pass/plugin-args-3.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:plugin_args.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin)]
15+
16+
#[no_link]
17+
#[plugin(hello(there), how(are="you"))]
18+
extern crate plugin_args;
19+
20+
fn main() {
21+
assert_eq!(plugin_args!(), "#[plugin(hello(there), how(are = \"you\"))]");
22+
}

src/test/run-pass/plugin-args-4.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
2+
// file at the top-level directory of this distribution and at
3+
// http://rust-lang.org/COPYRIGHT.
4+
//
5+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
6+
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
7+
// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
8+
// option. This file may not be copied, modified, or distributed
9+
// except according to those terms.
10+
11+
// aux-build:plugin_args.rs
12+
// ignore-stage1
13+
14+
#![feature(plugin)]
15+
16+
#[no_link]
17+
#[plugin="foobar"]
18+
extern crate plugin_args;
19+
20+
fn main() {
21+
assert_eq!(plugin_args!(), "#[plugin = \"foobar\"]");
22+
}

0 commit comments

Comments
 (0)