]> git.lizzy.rs Git - rust.git/commitdiff
Add and use `HasAttrs` trait
authorJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Wed, 18 May 2016 07:25:44 +0000 (07:25 +0000)
committerJeffrey Seyfried <jeffrey.seyfried@gmail.com>
Thu, 26 May 2016 23:23:01 +0000 (23:23 +0000)
src/libsyntax/ast.rs
src/libsyntax/attr.rs

index d9409d3bbd9213bf3fe842c69a316b6d67d30153..b641600fb448a07119d90b70e77acb7c3449de7c 100644 (file)
@@ -15,7 +15,7 @@
 pub use self::ViewPath_::*;
 pub use self::PathParameters::*;
 
-use attr::ThinAttributes;
+use attr::{ThinAttributes, HasAttrs};
 use codemap::{mk_sp, respan, Span, Spanned, DUMMY_SP, ExpnId};
 use abi::Abi;
 use errors;
@@ -829,13 +829,7 @@ pub fn id(&self) -> Option<NodeId> {
     }
 
     pub fn attrs(&self) -> &[Attribute] {
-        match *self {
-            StmtKind::Decl(ref d, _) => d.attrs(),
-            StmtKind::Expr(ref e, _) |
-            StmtKind::Semi(ref e, _) => e.attrs(),
-            StmtKind::Mac(_, _, Some(ref b)) => b,
-            StmtKind::Mac(_, _, None) => &[],
-        }
+        HasAttrs::attrs(self)
     }
 }
 
