2014-05-24 18:16:10 -05:00
|
|
|
// Copyright 2012-2013 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.
|
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
//! Used by plugin crates to tell `rustc` about the plugins they provide.
|
|
|
|
|
2014-07-20 22:27:59 -05:00
|
|
|
use lint::{LintPassObject, LintId, Lint};
|
2014-09-15 18:09:09 -05:00
|
|
|
use session::Session;
|
2014-06-18 19:26:14 -05:00
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
use syntax::ext::base::{SyntaxExtension, NamedSyntaxExtension, NormalTT};
|
2014-12-02 12:07:41 -06:00
|
|
|
use syntax::ext::base::{IdentTT, Decorator, Modifier, MultiModifier, MacroRulesTT};
|
2015-03-28 04:23:20 -05:00
|
|
|
use syntax::ext::base::MacroExpanderFn;
|
2014-05-24 18:16:10 -05:00
|
|
|
use syntax::codemap::Span;
|
|
|
|
use syntax::parse::token;
|
2015-01-02 20:26:00 -06:00
|
|
|
use syntax::ptr::P;
|
2014-05-24 18:16:10 -05:00
|
|
|
use syntax::ast;
|
2015-05-06 11:38:36 -05:00
|
|
|
use syntax::feature_gate::AttributeType;
|
2014-05-24 18:16:10 -05:00
|
|
|
|
2014-07-20 22:27:59 -05:00
|
|
|
use std::collections::HashMap;
|
2015-04-08 14:52:58 -05:00
|
|
|
use std::borrow::ToOwned;
|
2014-07-20 22:27:59 -05:00
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
/// Structure used to register plugins.
|
|
|
|
///
|
|
|
|
/// A plugin registrar function takes an `&mut Registry` and should call
|
|
|
|
/// methods to register its plugins.
|
|
|
|
///
|
|
|
|
/// This struct has public fields and other methods for use by `rustc`
|
|
|
|
/// itself. They are not documented here, and plugin authors should
|
|
|
|
/// not use them.
|
2014-09-15 18:09:09 -05:00
|
|
|
pub struct Registry<'a> {
|
|
|
|
/// Compiler session. Useful if you want to emit diagnostic messages
|
|
|
|
/// from the plugin registrar.
|
|
|
|
pub sess: &'a Session,
|
|
|
|
|
2015-01-02 20:26:00 -06:00
|
|
|
#[doc(hidden)]
|
2015-02-06 15:56:38 -06:00
|
|
|
pub args_hidden: Option<Vec<P<ast::MetaItem>>>,
|
2015-01-02 20:26:00 -06:00
|
|
|
|
2014-05-24 18:16:10 -05:00
|
|
|
#[doc(hidden)]
|
|
|
|
pub krate_span: Span,
|
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub syntax_exts: Vec<NamedSyntaxExtension>,
|
2014-06-18 19:26:14 -05:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub lint_passes: Vec<LintPassObject>,
|
2014-07-20 22:27:59 -05:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub lint_groups: HashMap<&'static str, Vec<LintId>>,
|
2015-04-08 14:52:58 -05:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub llvm_passes: Vec<String>,
|
2015-05-06 11:38:36 -05:00
|
|
|
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub attributes: Vec<(String, AttributeType)>,
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
|
2014-09-15 18:09:09 -05:00
|
|
|
impl<'a> Registry<'a> {
|
2014-05-24 18:16:10 -05:00
|
|
|
#[doc(hidden)]
|
2014-09-15 18:09:09 -05:00
|
|
|
pub fn new(sess: &'a Session, krate: &ast::Crate) -> Registry<'a> {
|
2014-05-24 18:16:10 -05:00
|
|
|
Registry {
|
2014-09-15 18:09:09 -05:00
|
|
|
sess: sess,
|
2015-01-02 20:26:00 -06:00
|
|
|
args_hidden: None,
|
2014-05-24 18:16:10 -05:00
|
|
|
krate_span: krate.span,
|
|
|
|
syntax_exts: vec!(),
|
2014-06-18 19:26:14 -05:00
|
|
|
lint_passes: vec!(),
|
2014-07-20 22:27:59 -05:00
|
|
|
lint_groups: HashMap::new(),
|
2015-04-08 14:52:58 -05:00
|
|
|
llvm_passes: vec!(),
|
2015-05-06 11:38:36 -05:00
|
|
|
attributes: vec!(),
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-02-06 15:56:38 -06:00
|
|
|
/// Get the plugin's arguments, if any.
|
2015-01-02 20:26:00 -06:00
|
|
|
///
|
2015-02-06 15:56:38 -06:00
|
|
|
/// 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>> {
|
2015-01-02 20:26:00 -06:00
|
|
|
self.args_hidden.as_ref().expect("args not set")
|
|
|
|
}
|
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
/// Register a syntax extension of any kind.
|
|
|
|
///
|
|
|
|
/// This is the most general hook into `libsyntax`'s expansion behavior.
|
2014-05-24 18:16:10 -05:00
|
|
|
pub fn register_syntax_extension(&mut self, name: ast::Name, extension: SyntaxExtension) {
|
|
|
|
self.syntax_exts.push((name, match extension {
|
Add #[allow_internal_unstable] to track stability for macros better.
Unstable items used in a macro expansion will now always trigger
stability warnings, *unless* the unstable items are directly inside a
macro marked with `#[allow_internal_unstable]`. IOW, the compiler warns
unless the span of the unstable item is a subspan of the definition of a
macro marked with that attribute.
E.g.
#[allow_internal_unstable]
macro_rules! foo {
($e: expr) => {{
$e;
unstable(); // no warning
only_called_by_foo!();
}}
}
macro_rules! only_called_by_foo {
() => { unstable() } // warning
}
foo!(unstable()) // warning
The unstable inside `foo` is fine, due to the attribute. But the
`unstable` inside `only_called_by_foo` is not, since that macro doesn't
have the attribute, and the `unstable` passed into `foo` is also not
fine since it isn't contained in the macro itself (that is, even though
it is only used directly in the macro).
In the process this makes the stability tracking much more precise,
e.g. previously `println!("{}", unstable())` got no warning, but now it
does. As such, this is a bug fix that may cause [breaking-change]s.
The attribute is definitely feature gated, since it explicitly allows
side-stepping the feature gating system.
2015-02-28 21:09:28 -06:00
|
|
|
NormalTT(ext, _, allow_internal_unstable) => {
|
|
|
|
NormalTT(ext, Some(self.krate_span), allow_internal_unstable)
|
|
|
|
}
|
|
|
|
IdentTT(ext, _, allow_internal_unstable) => {
|
|
|
|
IdentTT(ext, Some(self.krate_span), allow_internal_unstable)
|
|
|
|
}
|
2014-09-11 00:07:49 -05:00
|
|
|
Decorator(ext) => Decorator(ext),
|
|
|
|
Modifier(ext) => Modifier(ext),
|
2014-12-02 12:07:41 -06:00
|
|
|
MultiModifier(ext) => MultiModifier(ext),
|
2014-09-15 18:09:09 -05:00
|
|
|
MacroRulesTT => {
|
|
|
|
self.sess.err("plugin tried to register a new MacroRulesTT");
|
|
|
|
return;
|
|
|
|
}
|
2014-05-24 18:16:10 -05:00
|
|
|
}));
|
|
|
|
}
|
|
|
|
|
2014-05-26 16:48:54 -05:00
|
|
|
/// Register a macro of the usual kind.
|
|
|
|
///
|
|
|
|
/// This is a convenience wrapper for `register_syntax_extension`.
|
2014-09-10 22:59:26 -05:00
|
|
|
/// It builds for you a `NormalTT` that calls `expander`,
|
2014-05-26 16:48:54 -05:00
|
|
|
/// and also takes care of interning the macro's name.
|
2014-05-24 18:16:10 -05:00
|
|
|
pub fn register_macro(&mut self, name: &str, expander: MacroExpanderFn) {
|
Add #[allow_internal_unstable] to track stability for macros better.
Unstable items used in a macro expansion will now always trigger
stability warnings, *unless* the unstable items are directly inside a
macro marked with `#[allow_internal_unstable]`. IOW, the compiler warns
unless the span of the unstable item is a subspan of the definition of a
macro marked with that attribute.
E.g.
#[allow_internal_unstable]
macro_rules! foo {
($e: expr) => {{
$e;
unstable(); // no warning
only_called_by_foo!();
}}
}
macro_rules! only_called_by_foo {
() => { unstable() } // warning
}
foo!(unstable()) // warning
The unstable inside `foo` is fine, due to the attribute. But the
`unstable` inside `only_called_by_foo` is not, since that macro doesn't
have the attribute, and the `unstable` passed into `foo` is also not
fine since it isn't contained in the macro itself (that is, even though
it is only used directly in the macro).
In the process this makes the stability tracking much more precise,
e.g. previously `println!("{}", unstable())` got no warning, but now it
does. As such, this is a bug fix that may cause [breaking-change]s.
The attribute is definitely feature gated, since it explicitly allows
side-stepping the feature gating system.
2015-02-28 21:09:28 -06:00
|
|
|
self.register_syntax_extension(token::intern(name),
|
|
|
|
NormalTT(Box::new(expander), None, false));
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|
2014-06-18 19:26:14 -05:00
|
|
|
|
|
|
|
/// Register a compiler lint pass.
|
|
|
|
pub fn register_lint_pass(&mut self, lint_pass: LintPassObject) {
|
|
|
|
self.lint_passes.push(lint_pass);
|
|
|
|
}
|
2014-07-20 22:27:59 -05:00
|
|
|
|
|
|
|
/// Register a lint group.
|
|
|
|
pub fn register_lint_group(&mut self, name: &'static str, to: Vec<&'static Lint>) {
|
2014-09-14 22:27:36 -05:00
|
|
|
self.lint_groups.insert(name, to.into_iter().map(|x| LintId::of(x)).collect());
|
2014-07-20 22:27:59 -05:00
|
|
|
}
|
2015-04-08 14:52:58 -05:00
|
|
|
|
|
|
|
/// Register an LLVM pass.
|
|
|
|
///
|
|
|
|
/// Registration with LLVM itself is handled through static C++ objects with
|
|
|
|
/// constructors. This method simply adds a name to the list of passes to
|
|
|
|
/// execute.
|
|
|
|
pub fn register_llvm_pass(&mut self, name: &str) {
|
|
|
|
self.llvm_passes.push(name.to_owned());
|
|
|
|
}
|
2015-05-06 11:38:36 -05:00
|
|
|
|
|
|
|
|
|
|
|
/// Register an attribute with an attribute type
|
|
|
|
///
|
|
|
|
/// Registered attributes will bypass the `custom_attribute` feature gate
|
|
|
|
///
|
|
|
|
/// `Whitelisted` attributes will additionally not trigger the `unused_attribute`
|
|
|
|
/// lint
|
|
|
|
///
|
|
|
|
/// `CrateLevel` attributes will not be allowed on anything other than a crate
|
|
|
|
pub fn register_attribute(&mut self, name: String, ty: AttributeType) {
|
|
|
|
if let AttributeType::Gated(..) = ty {
|
|
|
|
self.sess.err("plugin tried to register a gated attribute. \
|
|
|
|
Only `Normal`, `Whitelisted`, and `CrateLevel` \
|
|
|
|
attributes are allowed");
|
|
|
|
}
|
|
|
|
self.attributes.push((name, ty));
|
|
|
|
}
|
2014-05-24 18:16:10 -05:00
|
|
|
}
|