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 quote::{quote, ToTokens};
8fad3a1d3Sopenharmony_ciuse syn::{parse_quote, Expr, Type, TypePath};
9fad3a1d3Sopenharmony_ci
10fad3a1d3Sopenharmony_ci#[test]
11fad3a1d3Sopenharmony_cifn parse_interpolated_leading_component() {
12fad3a1d3Sopenharmony_ci    // mimics the token stream corresponding to `$mod::rest`
13fad3a1d3Sopenharmony_ci    let tokens = TokenStream::from_iter(vec![
14fad3a1d3Sopenharmony_ci        TokenTree::Group(Group::new(Delimiter::None, quote! { first })),
15fad3a1d3Sopenharmony_ci        TokenTree::Punct(Punct::new(':', Spacing::Joint)),
16fad3a1d3Sopenharmony_ci        TokenTree::Punct(Punct::new(':', Spacing::Alone)),
17fad3a1d3Sopenharmony_ci        TokenTree::Ident(Ident::new("rest", Span::call_site())),
18fad3a1d3Sopenharmony_ci    ]);
19fad3a1d3Sopenharmony_ci
20fad3a1d3Sopenharmony_ci    snapshot!(tokens.clone() as Expr, @r###"
21fad3a1d3Sopenharmony_ci    Expr::Path {
22fad3a1d3Sopenharmony_ci        path: Path {
23fad3a1d3Sopenharmony_ci            segments: [
24fad3a1d3Sopenharmony_ci                PathSegment {
25fad3a1d3Sopenharmony_ci                    ident: "first",
26fad3a1d3Sopenharmony_ci                },
27fad3a1d3Sopenharmony_ci                Token![::],
28fad3a1d3Sopenharmony_ci                PathSegment {
29fad3a1d3Sopenharmony_ci                    ident: "rest",
30fad3a1d3Sopenharmony_ci                },
31fad3a1d3Sopenharmony_ci            ],
32fad3a1d3Sopenharmony_ci        },
33fad3a1d3Sopenharmony_ci    }
34fad3a1d3Sopenharmony_ci    "###);
35fad3a1d3Sopenharmony_ci
36fad3a1d3Sopenharmony_ci    snapshot!(tokens as Type, @r###"
37fad3a1d3Sopenharmony_ci    Type::Path {
38fad3a1d3Sopenharmony_ci        path: Path {
39fad3a1d3Sopenharmony_ci            segments: [
40fad3a1d3Sopenharmony_ci                PathSegment {
41fad3a1d3Sopenharmony_ci                    ident: "first",
42fad3a1d3Sopenharmony_ci                },
43fad3a1d3Sopenharmony_ci                Token![::],
44fad3a1d3Sopenharmony_ci                PathSegment {
45fad3a1d3Sopenharmony_ci                    ident: "rest",
46fad3a1d3Sopenharmony_ci                },
47fad3a1d3Sopenharmony_ci            ],
48fad3a1d3Sopenharmony_ci        },
49fad3a1d3Sopenharmony_ci    }
50fad3a1d3Sopenharmony_ci    "###);
51fad3a1d3Sopenharmony_ci}
52fad3a1d3Sopenharmony_ci
53fad3a1d3Sopenharmony_ci#[test]
54fad3a1d3Sopenharmony_cifn print_incomplete_qpath() {
55fad3a1d3Sopenharmony_ci    // qpath with `as` token
56fad3a1d3Sopenharmony_ci    let mut ty: TypePath = parse_quote!(<Self as A>::Q);
57fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
58fad3a1d3Sopenharmony_ci    TokenStream(`< Self as A > :: Q`)
59fad3a1d3Sopenharmony_ci    "###);
60fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
61fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
62fad3a1d3Sopenharmony_ci    TokenStream(`< Self as A > ::`)
63fad3a1d3Sopenharmony_ci    "###);
64fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
65fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
66fad3a1d3Sopenharmony_ci    TokenStream(`< Self >`)
67fad3a1d3Sopenharmony_ci    "###);
68fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_none());
69fad3a1d3Sopenharmony_ci
70fad3a1d3Sopenharmony_ci    // qpath without `as` token
71fad3a1d3Sopenharmony_ci    let mut ty: TypePath = parse_quote!(<Self>::A::B);
72fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
73fad3a1d3Sopenharmony_ci    TokenStream(`< Self > :: A :: B`)
74fad3a1d3Sopenharmony_ci    "###);
75fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
76fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
77fad3a1d3Sopenharmony_ci    TokenStream(`< Self > :: A ::`)
78fad3a1d3Sopenharmony_ci    "###);
79fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
80fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
81fad3a1d3Sopenharmony_ci    TokenStream(`< Self > ::`)
82fad3a1d3Sopenharmony_ci    "###);
83fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_none());
84fad3a1d3Sopenharmony_ci
85fad3a1d3Sopenharmony_ci    // normal path
86fad3a1d3Sopenharmony_ci    let mut ty: TypePath = parse_quote!(Self::A::B);
87fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
88fad3a1d3Sopenharmony_ci    TokenStream(`Self :: A :: B`)
89fad3a1d3Sopenharmony_ci    "###);
90fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
91fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
92fad3a1d3Sopenharmony_ci    TokenStream(`Self :: A ::`)
93fad3a1d3Sopenharmony_ci    "###);
94fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
95fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
96fad3a1d3Sopenharmony_ci    TokenStream(`Self ::`)
97fad3a1d3Sopenharmony_ci    "###);
98fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_some());
99fad3a1d3Sopenharmony_ci    snapshot!(ty.to_token_stream(), @r###"
100fad3a1d3Sopenharmony_ci    TokenStream(``)
101fad3a1d3Sopenharmony_ci    "###);
102fad3a1d3Sopenharmony_ci    assert!(ty.path.segments.pop().is_none());
103fad3a1d3Sopenharmony_ci}
104fad3a1d3Sopenharmony_ci
105fad3a1d3Sopenharmony_ci#[test]
106fad3a1d3Sopenharmony_cifn parse_parenthesized_path_arguments_with_disambiguator() {
107fad3a1d3Sopenharmony_ci    #[rustfmt::skip]
108fad3a1d3Sopenharmony_ci    let tokens = quote!(dyn FnOnce::() -> !);
109fad3a1d3Sopenharmony_ci    snapshot!(tokens as Type, @r###"
110fad3a1d3Sopenharmony_ci    Type::TraitObject {
111fad3a1d3Sopenharmony_ci        dyn_token: Some,
112fad3a1d3Sopenharmony_ci        bounds: [
113fad3a1d3Sopenharmony_ci            TypeParamBound::Trait(TraitBound {
114fad3a1d3Sopenharmony_ci                path: Path {
115fad3a1d3Sopenharmony_ci                    segments: [
116fad3a1d3Sopenharmony_ci                        PathSegment {
117fad3a1d3Sopenharmony_ci                            ident: "FnOnce",
118fad3a1d3Sopenharmony_ci                            arguments: PathArguments::Parenthesized {
119fad3a1d3Sopenharmony_ci                                output: ReturnType::Type(
120fad3a1d3Sopenharmony_ci                                    Type::Never,
121fad3a1d3Sopenharmony_ci                                ),
122fad3a1d3Sopenharmony_ci                            },
123fad3a1d3Sopenharmony_ci                        },
124fad3a1d3Sopenharmony_ci                    ],
125fad3a1d3Sopenharmony_ci                },
126fad3a1d3Sopenharmony_ci            }),
127fad3a1d3Sopenharmony_ci        ],
128fad3a1d3Sopenharmony_ci    }
129fad3a1d3Sopenharmony_ci    "###);
130fad3a1d3Sopenharmony_ci}
131