@@ -868,10 +862,7 @@ pub struct Local {
 
 impl Local {
     pub fn attrs(&self) -> &[Attribute] {
-        match self.attrs {
-            Some(ref b) => b,
-            None => &[],
-        }
+        HasAttrs::attrs(self)
     }
 }
 
@@ -887,10 +878,7 @@ pub enum DeclKind {
 
 impl Decl {
     pub fn attrs(&self) -> &[Attribute] {
-        match self.node {
-            DeclKind::Local(ref l) => l.attrs(),
-            DeclKind::Item(ref i) => i.attrs(),
-        }
+        HasAttrs::attrs(self)
     }
 }
 
@@ -935,10 +923,7 @@ pub struct Expr {
 
 impl Expr {
     pub fn attrs(&self) -> &[Attribute] {
-        match self.attrs {
-            Some(ref b) => b,
-            None => &[],
-        }
+        HasAttrs::attrs(self)
     }
 }
 
index 8761ca3717895adb0aebba24551e46d88d71b67d..c3c3deea1877fa1a00fc69fd6c413e55bdd6f813 100644 (file)
@@ -884,82 +884,109 @@ fn into_thin_attrs(self) -> ThinAttributes {
     }
 }
 
+pub trait HasAttrs: Sized {
+    fn attrs(&self) -> &[ast::Attribute];
+    fn map_attrs<F: FnOnce(Vec<ast::Attribute>) -> Vec<ast::Attribute>>(self, f: F) -> Self;
+}
+
 /// A cheap way to add Attributes to an AST node.
 pub trait WithAttrs {
     // FIXME: Could be extended to anything IntoIter<Item=Attribute>
     fn with_attrs(self, attrs: ThinAttributes) -> Self;
 }
 
-impl WithAttrs for P<Expr> {
+impl<T: HasAttrs> WithAttrs for T {
     fn with_attrs(self, attrs: ThinAttributes) -> Self {
-        self.map(|mut e| {
-            e.attrs.update(|a| a.append(attrs));
-            e
+        self.map_attrs(|mut orig_attrs| {
+            orig_attrs.extend(attrs.into_attr_vec());
+            orig_attrs
         })
     }
 }
 
-impl WithAttrs for P<Item> {
-    fn with_attrs(self, attrs: ThinAttributes) -> Self {
-        self.map(|Item { ident, attrs: mut ats, id, node, vis, span }| {
-            ats.extend(attrs.into_attr_vec());
-            Item {
-                ident: ident,
-                attrs: ats,
-                id: id,
-                node: node,
-                vis: vis,
-                span: span,
-            }
-        })
+impl HasAttrs for Vec<Attribute> {
+    fn attrs(&self) -> &[Attribute] {
+        &self
+    }
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        f(self)
     }
 }
 
-impl WithAttrs for P<Local> {
-    fn with_attrs(self, attrs: ThinAttributes) -> Self {
-        self.map(|Local { pat, ty, init, id, span, attrs: mut ats }| {
-            ats.update(|a| a.append(attrs));
-            Local {
-                pat: pat,
-                ty: ty,
-                init: init,
-                id: id,
-                span: span,
-                attrs: ats,
-            }
-        })
+impl HasAttrs for ThinAttributes {
+    fn attrs(&self) -> &[Attribute] {
+        self.as_attr_slice()
+    }
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        self.map_thin_attrs(f)
     }
 }
 
-impl WithAttrs for P<Decl> {
-    fn with_attrs(self, attrs: ThinAttributes) -> Self {
-        self.map(|Spanned { span, node }| {
-            Spanned {
-                span: span,
-                node: match node {
-                    DeclKind::Local(local) => DeclKind::Local(local.with_attrs(attrs)),
-                    DeclKind::Item(item) => DeclKind::Item(item.with_attrs(attrs)),
-                }
-            }
-        })
+impl<T: HasAttrs + 'static> HasAttrs for P<T> {
+    fn attrs(&self) -> &[Attribute] {
+        (**self).attrs()
+    }
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        self.map(|t| t.map_attrs(f))
     }
 }
 
-impl WithAttrs for P<Stmt> {
-    fn with_attrs(self, attrs: ThinAttributes) -> Self {
-        self.map(|Spanned { span, node }| {
-            Spanned {
-                span: span,
-                node: match node {
-                    StmtKind::Decl(decl, id) => StmtKind::Decl(decl.with_attrs(attrs), id),
-                    StmtKind::Expr(expr, id) => StmtKind::Expr(expr.with_attrs(attrs), id),
-                    StmtKind::Semi(expr, id) => StmtKind::Semi(expr.with_attrs(attrs), id),
-                    StmtKind::Mac(mac, style, mut ats) => {
-                        ats.update(|a| a.append(attrs));
-                        StmtKind::Mac(mac, style, ats)
-                    }
-                },
-            }
-        })
+impl HasAttrs for DeclKind {
+    fn attrs(&self) -> &[Attribute] {
+        match *self {
+            DeclKind::Local(ref local) => local.attrs(),
+            DeclKind::Item(ref item) => item.attrs(),
+        }
+    }
+
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        match self {
+            DeclKind::Local(local) => DeclKind::Local(local.map_attrs(f)),
+            DeclKind::Item(item) => DeclKind::Item(item.map_attrs(f)),
+        }
     }
 }
+
+impl HasAttrs for StmtKind {
+    fn attrs(&self) -> &[Attribute] {
+        match *self {
+            StmtKind::Decl(ref decl, _) => decl.attrs(),
+            StmtKind::Expr(ref expr, _) | StmtKind::Semi(ref expr, _) => expr.attrs(),
+            StmtKind::Mac(_, _, ref attrs) => attrs.attrs(),
+        }
+    }
+
+    fn map_attrs<F: FnOnce(Vec<Attribute>) -> Vec<Attribute>>(self, f: F) -> Self {
+        match self {
+            StmtKind::Decl(decl, id) => StmtKind::Decl(decl.map_attrs(f), id),
+            StmtKind::Expr(expr, id) => StmtKind::Expr(expr.map_attrs(f), id),
+            StmtKind::Semi(expr, id) => StmtKind::Semi(expr.map_attrs(f), id),
+            StmtKind::Mac(mac, style, attrs) =>
+                StmtKind::Mac(mac, style, attrs.map_attrs(f)),
+        }
+    }
+}
+
+macro_rules! derive_has_attrs_from_field {
+    ($($ty:path),*) => { derive_has_attrs_from_field!($($ty: .attrs),*); };
+    ($($ty:path : $(.$field:ident)*),*) => { $(
+        impl HasAttrs for $ty {
+            fn attrs(&self) -> &[Attribute] {
+                self $(.$field)* .attrs()
+            }
+
+            fn map_attrs<F>(mut self, f: F) -> Self
+                where F: FnOnce(Vec<Attribute>) -> Vec<Attribute>,
+            {
+                self $(.$field)* = self $(.$field)* .map_attrs(f);
+                self
+            }
+        }
+    )* }
+}
+
+derive_has_attrs_from_field! {
+    Item, Expr, Local, ast::ForeignItem, ast::StructField, ast::ImplItem, ast::TraitItem, ast::Arm
+}
+
+derive_has_attrs_from_field! { Decl: .node, Stmt: .node, ast::Variant: .node.attrs }