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