about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2015-02-06 13:56:38 -0800
committerKeegan McAllister <kmcallister@mozilla.com>2015-02-09 13:27:27 -0800
commit93b642d9743edea728ef08b2d6fd17229caaad43 (patch)
treeb88ec4e6fac283b95735e7c34dac6760e53a2874 /src
parent0ba9e1fa52627404a1e5b90f745f96a872a0c564 (diff)
downloadrust-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')
-rw-r--r--src/doc/reference.md16
-rw-r--r--src/doc/trpl/plugins.md15
-rw-r--r--src/librustc/metadata/creader.rs8
-rw-r--r--src/librustc/plugin/load.rs97
-rw-r--r--src/librustc/plugin/mod.rs7
-rw-r--r--src/librustc/plugin/registry.rs13
-rw-r--r--src/librustc_driver/lib.rs1
-rw-r--r--src/libsyntax/feature_gate.rs10
-rw-r--r--src/test/auxiliary/plugin_args.rs9
-rw-r--r--src/test/auxiliary/syntax_extension_with_dll_deps_1.rs (renamed from src/test/auxiliary/syntax-extension-with-dll-deps-1.rs)0
-rw-r--r--src/test/auxiliary/syntax_extension_with_dll_deps_2.rs (renamed from src/test/auxiliary/syntax-extension-with-dll-deps-2.rs)2
-rw-r--r--src/test/compile-fail-fulldeps/gated-plugin.rs2
-rw-r--r--src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs4
-rw-r--r--src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs4
-rw-r--r--src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs4
-rw-r--r--src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs4
-rw-r--r--src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs4
-rw-r--r--src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs4
-rw-r--r--src/test/compile-fail-fulldeps/macro-crate-rlib.rs2
-rw-r--r--src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs4
-rw-r--r--src/test/compile-fail/malformed-plugin-1.rs (renamed from src/test/run-pass-fulldeps/plugin-args-4.rs)13
-rw-r--r--src/test/compile-fail/malformed-plugin-2.rs13
-rw-r--r--src/test/compile-fail/malformed-plugin-3.rs13
-rw-r--r--src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs (renamed from src/test/compile-fail/multi-plugin-attr.rs)3
-rw-r--r--src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs3
-rw-r--r--src/test/run-pass-fulldeps/lint-group-plugin.rs4
-rw-r--r--src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs4
-rw-r--r--src/test/run-pass-fulldeps/lint-plugin.rs4
-rw-r--r--src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs4
-rw-r--r--src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs4
-rw-r--r--src/test/run-pass-fulldeps/macro-crate.rs3
-rw-r--r--src/test/run-pass-fulldeps/plugin-args-1.rs7
-rw-r--r--src/test/run-pass-fulldeps/plugin-args-2.rs7
-rw-r--r--src/test/run-pass-fulldeps/plugin-args-3.rs7
-rw-r--r--src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs (renamed from src/test/run-pass-fulldeps/plugin-link-does-resolve.rs)4
-rw-r--r--src/test/run-pass-fulldeps/roman-numerals-macro.rs4
-rw-r--r--src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs8
37 files changed, 151 insertions, 164 deletions
diff --git a/src/doc/reference.md b/src/doc/reference.md
index 9c8191a386d..999efc95c0e 100644
--- a/src/doc/reference.md
+++ b/src/doc/reference.md
@@ -2014,6 +2014,11 @@ type int8_t = i8;
 - `no_start` - disable linking to the `native` crate, which specifies the
   "start" language item.
 - `no_std` - disable linking to the `std` crate.
+- `plugin` — load a list of named crates as compiler plugins, e.g.
+             `#![plugin(foo, bar)]`. Optional arguments for each plugin,
+             i.e. `#![plugin(foo(... args ...))]`, are provided to the plugin's
+             registrar function.  The `plugin` feature gate is required to use
+             this attribute.
 
 ### Module-only attributes
 
@@ -2082,7 +2087,7 @@ On `struct`s:
   remove any padding between fields (note that this is very fragile and may
   break platforms which require aligned access).
 
-### Macro- and plugin-related attributes
+### Macro-related attributes
 
 - `macro_use` on a `mod` — macros defined in this module will be visible in the
   module's parent, after this module has been included.
@@ -2097,13 +2102,8 @@ On `struct`s:
 
 - `macro_export` - export a macro for cross-crate usage.
 
