1 | use crate::algorithm::Printer; |
2 | use crate::fixup::FixupContext; |
3 | use crate::iter::IterDelimited; |
4 | use crate::path::PathKind; |
5 | use crate::INDENT; |
6 | use proc_macro2::TokenStream; |
7 | use syn::{ |
8 | Abi, BareFnArg, BareVariadic, ReturnType, Type, TypeArray, TypeBareFn, TypeGroup, |
9 | TypeImplTrait, TypeInfer, TypeMacro, TypeNever, TypeParen, TypePath, TypePtr, TypeReference, |
10 | TypeSlice, TypeTraitObject, TypeTuple, |
11 | }; |
12 | |
13 | impl Printer { |
14 | pub fn ty(&mut self, ty: &Type) { |
15 | match ty { |
16 | #![cfg_attr (all(test, exhaustive), deny(non_exhaustive_omitted_patterns))] |
17 | Type::Array(ty) => self.type_array(ty), |
18 | Type::BareFn(ty) => self.type_bare_fn(ty), |
19 | Type::Group(ty) => self.type_group(ty), |
20 | Type::ImplTrait(ty) => self.type_impl_trait(ty), |
21 | Type::Infer(ty) => self.type_infer(ty), |
22 | Type::Macro(ty) => self.type_macro(ty), |
23 | Type::Never(ty) => self.type_never(ty), |
24 | Type::Paren(ty) => self.type_paren(ty), |
25 | Type::Path(ty) => self.type_path(ty), |
26 | Type::Ptr(ty) => self.type_ptr(ty), |
27 | Type::Reference(ty) => self.type_reference(ty), |
28 | Type::Slice(ty) => self.type_slice(ty), |
29 | Type::TraitObject(ty) => self.type_trait_object(ty), |
30 | Type::Tuple(ty) => self.type_tuple(ty), |
31 | Type::Verbatim(ty) => self.type_verbatim(ty), |
32 | _ => unimplemented!("unknown Type" ), |
33 | } |
34 | } |
35 | |
36 | fn type_array(&mut self, ty: &TypeArray) { |
37 | self.word("[" ); |
38 | self.ty(&ty.elem); |
39 | self.word("; " ); |
40 | self.expr(&ty.len, FixupContext::NONE); |
41 | self.word("]" ); |
42 | } |
43 | |
44 | fn type_bare_fn(&mut self, ty: &TypeBareFn) { |
45 | if let Some(bound_lifetimes) = &ty.lifetimes { |
46 | self.bound_lifetimes(bound_lifetimes); |
47 | } |
48 | if ty.unsafety.is_some() { |
49 | self.word("unsafe " ); |
50 | } |
51 | if let Some(abi) = &ty.abi { |
52 | self.abi(abi); |
53 | } |
54 | self.word("fn(" ); |
55 | self.cbox(INDENT); |
56 | self.zerobreak(); |
57 | for bare_fn_arg in ty.inputs.iter().delimited() { |
58 | self.bare_fn_arg(&bare_fn_arg); |
59 | self.trailing_comma(bare_fn_arg.is_last && ty.variadic.is_none()); |
60 | } |
61 | if let Some(variadic) = &ty.variadic { |
62 | self.bare_variadic(variadic); |
63 | self.zerobreak(); |
64 | } |
65 | self.offset(-INDENT); |
66 | self.end(); |
67 | self.word(")" ); |
68 | self.return_type(&ty.output); |
69 | } |
70 | |
71 | fn type_group(&mut self, ty: &TypeGroup) { |
72 | self.ty(&ty.elem); |
73 | } |
74 | |
75 | fn type_impl_trait(&mut self, ty: &TypeImplTrait) { |
76 | self.word("impl " ); |
77 | for type_param_bound in ty.bounds.iter().delimited() { |
78 | if !type_param_bound.is_first { |
79 | self.word(" + " ); |
80 | } |
81 | self.type_param_bound(&type_param_bound); |
82 | } |
83 | } |
84 | |
85 | fn type_infer(&mut self, ty: &TypeInfer) { |
86 | let _ = ty; |
87 | self.word("_" ); |
88 | } |
89 | |
90 | fn type_macro(&mut self, ty: &TypeMacro) { |
91 | let semicolon = false; |
92 | self.mac(&ty.mac, None, semicolon); |
93 | } |
94 | |
95 | fn type_never(&mut self, ty: &TypeNever) { |
96 | let _ = ty; |
97 | self.word("!" ); |
98 | } |
99 | |
100 | fn type_paren(&mut self, ty: &TypeParen) { |
101 | self.word("(" ); |
102 | self.ty(&ty.elem); |
103 | self.word(")" ); |
104 | } |
105 | |
106 | fn type_path(&mut self, ty: &TypePath) { |
107 | self.qpath(&ty.qself, &ty.path, PathKind::Type); |
108 | } |
109 | |
110 | fn type_ptr(&mut self, ty: &TypePtr) { |
111 | self.word("*" ); |
112 | if ty.mutability.is_some() { |
113 | self.word("mut " ); |
114 | } else { |
115 | self.word("const " ); |
116 | } |
117 | self.ty(&ty.elem); |
118 | } |
119 | |
120 | fn type_reference(&mut self, ty: &TypeReference) { |
121 | self.word("&" ); |
122 | if let Some(lifetime) = &ty.lifetime { |
123 | self.lifetime(lifetime); |
124 | self.nbsp(); |
125 | } |
126 | if ty.mutability.is_some() { |
127 | self.word("mut " ); |
128 | } |
129 | self.ty(&ty.elem); |
130 | } |
131 | |
132 | fn type_slice(&mut self, ty: &TypeSlice) { |
133 | self.word("[" ); |
134 | self.ty(&ty.elem); |
135 | self.word("]" ); |
136 | } |
137 | |
138 | fn type_trait_object(&mut self, ty: &TypeTraitObject) { |
139 | self.word("dyn " ); |
140 | for type_param_bound in ty.bounds.iter().delimited() { |
141 | if !type_param_bound.is_first { |
142 | self.word(" + " ); |
143 | } |
144 | self.type_param_bound(&type_param_bound); |
145 | } |
146 | } |
147 | |
148 | fn type_tuple(&mut self, ty: &TypeTuple) { |
149 | self.word("(" ); |
150 | self.cbox(INDENT); |
151 | self.zerobreak(); |
152 | for elem in ty.elems.iter().delimited() { |
153 | self.ty(&elem); |
154 | if ty.elems.len() == 1 { |
155 | self.word("," ); |
156 | self.zerobreak(); |
157 | } else { |
158 | self.trailing_comma(elem.is_last); |
159 | } |
160 | } |
161 | self.offset(-INDENT); |
162 | self.end(); |
163 | self.word(")" ); |
164 | } |
165 | |
166 | #[cfg (not(feature = "verbatim" ))] |
167 | fn type_verbatim(&mut self, ty: &TokenStream) { |
168 | unimplemented!("Type::Verbatim `{}`" , ty); |
169 | } |
170 | |
171 | #[cfg (feature = "verbatim" )] |
172 | fn type_verbatim(&mut self, tokens: &TokenStream) { |
173 | use syn::parse::{Parse, ParseStream, Result}; |
174 | use syn::punctuated::Punctuated; |
175 | use syn::{token, FieldsNamed, Token, TypeParamBound}; |
176 | |
177 | enum TypeVerbatim { |
178 | Ellipsis, |
179 | AnonStruct(AnonStruct), |
180 | AnonUnion(AnonUnion), |
181 | DynStar(DynStar), |
182 | MutSelf(MutSelf), |
183 | NotType(NotType), |
184 | } |
185 | |
186 | struct AnonStruct { |
187 | fields: FieldsNamed, |
188 | } |
189 | |
190 | struct AnonUnion { |
191 | fields: FieldsNamed, |
192 | } |
193 | |
194 | struct DynStar { |
195 | bounds: Punctuated<TypeParamBound, Token![+]>, |
196 | } |
197 | |
198 | struct MutSelf { |
199 | ty: Option<Type>, |
200 | } |
201 | |
202 | struct NotType { |
203 | inner: Type, |
204 | } |
205 | |
206 | impl Parse for TypeVerbatim { |
207 | fn parse(input: ParseStream) -> Result<Self> { |
208 | let lookahead = input.lookahead1(); |
209 | if lookahead.peek(Token![struct]) { |
210 | input.parse::<Token![struct]>()?; |
211 | let fields: FieldsNamed = input.parse()?; |
212 | Ok(TypeVerbatim::AnonStruct(AnonStruct { fields })) |
213 | } else if lookahead.peek(Token![union]) && input.peek2(token::Brace) { |
214 | input.parse::<Token![union]>()?; |
215 | let fields: FieldsNamed = input.parse()?; |
216 | Ok(TypeVerbatim::AnonUnion(AnonUnion { fields })) |
217 | } else if lookahead.peek(Token![dyn]) { |
218 | input.parse::<Token![dyn]>()?; |
219 | input.parse::<Token![*]>()?; |
220 | let bounds = input.parse_terminated(TypeParamBound::parse, Token![+])?; |
221 | Ok(TypeVerbatim::DynStar(DynStar { bounds })) |
222 | } else if lookahead.peek(Token![mut]) { |
223 | input.parse::<Token![mut]>()?; |
224 | input.parse::<Token![self]>()?; |
225 | let ty = if input.is_empty() { |
226 | None |
227 | } else { |
228 | input.parse::<Token![:]>()?; |
229 | let ty: Type = input.parse()?; |
230 | Some(ty) |
231 | }; |
232 | Ok(TypeVerbatim::MutSelf(MutSelf { ty })) |
233 | } else if lookahead.peek(Token![!]) { |
234 | input.parse::<Token![!]>()?; |
235 | let inner: Type = input.parse()?; |
236 | Ok(TypeVerbatim::NotType(NotType { inner })) |
237 | } else if lookahead.peek(Token![...]) { |
238 | input.parse::<Token![...]>()?; |
239 | Ok(TypeVerbatim::Ellipsis) |
240 | } else { |
241 | Err(lookahead.error()) |
242 | } |
243 | } |
244 | } |
245 | |
246 | let ty: TypeVerbatim = match syn::parse2(tokens.clone()) { |
247 | Ok(ty) => ty, |
248 | Err(_) => unimplemented!("Type::Verbatim ` {}`" , tokens), |
249 | }; |
250 | |
251 | match ty { |
252 | TypeVerbatim::Ellipsis => { |
253 | self.word("..." ); |
254 | } |
255 | TypeVerbatim::AnonStruct(ty) => { |
256 | self.cbox(INDENT); |
257 | self.word("struct {" ); |
258 | self.hardbreak_if_nonempty(); |
259 | for field in &ty.fields.named { |
260 | self.field(field); |
261 | self.word("," ); |
262 | self.hardbreak(); |
263 | } |
264 | self.offset(-INDENT); |
265 | self.end(); |
266 | self.word("}" ); |
267 | } |
268 | TypeVerbatim::AnonUnion(ty) => { |
269 | self.cbox(INDENT); |
270 | self.word("union {" ); |
271 | self.hardbreak_if_nonempty(); |
272 | for field in &ty.fields.named { |
273 | self.field(field); |
274 | self.word("," ); |
275 | self.hardbreak(); |
276 | } |
277 | self.offset(-INDENT); |
278 | self.end(); |
279 | self.word("}" ); |
280 | } |
281 | TypeVerbatim::DynStar(ty) => { |
282 | self.word("dyn* " ); |
283 | for type_param_bound in ty.bounds.iter().delimited() { |
284 | if !type_param_bound.is_first { |
285 | self.word(" + " ); |
286 | } |
287 | self.type_param_bound(&type_param_bound); |
288 | } |
289 | } |
290 | TypeVerbatim::MutSelf(bare_fn_arg) => { |
291 | self.word("mut self" ); |
292 | if let Some(ty) = &bare_fn_arg.ty { |
293 | self.word(": " ); |
294 | self.ty(ty); |
295 | } |
296 | } |
297 | TypeVerbatim::NotType(ty) => { |
298 | self.word("!" ); |
299 | self.ty(&ty.inner); |
300 | } |
301 | } |
302 | } |
303 | |
304 | pub fn return_type(&mut self, ty: &ReturnType) { |
305 | match ty { |
306 | ReturnType::Default => {} |
307 | ReturnType::Type(_arrow, ty) => { |
308 | self.word(" -> " ); |
309 | self.ty(ty); |
310 | } |
311 | } |
312 | } |
313 | |
314 | fn bare_fn_arg(&mut self, bare_fn_arg: &BareFnArg) { |
315 | self.outer_attrs(&bare_fn_arg.attrs); |
316 | if let Some((name, _colon)) = &bare_fn_arg.name { |
317 | self.ident(name); |
318 | self.word(": " ); |
319 | } |
320 | self.ty(&bare_fn_arg.ty); |
321 | } |
322 | |
323 | fn bare_variadic(&mut self, variadic: &BareVariadic) { |
324 | self.outer_attrs(&variadic.attrs); |
325 | if let Some((name, _colon)) = &variadic.name { |
326 | self.ident(name); |
327 | self.word(": " ); |
328 | } |
329 | self.word("..." ); |
330 | } |
331 | |
332 | pub fn abi(&mut self, abi: &Abi) { |
333 | self.word("extern " ); |
334 | if let Some(name) = &abi.name { |
335 | self.lit_str(name); |
336 | self.nbsp(); |
337 | } |
338 | } |
339 | } |
340 | |