Update `visibility` rule for stabilized `pub(restricted)` syntax.

Fixes #118
diff --git a/src/data.rs b/src/data.rs
index f21bfd8..69df303 100644
--- a/src/data.rs
+++ b/src/data.rs
@@ -77,7 +77,7 @@
     /// Crate-visible, i.e. `pub(crate)`.
     Crate,
 
-    /// Restricted, e.g. `pub(some::module)`.
+    /// Restricted, e.g. `pub(self)` or `pub(super)` or `pub(in some::module)`.
     Restricted(Box<Path>),
 
     /// Inherited, i.e. private.
@@ -97,7 +97,7 @@
     use expr::parsing::expr;
     use generics::parsing::where_clause;
     use ident::parsing::ident;
-    use ty::parsing::{path, ty};
+    use ty::parsing::{mod_style_path, ty};
 
     named!(pub struct_body -> (WhereClause, VariantData), alt!(
         do_parse!(
@@ -212,7 +212,24 @@
         do_parse!(
             keyword!("pub") >>
             punct!("(") >>
-            restricted: path >>
+            keyword!("self") >>
+            punct!(")") >>
+            (Visibility::Restricted(Box::new("self".into())))
+        )
+        |
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            keyword!("super") >>
+            punct!(")") >>
+            (Visibility::Restricted(Box::new("super".into())))
+        )
+        |
+        do_parse!(
+            keyword!("pub") >>
+            punct!("(") >>
+            keyword!("in") >>
+            restricted: mod_style_path >>
             punct!(")") >>
             (Visibility::Restricted(Box::new(restricted)))
         )
@@ -227,6 +244,7 @@
 mod printing {
     use super::*;
     use quote::{Tokens, ToTokens};
+    use ty::PathParameters;
 
     impl ToTokens for Variant {
         fn to_tokens(&self, tokens: &mut Tokens) {
@@ -287,6 +305,17 @@
                 Visibility::Restricted(ref path) => {
                     tokens.append("pub");
                     tokens.append("(");
+
+                    if !path.global &&
+                       path.segments.len() == 1 &&
+                       (path.segments[0].ident == "self" || path.segments[0].ident == "super") &&
+                       path.segments[0].parameters == PathParameters::none() {
+
+                        // Don't emit preceding `in` if path is `self` or `super`
+                    } else {
+                        tokens.append("in");
+                    }
+
                     path.to_tokens(tokens);
                     tokens.append(")");
                 }
diff --git a/tests/test_macro_input.rs b/tests/test_macro_input.rs
index 6f40a00..126ed34 100644
--- a/tests/test_macro_input.rs
+++ b/tests/test_macro_input.rs
@@ -316,3 +316,85 @@
 
     assert!(actual.attrs[0].meta_item().is_none());
 }
+
+#[test]
+fn test_pub_restricted() {
+    // Taken from tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs
+    let raw =r#"
+        pub(in m) struct Z(pub(in m::n) u8);
+    "#;
+
+    let expected = MacroInput {
+        ident: "Z".into(),
+        vis: Visibility::Restricted(Box::new("m".into())),
+        attrs: vec![],
+        generics: Generics::default(),
+        body: Body::Struct(VariantData::Tuple(vec![Field {
+            ident: None,
+            vis: Visibility::Restricted(Box::new(Path { global: false, segments: vec!["m".into(), "n".into()] })),
+            attrs: vec![],
+            ty: Ty::Path(None, "u8".into()),
+        }])),
+    };
+
+    let actual = parse_macro_input(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_crate() {
+    let raw =r#"
+        pub(crate) struct S;
+    "#;
+
+    let expected = MacroInput {
+        ident: "S".into(),
+        vis: Visibility::Crate,
+        attrs: vec![],
+        generics: Generics::default(),
+        body: Body::Struct(VariantData::Unit),
+    };
+
+    let actual = parse_macro_input(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_super() {
+    let raw =r#"
+        pub(super) struct S;
+    "#;
+
+    let expected = MacroInput {
+        ident: "S".into(),
+        vis: Visibility::Restricted(Box::new("super".into())),
+        attrs: vec![],
+        generics: Generics::default(),
+        body: Body::Struct(VariantData::Unit),
+    };
+
+    let actual = parse_macro_input(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
+
+#[test]
+fn test_pub_restricted_in_super() {
+    let raw =r#"
+        pub(in super) struct S;
+    "#;
+
+    let expected = MacroInput {
+        ident: "S".into(),
+        vis: Visibility::Restricted(Box::new("super".into())),
+        attrs: vec![],
+        generics: Generics::default(),
+        body: Body::Struct(VariantData::Unit),
+    };
+
+    let actual = parse_macro_input(raw).unwrap();
+
+    assert_eq!(expected, actual);
+}
diff --git a/tests/test_round_trip.rs b/tests/test_round_trip.rs
index 9b44115..d77bf06 100644
--- a/tests/test_round_trip.rs
+++ b/tests/test_round_trip.rs
@@ -91,9 +91,7 @@
         // TODO precedence issue with binop vs poly trait ref
         "tests/rust/src/test/run-pass/try-macro.rs" |
         // TODO 128-bit integer literals
-        "tests/rust/src/test/run-pass/u128.rs" |
-        // TODO pub(restricted) syntax
-        "tests/rust/src/test/ui/resolve/auxiliary/privacy-struct-ctor.rs" => false,
+        "tests/rust/src/test/run-pass/u128.rs" => false,
         _ => true,
     }
 }