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