-- `plugin` on an `extern crate` — load this crate as a [compiler
-  plugin][plugin].  The `plugin` feature gate is required.  Any arguments to
-  the attribute, e.g. `#[plugin=...]` or `#[plugin(...)]`, are provided to the
-  plugin.
-
-- `no_link` on an `extern crate` — even if we load this crate for macros or
-  compiler plugins, don't link it into the output.
+- `no_link` on an `extern crate` — even if we load this crate for macros, don't
+  link it into the output.
 
 See the [macros section of the
 book](book/macros.html#scoping-and-macro-import/export) for more information on
diff --git a/src/doc/trpl/plugins.md b/src/doc/trpl/plugins.md
index 5ff233b4844..3dea1a66ffd 100644
--- a/src/doc/trpl/plugins.md
+++ b/src/doc/trpl/plugins.md
@@ -30,14 +30,14 @@ information.
 extend the compiler's behavior with new syntax extensions, lint checks, etc.
 
 A plugin is a dynamic library crate with a designated *registrar* function that
-registers extensions with `rustc`. Other crates can use these extensions by
-loading the plugin crate with `#[plugin] extern crate`. See the
+registers extensions with `rustc`. Other crates can load these extensions using
+the crate attribute `#![plugin(...)]`.  See the
 [`rustc::plugin`](../rustc/plugin/index.html) documentation for more about the
 mechanics of defining and loading a plugin.
 
-Arguments passed as `#[plugin=...]` or `#[plugin(...)]` are not interpreted by
-rustc itself.  They are provided to the plugin through the `Registry`'s [`args`
-method](../rustc/plugin/registry/struct.Registry.html#method.args).
+If present, arguments passed as `#![plugin(foo(... args ...))]` are not
+interpreted by rustc itself.  They are provided to the plugin through the
+`Registry`'s [`args` method](../rustc/plugin/registry/struct.Registry.html#method.args).
 
 # Syntax extensions
 
@@ -110,8 +110,7 @@ Then we can use `rn!()` like any other macro:
 
 ```ignore
 #![feature(plugin)]
-
-#[plugin] extern crate roman_numerals;
+#![plugin(roman_numerals)]
 
 fn main() {
     assert_eq!(rn!(MMXV), 2015);
@@ -219,7 +218,7 @@ pub fn plugin_registrar(reg: &mut Registry) {
 Then code like
 
 ```ignore
-#[plugin] extern crate lint_plugin_test;
+#![plugin(lint_plugin_test)]
 
 fn lintme() { }
 ```
diff --git a/src/librustc/metadata/creader.rs b/src/librustc/metadata/creader.rs
index d28b3afec79..f6cd0e5add2 100644
--- a/src/librustc/metadata/creader.rs
+++ b/src/librustc/metadata/creader.rs
@@ -26,7 +26,7 @@ use syntax::ast;
 use syntax::abi;
 use syntax::attr;
 use syntax::attr::AttrMetaMethods;
-use syntax::codemap::{COMMAND_LINE_SP, Span, mk_sp};
+use syntax::codemap::{Span, mk_sp};
 use syntax::parse;
 use syntax::parse::token::InternedString;
 use syntax::parse::token;
@@ -457,13 +457,13 @@ impl<'a> CrateReader<'a> {
             CrateOrString::Krate(c) => {
                 (self.extract_crate_info(c).unwrap(), c.span)
             }
-            CrateOrString::Str(s) => {
+            CrateOrString::Str(sp, s) => {
                 (CrateInfo {
                      name: s.to_string(),
                      ident: s.to_string(),
                      id: ast::DUMMY_NODE_ID,
                      should_link: true,
-                 }, COMMAND_LINE_SP)
+                 }, sp)
             }
         };
         let target_triple = &self.sess.opts.target_triple[];
@@ -531,7 +531,7 @@ impl<'a> CrateReader<'a> {
 #[derive(Copy)]
 pub enum CrateOrString<'a> {
     Krate(&'a ast::Item),
-    Str(&'a str)
+    Str(Span, &'a str)
 }
 
 impl<'a> PluginMetadata<'a> {
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")
     }
 
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 9193debbe42..7f8bc3a3ad7 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -69,7 +69,6 @@ use rustc::session::config::{Input, PrintRequest, UnstableFeatures};
 use rustc::lint::Lint;
 use rustc::lint;
 use rustc::metadata;
-use rustc::metadata::creader::CrateOrString::Str;
 use rustc::util::common::time;
 
 use std::cmp::Ordering::Equal;
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index c8ab46ff8fd..72bbe1adfaa 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -284,11 +284,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
         }
         match i.node {
             ast::ItemExternCrate(_) => {
-                if attr::contains_name(&i.attrs[], "plugin") {
-                    self.gate_feature("plugin", i.span,
-                                      "compiler plugins are experimental \
-                                       and possibly buggy");
-                } else if attr::contains_name(&i.attrs[], "macro_reexport") {
+                if attr::contains_name(&i.attrs[], "macro_reexport") {
                     self.gate_feature("macro_reexport", i.span,
                                       "macros reexports are experimental \
                                        and possibly buggy");
@@ -462,6 +458,10 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
         if attr.check_name("staged_api") {
             self.gate_feature("staged_api", attr.span,
                               "staged_api is for use by rustc only");
+        } else if attr.check_name("plugin") {
+            self.gate_feature("plugin", attr.span,
+                              "compiler plugins are experimental \
+                               and possibly buggy");
         }
 
         if attr::contains_name(slice::ref_slice(attr), "lang") {
diff --git a/src/test/auxiliary/plugin_args.rs b/src/test/auxiliary/plugin_args.rs
index 6779cf997c1..907d80b50db 100644
--- a/src/test/auxiliary/plugin_args.rs
+++ b/src/test/auxiliary/plugin_args.rs
@@ -27,7 +27,7 @@ use syntax::ptr::P;
 use rustc::plugin::Registry;
 
 struct Expander {
-    args: P<ast::MetaItem>,
+    args: Vec<P<ast::MetaItem>>,
 }
 
 impl TTMacroExpander for Expander {
@@ -35,10 +35,9 @@ impl TTMacroExpander for Expander {
                    ecx: &'cx mut ExtCtxt,
                    sp: Span,
                    _: &[ast::TokenTree]) -> Box<MacResult+'cx> {
-
-        let attr = ecx.attribute(sp, self.args.clone());
-        let src = pprust::attribute_to_string(&attr);
-        let interned = token::intern_and_get_ident(&src);
+        let args = self.args.iter().map(|i| pprust::meta_item_to_string(&*i))
+            .collect::<Vec<_>>().connect(", ");
+        let interned = token::intern_and_get_ident(&args[]);
         MacExpr::new(ecx.expr_str(sp, interned))
     }
 }
diff --git a/src/test/auxiliary/syntax-extension-with-dll-deps-1.rs b/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs
index 338e04fbb07..338e04fbb07 100644
--- a/src/test/auxiliary/syntax-extension-with-dll-deps-1.rs
+++ b/src/test/auxiliary/syntax_extension_with_dll_deps_1.rs
diff --git a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs b/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs
index 5ad1d244c92..7a24dd76f32 100644
--- a/src/test/auxiliary/syntax-extension-with-dll-deps-2.rs
+++ b/src/test/auxiliary/syntax_extension_with_dll_deps_2.rs
@@ -13,7 +13,7 @@
 #![crate_type = "dylib"]
 #![feature(plugin_registrar, quote)]
 
-extern crate "syntax-extension-with-dll-deps-1" as other;
+extern crate "syntax_extension_with_dll_deps_1" as other;
 extern crate syntax;
 extern crate rustc;
 
diff --git a/src/test/compile-fail-fulldeps/gated-plugin.rs b/src/test/compile-fail-fulldeps/gated-plugin.rs
index be9e57e2d19..9fa93063ea3 100644
--- a/src/test/compile-fail-fulldeps/gated-plugin.rs
+++ b/src/test/compile-fail-fulldeps/gated-plugin.rs
@@ -11,7 +11,7 @@
 // aux-build:macro_crate_test.rs
 // ignore-stage1
 
-#[plugin] #[no_link] extern crate macro_crate_test;
+#![plugin(macro_crate_test)]
 //~^ ERROR compiler plugins are experimental and possibly buggy
 
 fn main() {}
diff --git a/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs b/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs
index 11ae5563959..a523799278c 100644
--- a/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs
+++ b/src/test/compile-fail-fulldeps/lint-group-plugin-deny-cmdline.rs
@@ -13,9 +13,7 @@
 // compile-flags: -D lint-me
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_group_plugin_test;
+#![plugin(lint_group_plugin_test)]
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs b/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs
index 62007d6575a..e3dbdc331a7 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-deny-attr.rs
@@ -12,11 +12,9 @@
 // ignore-stage1
 
 #![feature(plugin)]
+#![plugin(lint_plugin_test)]
 #![deny(test_lint)]
 
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
-
 fn lintme() { } //~ ERROR item is named 'lintme'
 
 pub fn main() {
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs b/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs
index da51c047f57..41d25becd84 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-deny-cmdline.rs
@@ -13,9 +13,7 @@
 // compile-flags: -D test-lint
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
+#![plugin(lint_plugin_test)]
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
index cf51958b53d..83c845bfdf9 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-attrs.rs
@@ -12,11 +12,9 @@
 // ignore-stage1
 
 #![feature(plugin)]
+#![plugin(lint_plugin_test)]
 #![forbid(test_lint)]
 
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
-
 fn lintme() { } //~ ERROR item is named 'lintme'
 
 #[allow(test_lint)] //~ ERROR allow(test_lint) overruled by outer forbid(test_lint)
diff --git a/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs b/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs
index 9a36143f65c..155294f8026 100644
--- a/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs
+++ b/src/test/compile-fail-fulldeps/lint-plugin-forbid-cmdline.rs
@@ -13,9 +13,7 @@
 // compile-flags: -F test-lint
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
+#![plugin(lint_plugin_test)]
 
 fn lintme() { } //~ ERROR item is named 'lintme'
 
diff --git a/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs b/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs
index 2e727f19635..c9ca6e5326c 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-cannot-read-embedded-ident.rs
@@ -21,9 +21,7 @@
 // ident form.
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate macro_crate_test;
+#![plugin(macro_crate_test)]
 
 fn main() {
     let x = 0;
diff --git a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs
index 1f44ac7cf9c..7d38d4352b0 100644
--- a/src/test/compile-fail-fulldeps/macro-crate-rlib.rs
+++ b/src/test/compile-fail-fulldeps/macro-crate-rlib.rs
@@ -15,7 +15,7 @@
 // ignore-cross-compile gives a different error message
 
 #![feature(plugin)]
-#[plugin] #[no_link] extern crate rlib_crate_test;
+#![plugin(rlib_crate_test)]
 //~^ ERROR: plugin crate `rlib_crate_test` only found in rlib format, but must be available in dylib format
 
 fn main() {}
diff --git a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs
index cff2e5eaf87..68b27822d3d 100644
--- a/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs
+++ b/src/test/compile-fail-fulldeps/plugin-MacroRulesTT.rs
@@ -14,8 +14,6 @@
 // error-pattern: plugin tried to register a new MacroRulesTT
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate macro_crate_MacroRulesTT;
+#![plugin(macro_crate_MacroRulesTT)]
 
 fn main() { }
diff --git a/src/test/run-pass-fulldeps/plugin-args-4.rs b/src/test/compile-fail/malformed-plugin-1.rs
index 8563c8c178f..254a797ef1c 100644
--- a/src/test/run-pass-fulldeps/plugin-args-4.rs
+++ b/src/test/compile-fail/malformed-plugin-1.rs
@@ -8,15 +8,6 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:plugin_args.rs
-// ignore-stage1
+#![plugin] //~ ERROR malformed plugin attribute
 
-#![feature(plugin)]
-
-#[no_link]
-#[plugin="foobar"]
-extern crate plugin_args;
-
-fn main() {
-    assert_eq!(plugin_args!(), "#[plugin = \"foobar\"]");
-}
+fn main() {}
diff --git a/src/test/compile-fail/malformed-plugin-2.rs b/src/test/compile-fail/malformed-plugin-2.rs
new file mode 100644
index 00000000000..884087b7bc5
--- /dev/null
+++ b/src/test/compile-fail/malformed-plugin-2.rs
@@ -0,0 +1,13 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![plugin="bleh"] //~ ERROR malformed plugin attribute
+
+fn main() {}
diff --git a/src/test/compile-fail/malformed-plugin-3.rs b/src/test/compile-fail/malformed-plugin-3.rs
new file mode 100644
index 00000000000..4885bb901df
--- /dev/null
+++ b/src/test/compile-fail/malformed-plugin-3.rs
@@ -0,0 +1,13 @@
+// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
+// file at the top-level directory of this distribution and at
+// http://rust-lang.org/COPYRIGHT.
+//
+// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
+// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
+// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
+// option. This file may not be copied, modified, or distributed
+// except according to those terms.
+
+#![plugin(foo="bleh")] //~ ERROR malformed plugin attribute
+
+fn main() {}
diff --git a/src/test/compile-fail/multi-plugin-attr.rs b/src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs
index 1d98cd26a38..e27f193cbe8 100644
--- a/src/test/compile-fail/multi-plugin-attr.rs
+++ b/src/test/compile-fail/plugin-extern-crate-attr-deprecated.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-#[plugin]
-#[plugin]  //~ ERROR #[plugin] specified multiple times
+#[plugin]  //~ ERROR #[plugin] on `extern crate` is deprecated
 extern crate std;
 
 fn main() {}
diff --git a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs
index 11e7da77029..c59a3589c04 100644
--- a/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs
+++ b/src/test/run-pass-fulldeps/issue_16723_multiple_items_syntax_ext.rs
@@ -12,8 +12,7 @@
 // ignore-android
 // aux-build:issue_16723_multiple_items_syntax_ext.rs
 #![feature(plugin)]
-
-#[plugin] #[no_link] extern crate issue_16723_multiple_items_syntax_ext;
+#![plugin(issue_16723_multiple_items_syntax_ext)]
 
 multiple_items!();
 
diff --git a/src/test/run-pass-fulldeps/lint-group-plugin.rs b/src/test/run-pass-fulldeps/lint-group-plugin.rs
index 7615b25f9e4..1a639cdb9dd 100644
--- a/src/test/run-pass-fulldeps/lint-group-plugin.rs
+++ b/src/test/run-pass-fulldeps/lint-group-plugin.rs
@@ -13,9 +13,7 @@
 // ignore-pretty
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_group_plugin_test;
+#![plugin(lint_group_plugin_test)]
 
 fn lintme() { } //~ WARNING item is named 'lintme'
 fn pleaselintme() { } //~ WARNING item is named 'pleaselintme'
diff --git a/src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs b/src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs
index 7144d2b0f1e..204312064b5 100644
--- a/src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs
+++ b/src/test/run-pass-fulldeps/lint-plugin-cmdline-allow.rs
@@ -13,9 +13,7 @@
 // compile-flags: -A test-lint
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
+#![plugin(lint_plugin_test)]
 
 fn lintme() { }
 
diff --git a/src/test/run-pass-fulldeps/lint-plugin.rs b/src/test/run-pass-fulldeps/lint-plugin.rs
index d11242f4fe6..8311e188f92 100644
--- a/src/test/run-pass-fulldeps/lint-plugin.rs
+++ b/src/test/run-pass-fulldeps/lint-plugin.rs
@@ -13,9 +13,7 @@
 // ignore-pretty
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate lint_plugin_test;
+#![plugin(lint_plugin_test)]
 
 fn lintme() { } //~ WARNING item is named 'lintme'
 
diff --git a/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs b/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs
index 497afae6189..8ed47fe1f6f 100644
--- a/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs
+++ b/src/test/run-pass-fulldeps/macro-crate-does-hygiene-work.rs
@@ -15,9 +15,7 @@
 // uses `quote_expr!` to rearrange it should be hygiene-preserving.
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate macro_crate_test;
+#![plugin(macro_crate_test)]
 
 fn main() {
     let x = 3;
diff --git a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
index d943cf0457b..9573d0c8c40 100644
--- a/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
+++ b/src/test/run-pass-fulldeps/macro-crate-outlive-expansion-phase.rs
@@ -12,8 +12,6 @@
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate plugin_crate_outlive_expansion_phase;
+#![plugin(plugin_crate_outlive_expansion_phase)]
 
 pub fn main() {}
diff --git a/src/test/run-pass-fulldeps/macro-crate.rs b/src/test/run-pass-fulldeps/macro-crate.rs
index a9e93aa8df5..58ccd79b712 100644
--- a/src/test/run-pass-fulldeps/macro-crate.rs
+++ b/src/test/run-pass-fulldeps/macro-crate.rs
@@ -12,8 +12,9 @@
 // ignore-stage1
 
 #![feature(plugin)]
+#![plugin(macro_crate_test)]
 
-#[macro_use] #[plugin] #[no_link]
+#[macro_use] #[no_link]
 extern crate macro_crate_test;
 
 #[into_foo]
diff --git a/src/test/run-pass-fulldeps/plugin-args-1.rs b/src/test/run-pass-fulldeps/plugin-args-1.rs
index 5a91f603f96..4d4f9092bc8 100644
--- a/src/test/run-pass-fulldeps/plugin-args-1.rs
+++ b/src/test/run-pass-fulldeps/plugin-args-1.rs
@@ -12,11 +12,8 @@
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[no_link]
-#[plugin]
-extern crate plugin_args;
+#![plugin(plugin_args)]
 
 fn main() {
-    assert_eq!(plugin_args!(), "#[plugin]");
+    assert_eq!(plugin_args!(), "");
 }
diff --git a/src/test/run-pass-fulldeps/plugin-args-2.rs b/src/test/run-pass-fulldeps/plugin-args-2.rs
index d0ac22a5290..4da566aec42 100644
--- a/src/test/run-pass-fulldeps/plugin-args-2.rs
+++ b/src/test/run-pass-fulldeps/plugin-args-2.rs
@@ -12,11 +12,8 @@
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[no_link]
-#[plugin()]
-extern crate plugin_args;
+#![plugin(plugin_args())]
 
 fn main() {
-    assert_eq!(plugin_args!(), "#[plugin()]");
+    assert_eq!(plugin_args!(), "");
 }
diff --git a/src/test/run-pass-fulldeps/plugin-args-3.rs b/src/test/run-pass-fulldeps/plugin-args-3.rs
index 7cac8ac57e5..0a064933aec 100644
--- a/src/test/run-pass-fulldeps/plugin-args-3.rs
+++ b/src/test/run-pass-fulldeps/plugin-args-3.rs
@@ -12,11 +12,8 @@
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[no_link]
-#[plugin(hello(there), how(are="you"))]
-extern crate plugin_args;
+#![plugin(plugin_args(hello(there), how(are="you")))]
 
 fn main() {
-    assert_eq!(plugin_args!(), "#[plugin(hello(there), how(are = \"you\"))]");
+    assert_eq!(plugin_args!(), "hello(there), how(are = \"you\")");
 }
diff --git a/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs b/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
index 518d02e3d75..0c27dba9c62 100644
--- a/src/test/run-pass-fulldeps/plugin-link-does-resolve.rs
+++ b/src/test/run-pass-fulldeps/plugin-plus-extern-crate.rs
@@ -1,4 +1,4 @@
-// Copyright 2013-2014 The Rust Project Developers. See the COPYRIGHT
+// Copyright 2013-2015 The Rust Project Developers. See the COPYRIGHT
 // file at the top-level directory of this distribution and at
 // http://rust-lang.org/COPYRIGHT.
 //
@@ -16,8 +16,8 @@
 // libsyntax is not compiled for it.
 
 #![feature(plugin)]
+#![plugin(macro_crate_test)]
 
-#[plugin]
 extern crate macro_crate_test;
 
 fn main() {
diff --git a/src/test/run-pass-fulldeps/roman-numerals-macro.rs b/src/test/run-pass-fulldeps/roman-numerals-macro.rs
index d76766094ed..81f5c649626 100644
--- a/src/test/run-pass-fulldeps/roman-numerals-macro.rs
+++ b/src/test/run-pass-fulldeps/roman-numerals-macro.rs
@@ -12,9 +12,7 @@
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate roman_numerals;
+#![plugin(roman_numerals)]
 
 pub fn main() {
     assert_eq!(rn!(MMXV), 2015);
diff --git a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
index 1c74c8ad08e..b7570eb0926 100644
--- a/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
+++ b/src/test/run-pass-fulldeps/syntax-extension-with-dll-deps.rs
@@ -8,14 +8,12 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-// aux-build:syntax-extension-with-dll-deps-1.rs
-// aux-build:syntax-extension-with-dll-deps-2.rs
+// aux-build:syntax_extension_with_dll_deps_1.rs
+// aux-build:syntax_extension_with_dll_deps_2.rs
 // ignore-stage1
 
 #![feature(plugin)]
-
-#[plugin] #[no_link]
-extern crate "syntax-extension-with-dll-deps-2" as extension;
+#![plugin(syntax_extension_with_dll_deps_2)]
 
 fn main() {
     foo!();