• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #![allow(clippy::uninlined_format_args)]
2 
3 #[macro_use]
4 mod macros;
5 
6 use proc_macro2::{Delimiter, Group, Ident, Punct, Spacing, Span, TokenStream, TokenTree};
7 use syn::parse::{Parse, ParseStream};
8 use syn::{DeriveInput, Result, Visibility};
9 
10 #[derive(Debug)]
11 struct VisRest {
12     vis: Visibility,
13     rest: TokenStream,
14 }
15 
16 impl Parse for VisRest {
parse(input: ParseStream) -> Result<Self>17     fn parse(input: ParseStream) -> Result<Self> {
18         Ok(VisRest {
19             vis: input.parse()?,
20             rest: input.parse()?,
21         })
22     }
23 }
24 
25 macro_rules! assert_vis_parse {
26     ($input:expr, Ok($p:pat)) => {
27         assert_vis_parse!($input, Ok($p) + "");
28     };
29 
30     ($input:expr, Ok($p:pat) + $rest:expr) => {
31         let expected = $rest.parse::<TokenStream>().unwrap();
32         let parse: VisRest = syn::parse_str($input).unwrap();
33 
34         match parse.vis {
35             $p => {}
36             _ => panic!("Expected {}, got {:?}", stringify!($p), parse.vis),
37         }
38 
39         // NOTE: Round-trips through `to_string` to avoid potential whitespace
40         // diffs.
41         assert_eq!(parse.rest.to_string(), expected.to_string());
42     };
43 
44     ($input:expr, Err) => {
45         syn::parse2::<VisRest>($input.parse().unwrap()).unwrap_err();
46     };
47 }
48 
49 #[test]
test_pub()50 fn test_pub() {
51     assert_vis_parse!("pub", Ok(Visibility::Public(_)));
52 }
53 
54 #[test]
test_inherited()55 fn test_inherited() {
56     assert_vis_parse!("", Ok(Visibility::Inherited));
57 }
58 
59 #[test]
test_in()60 fn test_in() {
61     assert_vis_parse!("pub(in foo::bar)", Ok(Visibility::Restricted(_)));
62 }
63 
64 #[test]
test_pub_crate()65 fn test_pub_crate() {
66     assert_vis_parse!("pub(crate)", Ok(Visibility::Restricted(_)));
67 }
68 
69 #[test]
test_pub_self()70 fn test_pub_self() {
71     assert_vis_parse!("pub(self)", Ok(Visibility::Restricted(_)));
72 }
73 
74 #[test]
test_pub_super()75 fn test_pub_super() {
76     assert_vis_parse!("pub(super)", Ok(Visibility::Restricted(_)));
77 }
78 
79 #[test]
test_missing_in()80 fn test_missing_in() {
81     assert_vis_parse!("pub(foo::bar)", Ok(Visibility::Public(_)) + "(foo::bar)");
82 }
83 
84 #[test]
test_missing_in_path()85 fn test_missing_in_path() {
86     assert_vis_parse!("pub(in)", Err);
87 }
88 
89 #[test]
test_crate_path()90 fn test_crate_path() {
91     assert_vis_parse!(
92         "pub(crate::A, crate::B)",
93         Ok(Visibility::Public(_)) + "(crate::A, crate::B)"
94     );
95 }
96 
97 #[test]
test_junk_after_in()98 fn test_junk_after_in() {
99     assert_vis_parse!("pub(in some::path @@garbage)", Err);
100 }
101 
102 #[test]
test_empty_group_vis()103 fn test_empty_group_vis() {
104     // mimics `struct S { $vis $field: () }` where $vis is empty
105     let tokens = TokenStream::from_iter(vec![
106         TokenTree::Ident(Ident::new("struct", Span::call_site())),
107         TokenTree::Ident(Ident::new("S", Span::call_site())),
108         TokenTree::Group(Group::new(
109             Delimiter::Brace,
110             TokenStream::from_iter(vec![
111                 TokenTree::Group(Group::new(Delimiter::None, TokenStream::new())),
112                 TokenTree::Group(Group::new(
113                     Delimiter::None,
114                     TokenStream::from_iter(vec![TokenTree::Ident(Ident::new(
115                         "f",
116                         Span::call_site(),
117                     ))]),
118                 )),
119                 TokenTree::Punct(Punct::new(':', Spacing::Alone)),
120                 TokenTree::Group(Group::new(Delimiter::Parenthesis, TokenStream::new())),
121             ]),
122         )),
123     ]);
124 
125     snapshot!(tokens as DeriveInput, @r###"
126     DeriveInput {
127         vis: Visibility::Inherited,
128         ident: "S",
129         generics: Generics,
130         data: Data::Struct {
131             fields: Fields::Named {
132                 named: [
133                     Field {
134                         vis: Visibility::Inherited,
135                         ident: Some("f"),
136                         colon_token: Some,
137                         ty: Type::Tuple,
138                     },
139                 ],
140             },
141         },
142     }
143     "###);
144 }
145