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