1 //! Used by plugin crates to tell `rustc` about the plugins they provide.
3 use rustc::lint::{EarlyLintPassObject, LateLintPassObject, LintId, Lint};
4 use rustc::session::Session;
5 use rustc::util::nodemap::FxHashMap;
7 use syntax::ext::base::{SyntaxExtension, SyntaxExtensionKind, NamedSyntaxExtension};
8 use syntax::ext::base::MacroExpanderFn;
9 use syntax::symbol::Symbol;
11 use syntax::feature_gate::AttributeType;
14 use std::borrow::ToOwned;
16 /// Structure used to register plugins.
18 /// A plugin registrar function takes an `&mut Registry` and should call
19 /// methods to register its plugins.
21 /// This struct has public fields and other methods for use by `rustc`
22 /// itself. They are not documented here, and plugin authors should
24 pub struct Registry<'a> {
25 /// Compiler session. Useful if you want to emit diagnostic messages
26 /// from the plugin registrar.
27 pub sess: &'a Session,
30 pub args_hidden: Option<Vec<ast::NestedMetaItem>>,
36 pub syntax_exts: Vec<NamedSyntaxExtension>,
39 pub early_lint_passes: Vec<EarlyLintPassObject>,
42 pub late_lint_passes: Vec<LateLintPassObject>,
45 pub lint_groups: FxHashMap<&'static str, (Vec<LintId>, Option<&'static str>)>,
48 pub llvm_passes: Vec<String>,
51 pub attributes: Vec<(Symbol, AttributeType)>,
54 impl<'a> Registry<'a> {
56 pub fn new(sess: &'a Session, krate_span: Span) -> Registry<'a> {
62 early_lint_passes: vec![],
63 late_lint_passes: vec![],
64 lint_groups: FxHashMap::default(),
70 /// Gets the plugin's arguments, if any.
72 /// These are specified inside the `plugin` crate attribute as
75 /// #![plugin(my_plugin_name(... args ...))]
78 /// Returns empty slice in case the plugin was loaded
79 /// with `--extra-plugins`
80 pub fn args(&self) -> &[ast::NestedMetaItem] {
81 self.args_hidden.as_ref().map(|v| &v[..]).unwrap_or(&[])
84 /// Register a syntax extension of any kind.
86 /// This is the most general hook into `libsyntax`'s expansion behavior.
87 pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
88 self.syntax_exts.push((name, extension));
91 /// Register a macro of the usual kind.
93 /// This is a convenience wrapper for `register_syntax_extension`.
94 /// It builds for you a `SyntaxExtensionKind::LegacyBang` that calls `expander`,
95 /// and also takes care of interning the macro's name.
96 pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
97 let kind = SyntaxExtensionKind::LegacyBang(Box::new(expander));
98 let ext = SyntaxExtension::default(kind, self.sess.edition());
99 self.register_syntax_extension(Symbol::intern(name), ext);
102 /// Register a compiler lint pass.
103 pub fn register_early_lint_pass(&mut self, lint_pass: EarlyLintPassObject) {
104 self.early_lint_passes.push(lint_pass);
107 /// Register a compiler lint pass.
108 pub fn register_late_lint_pass(&mut self, lint_pass: LateLintPassObject) {
109 self.late_lint_passes.push(lint_pass);
111 /// Register a lint group.
112 pub fn register_lint_group(
115 deprecated_name: Option<&'static str>,
116 to: Vec<&'static Lint>
118 self.lint_groups.insert(name,
119 (to.into_iter().map(|x| LintId::of(x)).collect(),
123 /// Register an LLVM pass.
125 /// Registration with LLVM itself is handled through static C++ objects with
126 /// constructors. This method simply adds a name to the list of passes to
128 pub fn register_llvm_pass(&mut self, name: &str) {
129 self.llvm_passes.push(name.to_owned());
132 /// Register an attribute with an attribute type.
134 /// Registered attributes will bypass the `custom_attribute` feature gate.
135 /// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
136 /// lint. `CrateLevel` attributes will not be allowed on anything other than a crate.
137 pub fn register_attribute(&mut self, name: Symbol, ty: AttributeType) {
138 self.attributes.push((name, ty));