From 2f274d11ba48f0da6158f1da732645dc32bfe1f4 Mon Sep 17 00:00:00 2001 From: Keegan McAllister Date: Wed, 18 Jun 2014 17:26:14 -0700 Subject: [PATCH] Implement lint plugins --- src/librustc/driver/driver.rs | 14 ++++++++++---- src/librustc/driver/mod.rs | 23 +++++++++++++++++------ src/librustc/lint/mod.rs | 1 + src/librustc/plugin/registry.rs | 11 +++++++++++ 4 files changed, 39 insertions(+), 10 deletions(-) diff --git a/src/librustc/driver/driver.rs b/src/librustc/driver/driver.rs index 2fb8b2d4ac9b2..9a7be85bdd747 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 e8e057c926c7c..cfde4ad52afa6 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 Warn about @@ -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 13106973c1d17..5aa10b5ab8e8a 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 f6e37822325a8..587bedd502e15 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, + + #[doc(hidden)] + pub lint_passes: Vec, } 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); + } }