Implement pub(crate) and pub(restricted)
diff --git a/src/data.rs b/src/data.rs
index 26367dd..738d4a7 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -42,9 +42,11 @@
     pub ty: Ty,
 }
 
-#[derive(Debug, Copy, Clone, Eq, PartialEq)]
+#[derive(Debug, Clone, Eq, PartialEq)]
 pub enum Visibility {
     Public,
+    Crate,
+    Restricted(Box<Path>),
     Inherited,
 }
 
@@ -56,7 +58,7 @@
     use constant::parsing::const_expr;
     use generics::parsing::where_clause;
     use ident::parsing::ident;
-    use ty::parsing::ty;
+    use ty::parsing::{path, ty};
 
     named!(pub struct_body -> (WhereClause, VariantData), alt!(
         do_parse!(
@@ -147,6 +149,22 @@
     ));
 
     named!(pub visibility -> Visibility, alt!(
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            keyword!("crate") >>
+            punct!(")") >>
+            (Visibility::Crate)
+        )
+        |
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            restricted: path >>
+            punct!(")") >>
+            (Visibility::Restricted(Box::new(restricted)))
+        )
+        |
         keyword!("pub") => { |_| Visibility::Public }
         |
         epsilon!() => { |_| Visibility::Inherited }
@@ -206,8 +224,21 @@
 
     impl ToTokens for Visibility {
         fn to_tokens(&self, tokens: &mut Tokens) {
-            if let Visibility::Public = *self {
-                tokens.append("pub");
+            match *self {
+                Visibility::Public => tokens.append("pub"),
+                Visibility::Crate => {
+                    tokens.append("pub");
+                    tokens.append("(");
+                    tokens.append("crate");
+                    tokens.append(")");
+                }
+                Visibility::Restricted(ref path) => {
+                    tokens.append("pub");
+                    tokens.append("(");
+                    path.to_tokens(tokens);
+                    tokens.append(")");
+                }
+                Visibility::Inherited => {}
             }
         }
     }
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 75ad023..848c67d 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -62,9 +62,7 @@
         // TODO ignore byte order mark
         "tests/rust/src/test/run-pass/utf8-bom.rs" |
         // TODO type macros
-        "tests/rust/src/test/run-pass-fulldeps/proc_macro.rs" |
-        // TODO pub(crate)
-        "tests/rust/src/test/ui/span/pub-struct-field.rs" => false,
+        "tests/rust/src/test/run-pass-fulldeps/proc_macro.rs" => false,
         _ => true,
     }
 }
@@ -154,7 +152,8 @@
     use std::rc::Rc;
     use syntex_syntax::ast::{Attribute, Expr, ExprKind, Field, FnDecl, FunctionRetTy, ImplItem,
                              ImplItemKind, ItemKind, Mac, MetaItem, MetaItemKind, MethodSig,
-                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam};
+                             NestedMetaItem, NestedMetaItemKind, TraitItem, TraitItemKind, TyParam,
+                             Visibility};
     use syntex_syntax::codemap::{self, Spanned};
     use syntex_syntax::fold::{self, Folder};
     use syntex_syntax::parse::token::{Lit, Token, intern};
@@ -383,6 +382,13 @@
                 _ => t,
             }
         }
+
+        fn fold_vis(&mut self, vis: Visibility) -> Visibility {
+            match vis {
+                Visibility::Crate(span) => Visibility::Crate(self.new_span(span)),
+                _ => fold::noop_fold_vis(vis, self),
+            }
+        }
     }
 
     Respanner.fold_crate(krate)