about summary refs log tree commit diff
diff options
context:
space:
mode:
authorKeegan McAllister <kmcallister@mozilla.com>2014-06-18 17:26:14 -0700
committerKeegan McAllister <kmcallister@mozilla.com>2014-06-24 11:36:28 -0700
commit2f274d11ba48f0da6158f1da732645dc32bfe1f4 (patch)
tree116e81ef1996273fffea1e13301788360c6f8dc3
parent51d438e568dc128af47f4ac77ea1416c29b7402c (diff)
Implement lint plugins
-rw-r--r--src/librustc/driver/driver.rs14
-rw-r--r--src/librustc/driver/mod.rs23
-rw-r--r--src/librustc/lint/mod.rs1
-rw-r--r--src/librustc/plugin/registry.rs11
4 files changed, 39 insertions, 10 deletions
diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs
index 2fb8b2d4ac9..9a7be85bdd7 100644
--- a/src/librustc/driver/driver.rs
+++ b/src/librustc/driver/driver.rs
@@ -216,12 +216,18 @@ pub fn phase_2_configure_and_expand(sess: &Session,
         }
     });
 
-    let Registry { syntax_exts, .. } = registry;
+    let Registry { syntax_exts, lint_passes, .. } = registry;
 
-    // Process command line flags for lints.
-    // Do this here because we will have lint plugins eventually.
+    {
+        let mut ls = sess.lint_store.borrow_mut();
+        for pass in lint_passes.move_iter() {
+            ls.register_pass(Some(sess), true, pass);
+        }
+    }
+
+    // Lint plugins are registered; now we can process command line flags.
     if sess.opts.describe_lints {
-        super::describe_lints(&*sess.lint_store.borrow());
+        super::describe_lints(&*sess.lint_store.borrow(), true);
         return None;
     }
     sess.lint_store.borrow_mut().process_command_line(sess);
diff --git a/src/librustc/driver/mod.rs b/src/librustc/driver/mod.rs
index e8e057c926c..cfde4ad52af 100644
--- a/src/librustc/driver/mod.rs
+++ b/src/librustc/driver/mod.rs
@@ -56,7 +56,7 @@ fn run_compiler(args: &[String]) {
             if sopts.describe_lints {
                 let mut ls = lint::LintStore::new();
                 ls.register_builtin(None);
-                describe_lints(&ls);
+                describe_lints(&ls, false);
                 return;
             }
             early_error("no input filename given");
@@ -132,7 +132,7 @@ Additional help:
                              config::optgroups().as_slice()));
 }
 
-fn describe_lints(lint_store: &lint::LintStore) {
+fn describe_lints(lint_store: &lint::LintStore, loaded_plugins: bool) {
     println!("
 Available lint options:
     -W <foo>           Warn about <foo>
@@ -154,13 +154,13 @@ Available lint options:
         lints
     }
 
-    let (_plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
-    // let plugin = sort_lints(plugin);
+    let (plugin, builtin) = lint_store.get_lints().partitioned(|&(_, p)| p);
+    let plugin = sort_lints(plugin);
     let builtin = sort_lints(builtin);
 
     // FIXME (#7043): We should use the width in character cells rather than
     // the number of codepoints.
-    let max_name_len = builtin.iter()
+    let max_name_len = plugin.iter().chain(builtin.iter())
         .map(|&s| s.name.char_len())
         .max().unwrap_or(0);
     let padded = |x: &str| {
@@ -182,7 +182,18 @@ Available lint options:
 
     print_lints(builtin);
 
-    // Describe lint plugins here once they exist.
+    match (loaded_plugins, plugin.len()) {
+        (false, 0) => {
+            println!("Compiler plugins can provide additional lints. To see a listing of these, \
+                      re-run `rustc -W help` with a crate filename.");
+        }
+        (false, _) => fail!("didn't load lint plugins but got them anyway!"),
+        (true, 0) => println!("This crate does not load any lint plugins."),
+        (true, _) => {
+            println!("Lint checks provided by plugins loaded by this crate:\n");
+            print_lints(plugin);
+        }
+    }
 }
 
 fn describe_debug_flags() {
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index 13106973c1d..5aa10b5ab8e 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -19,6 +19,7 @@
 //! Most lints can be written as `LintPass` instances. These run just before
 //! translation to LLVM bytecode. The `LintPass`es built into rustc are defined
 //! within `builtin.rs`, which has further comments on how to add such a lint.
+//! rustc can also load user-defined lint plugins via the plugin mechanism.
 //!
 //! Some of rustc's lints are defined elsewhere in the compiler and work by
 //! calling `add_lint()` on the overall `Session` object. This works when
diff --git a/src/librustc/plugin/registry.rs b/src/librustc/plugin/registry.rs
index f6e37822325..587bedd502e 100644
--- a/src/librustc/plugin/registry.rs
+++ b/src/librustc/plugin/registry.rs
@@ -10,6 +10,8 @@
 
 //! Used by plugin crates to tell `rustc` about the plugins they provide.
 
+use lint::LintPassObject;
+
 use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
 use syntax::ext::base::{IdentTT, ItemDecorator, ItemModifier, BasicMacroExpander};
 use syntax::ext::base::{MacroExpanderFn};
@@ -31,6 +33,9 @@ pub struct Registry {
 
     #[doc(hidden)]
     pub syntax_exts: Vec<NamedSyntaxExtension>,
+
+    #[doc(hidden)]
+    pub lint_passes: Vec<LintPassObject>,
 }
 
 impl Registry {
@@ -39,6 +44,7 @@ impl Registry {
         Registry {
             krate_span: krate.span,
             syntax_exts: vec!(),
+            lint_passes: vec!(),
         }
     }
 
@@ -67,4 +73,9 @@ impl Registry {
                 span: None,
             }, None));
     }
+
+    /// Register a compiler lint pass.
+    pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) {
+        self.lint_passes.push(lint_pass);
+    }
 }