about summary refs log tree commit diff
path: root/src/libsyntax
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2015-05-24 09:38:26 +0000
committerbors <bors@rust-lang.org>2015-05-24 09:38:26 +0000
commitcc56c20ba4ccc12f58e1c844b77168bc4805cbb6 (patch)
treecde59db62a290a198a398b9f686f807e7f4d75db /src/libsyntax
parent0fc0476e6ae2bcc5cce75d78548cf037b6692a97 (diff)
parent22b720a920612211d83f7176d7cf2f184c74d294 (diff)
downloadrust-cc56c20ba4ccc12f58e1c844b77168bc4805cbb6.tar.gz
rust-cc56c20ba4ccc12f58e1c844b77168bc4805cbb6.zip
Auto merge of #25168 - Manishearth:register_attr, r=eddyb
This lets plugin authors opt attributes out of the `custom_attribute`
and `unused_attribute` checks.


cc @thepowersgang
Diffstat (limited to 'src/libsyntax')
-rw-r--r--src/libsyntax/feature_gate.rs44
1 files changed, 31 insertions, 13 deletions
diff --git a/src/libsyntax/feature_gate.rs b/src/libsyntax/feature_gate.rs
index d79714248c8..bd73e6b7de7 100644
--- a/src/libsyntax/feature_gate.rs
+++ b/src/libsyntax/feature_gate.rs
@@ -358,6 +358,7 @@ struct Context<'a> {
     features: Vec<&'static str>,
     span_handler: &'a SpanHandler,
     cm: &'a CodeMap,
+    plugin_attributes: &'a [(String, AttributeType)],
 }
 
 impl<'a> Context<'a> {
@@ -372,7 +373,7 @@ impl<'a> Context<'a> {
         self.features.iter().any(|&n| n == feature)
     }
 
-    fn check_attribute(&self, attr: &ast::Attribute) {
+    fn check_attribute(&self, attr: &ast::Attribute, is_macro: bool) {
         debug!("check_attribute(attr = {:?})", attr);
         let name = &*attr.name();
         for &(n, ty) in KNOWN_ATTRIBUTES {
@@ -384,6 +385,15 @@ impl<'a> Context<'a> {
                 return;
             }
         }
+        for &(ref n, ref ty) in self.plugin_attributes.iter() {
+            if &*n == name {
+                // Plugins can't gate attributes, so we don't check for it
+                // unlike the code above; we only use this loop to
+                // short-circuit to avoid the checks below
+                debug!("check_attribute: {:?} is registered by a plugin, {:?}", name, ty);
+                return;
+            }
+        }
         if name.starts_with("rustc_") {
             self.gate_feature("rustc_attrs", attr.span,
                               "unless otherwise specified, attributes \
@@ -394,12 +404,18 @@ impl<'a> Context<'a> {
                               "attributes of the form `#[derive_*]` are reserved \
                                for the compiler");
         } else {
-            self.gate_feature("custom_attribute", attr.span,
-                       &format!("The attribute `{}` is currently \
-                                unknown to the compiler and \
-                                may have meaning \
-                                added to it in the future",
-                                name));
+            // Only run the custom attribute lint during regular
+            // feature gate checking. Macro gating runs
+            // before the plugin attributes are registered
+            // so we skip this then
+            if !is_macro {
+                self.gate_feature("custom_attribute", attr.span,
+                           &format!("The attribute `{}` is currently \
+                                    unknown to the compiler and \
+                                    may have meaning \
+                                    added to it in the future",
+                                    name));
+            }
         }
     }
 }
@@ -478,7 +494,7 @@ impl<'a, 'v> Visitor<'v> for MacroVisitor<'a> {
     }
 
     fn visit_attribute(&mut self, attr: &'v ast::Attribute) {
-        self.context.check_attribute(attr);
+        self.context.check_attribute(attr, true);
     }
 }
 
@@ -497,7 +513,7 @@ impl<'a> PostExpansionVisitor<'a> {
 impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
     fn visit_attribute(&mut self, attr: &ast::Attribute) {
         if !self.context.cm.span_allows_unstable(attr.span) {
-            self.context.check_attribute(attr);
+            self.context.check_attribute(attr, false);
         }
     }
 
@@ -684,6 +700,7 @@ impl<'a, 'v> Visitor<'v> for PostExpansionVisitor<'a> {
 
 fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
                         krate: &ast::Crate,
+                        plugin_attributes: &[(String, AttributeType)],
                         check: F)
                        -> Features
     where F: FnOnce(&mut Context, &ast::Crate)
@@ -692,6 +709,7 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
         features: Vec::new(),
         span_handler: span_handler,
         cm: cm,
+        plugin_attributes: plugin_attributes,
     };
 
     let mut accepted_features = Vec::new();
@@ -764,14 +782,14 @@ fn check_crate_inner<F>(cm: &CodeMap, span_handler: &SpanHandler,
 
 pub fn check_crate_macros(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
 -> Features {
-    check_crate_inner(cm, span_handler, krate,
+    check_crate_inner(cm, span_handler, krate, &[] as &'static [_],
                       |ctx, krate| visit::walk_crate(&mut MacroVisitor { context: ctx }, krate))
 }
 
-pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate)
-                   -> Features
+pub fn check_crate(cm: &CodeMap, span_handler: &SpanHandler, krate: &ast::Crate,
+                   plugin_attributes: &[(String, AttributeType)]) -> Features
 {
-    check_crate_inner(cm, span_handler, krate,
+    check_crate_inner(cm, span_handler, krate, plugin_attributes,
                       |ctx, krate| visit::walk_crate(&mut PostExpansionVisitor { context: ctx },
                                                      krate))
 }