1use {
5 crate::{
6 attr::{self, WithOuterAttributes},
7 expr::BlockExpression,
8 lifetime::Lifetime,
9 pat::PatternNoTopAlt,
10 token,
11 ty::{Type, TypePath},
12 util::{FmtSingleOrIndent, Parenthesized},
13 },
14 rustidy_ast_literal::{LiteralExpression, RawStringLiteral, StringLiteral},
15 rustidy_ast_util::{Delimited, Follows, Identifier, PunctuatedTrailing, delimited, punct},
16 rustidy_format::{Format, Formattable, WhitespaceFormat},
17 rustidy_parse::{Parse, ParsePeeked},
18 rustidy_print::Print,
19 rustidy_util::Whitespace,
20};
21
22#[derive(PartialEq, Eq, Clone, Debug)]
24#[derive(serde::Serialize, serde::Deserialize)]
25#[derive(Parse, Formattable, Format, Print)]
26#[parse(name = "a function")]
27pub struct Function {
28 pub qualifiers: FunctionQualifiers,
29 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.qualifiers.has_any()))]
30 pub fn_: token::Fn,
31 #[parse(fatal)]
32 #[format(prefix_ws = Whitespace::SINGLE)]
33 pub ident: Identifier,
34 #[format(prefix_ws = Whitespace::REMOVE)]
35 pub generics: Option<GenericParams>,
36 #[format(prefix_ws = Whitespace::REMOVE)]
37 #[format(args = delimited::fmt_remove_or_indent_if_non_blank(
38 60,
39 FmtSingleOrIndent::Single,
40 FmtSingleOrIndent::Indent
41 ))]
42 pub params: Parenthesized<Option<FunctionParameters>>,
43 #[format(prefix_ws = Whitespace::SINGLE)]
44 pub ret: Option<FunctionReturnType>,
45 #[format(prefix_ws = Whitespace::INDENT)]
46 pub where_: Option<WhereClause>,
47 #[format(prefix_ws = match self.body.is_semi() {
48 true => Whitespace::REMOVE,
49 false => match self.where_.is_some() {
50 true => Whitespace::INDENT,
51 false => Whitespace::SINGLE,
52 }
53 })]
54 pub body: FunctionBody,
55}
56
57#[derive(PartialEq, Eq, Clone, Debug)]
58#[derive(strum::EnumIs)]
59#[derive(serde::Serialize, serde::Deserialize)]
60#[derive(Parse, Formattable, Format, Print)]
61pub enum FunctionBody {
62 Expr(BlockExpression),
63 Semi(token::Semi),
64}
65
66#[derive(PartialEq, Eq, Clone, Debug)]
68#[derive(serde::Serialize, serde::Deserialize)]
69#[derive(Parse, Formattable, Format, Print)]
70#[parse(name = "function qualifiers")]
71pub struct FunctionQualifiers {
72 pub const_: Option<token::Const>,
73 #[format(prefix_ws(if_ = self.const_.is_some(), expr = Whitespace::SINGLE))]
74 pub async_: Option<token::Async>,
75 #[format(prefix_ws(if_ = self.const_.is_some() || self.async_.is_some(), expr = Whitespace::SINGLE))]
76 pub safety: Option<ItemSafety>,
77 #[format(prefix_ws(
78 if_ = self.const_.is_some() || self.async_.is_some() || self.safety.is_some(),
79 expr = Whitespace::SINGLE
80 ))]
81 pub extern_: Option<ExternAbi>,
82}
83
84impl FunctionQualifiers {
85 #[must_use]
87 pub const fn has_any(&self) -> bool {
88 self.const_.is_some() || self.async_.is_some() || self.safety.is_some() || self.extern_.is_some()
89 }
90}
91
92#[derive(PartialEq, Eq, Clone, Debug)]
93#[derive(serde::Serialize, serde::Deserialize)]
94#[derive(Parse, Formattable, Format, Print)]
95pub struct ExternAbi {
96 pub extern_: token::Extern,
97 #[format(prefix_ws = Whitespace::SINGLE)]
98 pub abi: Option<Abi>,
99}
100
101#[derive(PartialEq, Eq, Clone, Debug)]
103#[derive(serde::Serialize, serde::Deserialize)]
104#[derive(Parse, Formattable, Format, Print)]
105pub enum Abi {
106 String(StringLiteral),
107 RawString(RawStringLiteral),
108}
109
110#[derive(PartialEq, Eq, Clone, Debug)]
112#[derive(serde::Serialize, serde::Deserialize)]
113#[derive(Parse, Formattable, Format, Print)]
114pub enum ItemSafety {
115 Safe(token::Safe),
116 Unsafe(token::Unsafe),
117}
118
119#[derive(PartialEq, Eq, Clone, Debug)]
121#[derive(serde::Serialize, serde::Deserialize)]
122#[derive(Parse, Formattable, Format, Print)]
123#[parse(name = "function parameters")]
124#[format(args(ty = "FmtSingleOrIndent"))]
125pub enum FunctionParameters {
126 #[format(args = args)]
127 Full(FunctionParametersFull),
128 #[parse(peek = (SelfParam, Option::<token::Comma>, Follows::<token::ParenClose>))]
129 OnlySelf(FunctionParametersOnlySelf),
130}
131
132#[derive(PartialEq, Eq, Clone, Debug)]
133#[derive(serde::Serialize, serde::Deserialize)]
134#[derive(Parse, Formattable, Format, Print)]
135pub struct FunctionParametersOnlySelf {
136 pub self_: SelfParam,
137 #[format(prefix_ws = Whitespace::REMOVE)]
138 pub trailing_comma: Option<token::Comma>,
139}
140
141impl ParsePeeked<(SelfParam, Option<token::Comma>, Follows<token::ParenClose>)> for FunctionParametersOnlySelf {
142 fn parse_from_with_peeked(
143 _parser: &mut rustidy_parse::Parser,
144 (self_, trailing_comma, _): (SelfParam, Option<token::Comma>, Follows<token::ParenClose>),
145 ) -> Result<Self, Self::Error> {
146 Ok(Self { self_, trailing_comma })
147 }
148}
149
150#[derive(PartialEq, Eq, Clone, Debug)]
151#[derive(serde::Serialize, serde::Deserialize)]
152#[derive(Parse, Formattable, Format, Print)]
153#[format(args(ty = "FmtSingleOrIndent"))]
154pub struct FunctionParametersFull {
155 pub self_: Option<FunctionParametersFullSelf>,
156 #[format(prefix_ws(if_ = self.self_.is_some(), expr = args.prefix_ws()))]
157 #[format(args = punct::fmt(args.prefix_ws(), Whitespace::REMOVE))]
158 pub rest: PunctuatedTrailing<FunctionParam, token::Comma>,
159}
160
161#[derive(PartialEq, Eq, Clone, Debug)]
162#[derive(serde::Serialize, serde::Deserialize)]
163#[derive(Parse, Formattable, Format, Print)]
164pub struct FunctionParametersFullSelf {
165 pub self_: SelfParam,
166 #[format(prefix_ws = Whitespace::REMOVE)]
167 pub comma: token::Comma,
168}
169
170#[derive(PartialEq, Eq, Clone, Debug)]
172#[derive(serde::Serialize, serde::Deserialize)]
173#[derive(Parse, Formattable, Format, Print)]
174pub struct FunctionParam(
175 #[format(args = attr::with::fmt(Whitespace::SINGLE))]
176 pub WithOuterAttributes<FunctionParamInner>,
177);
178
179#[derive(PartialEq, Eq, Clone, Debug)]
180#[derive(serde::Serialize, serde::Deserialize)]
181#[derive(Parse, Formattable, Format, Print)]
182pub enum FunctionParamInner {
183 Pattern(FunctionParamPattern),
184 CVariadic(token::DotDotDot),
185 Type(Type),
186}
187
188#[derive(PartialEq, Eq, Clone, Debug)]
190#[derive(serde::Serialize, serde::Deserialize)]
191#[derive(Parse, Formattable, Format, Print)]
192pub struct FunctionParamPattern {
193 pub pat: PatternNoTopAlt,
194 #[format(prefix_ws = Whitespace::REMOVE)]
195 pub colon: token::Colon,
196 #[parse(fatal)]
197 #[format(prefix_ws = Whitespace::SINGLE)]
198 pub ty: Type,
199}
200
201#[derive(PartialEq, Eq, Clone, Debug)]
203#[derive(serde::Serialize, serde::Deserialize)]
204#[derive(Parse, Formattable, Format, Print)]
205pub struct SelfParam(
206 #[format(args = attr::with::fmt(Whitespace::SINGLE))]
207 pub WithOuterAttributes<ShorthandOrTypedSelf>,
208);
209
210#[derive(PartialEq, Eq, Clone, Debug)]
211#[derive(serde::Serialize, serde::Deserialize)]
212#[derive(Parse, Formattable, Format, Print)]
213pub enum ShorthandOrTypedSelf {
214 Typed(TypedSelf),
215 Shorthand(ShorthandSelf),
216}
217
218#[derive(PartialEq, Eq, Clone, Debug)]
220#[derive(serde::Serialize, serde::Deserialize)]
221#[derive(Parse, Formattable, Format, Print)]
222pub struct ShorthandSelf {
223 pub ref_: Option<ShorthandSelfRef>,
224 #[format(prefix_ws(if_ = let Some(ref_) = &self.ref_, expr = match ref_.lifetime.is_some() {
225 true => Whitespace::SINGLE,
226 false => Whitespace::REMOVE,
227 }))]
228 pub mut_: Option<token::Mut>,
229 #[format(prefix_ws(if_ = self.ref_.is_some() || self.mut_.is_some(), expr = match self
230 .ref_
231 .as_ref()
232 .is_some_and(|ref_| ref_.lifetime.is_some()) || self.mut_.is_some() {
233 true => Whitespace::SINGLE,
234 false => Whitespace::REMOVE,
235 }))]
236 pub self_: token::SelfLower,
237}
238
239#[derive(PartialEq, Eq, Clone, Debug)]
240#[derive(serde::Serialize, serde::Deserialize)]
241#[derive(Parse, Formattable, Format, Print)]
242pub struct ShorthandSelfRef {
243 pub ref_: token::And,
244 #[parse(fatal)]
245 #[format(prefix_ws = Whitespace::REMOVE)]
246 pub lifetime: Option<Lifetime>,
247}
248
249#[derive(PartialEq, Eq, Clone, Debug)]
251#[derive(serde::Serialize, serde::Deserialize)]
252#[derive(Parse, Formattable, Format, Print)]
253pub struct TypedSelf {
254 pub mut_: Option<token::Mut>,
255 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.mut_.is_some()))]
256 pub self_: token::SelfLower,
257 #[format(prefix_ws = Whitespace::REMOVE)]
258 pub colon: token::Colon,
259 #[format(prefix_ws = Whitespace::SINGLE)]
260 pub ty: Type,
261}
262
263#[derive(PartialEq, Eq, Clone, Debug)]
265#[derive(serde::Serialize, serde::Deserialize)]
266#[derive(Parse, Formattable, Format, Print)]
267#[parse(name = "function return type")]
268pub struct FunctionReturnType {
269 pub arrow: token::RArrow,
270 #[parse(fatal)]
271 #[format(prefix_ws = Whitespace::SINGLE)]
272 pub ty: Type,
273}
274
275#[derive(PartialEq, Eq, Clone, Debug)]
277#[derive(serde::Serialize, serde::Deserialize)]
278#[derive(Parse, Formattable, Format, Print)]
279#[parse(name = "generic parameters")]
280pub struct GenericParams(
281 #[format(args = delimited::FmtRemove)]
282 pub Delimited<Option<GenericParamsInner>, token::Lt, token::Gt>,
283);
284
285#[derive(PartialEq, Eq, Clone, Debug)]
286#[derive(serde::Serialize, serde::Deserialize)]
287#[derive(Parse, Formattable, Format, Print)]
288#[parse(name = "generic parameters")]
289pub struct GenericParamsInner(
290 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::REMOVE))]
291 pub PunctuatedTrailing<GenericParam, token::Comma>,
292);
293
294#[derive(PartialEq, Eq, Clone, Debug)]
296#[derive(serde::Serialize, serde::Deserialize)]
297#[derive(Parse, Formattable, Format, Print)]
298pub struct GenericParam(
299 #[format(args = attr::with::fmt(Whitespace::SINGLE))]
300 pub WithOuterAttributes<GenericParamInner>,
301);
302
303#[derive(PartialEq, Eq, Clone, Debug)]
304#[derive(serde::Serialize, serde::Deserialize)]
305#[derive(Parse, Formattable, Format, Print)]
306pub enum GenericParamInner {
307 Lifetime(LifetimeParam),
308 Type(TypeParam),
309 Const(ConstParam),
310}
311
312#[derive(PartialEq, Eq, Clone, Debug)]
314#[derive(serde::Serialize, serde::Deserialize)]
315#[derive(Parse, Formattable, Format, Print)]
316#[parse(name = "a lifetime parameter")]
317pub struct LifetimeParam {
318 pub lifetime: Lifetime,
319 #[format(prefix_ws = Whitespace::REMOVE)]
320 pub bounds: Option<LifetimeParamBounds>,
321}
322
323#[derive(PartialEq, Eq, Clone, Debug)]
324#[derive(serde::Serialize, serde::Deserialize)]
325#[derive(Parse, Formattable, Format, Print)]
326pub struct LifetimeParamBounds {
327 pub colon: token::Colon,
328 #[format(prefix_ws = Whitespace::SINGLE)]
329 pub bounds: Option<LifetimeBounds>,
330}
331
332#[derive(PartialEq, Eq, Clone, Debug)]
334#[derive(serde::Serialize, serde::Deserialize)]
335#[derive(Parse, Formattable, Format, Print)]
336pub struct LifetimeBounds(
337 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::SINGLE))]
338 PunctuatedTrailing<Lifetime, token::Plus>,
339);
340
341#[derive(PartialEq, Eq, Clone, Debug)]
343#[derive(serde::Serialize, serde::Deserialize)]
344#[derive(Parse, Formattable, Format, Print)]
345#[parse(name = "a type parameter")]
346pub struct TypeParam {
347 pub ident: Identifier,
348 #[format(prefix_ws = Whitespace::REMOVE)]
349 pub bounds: Option<TypeParamColonBounds>,
350 #[format(prefix_ws = Whitespace::SINGLE)]
351 pub eq_ty: Option<TypeParamEqType>,
352}
353
354#[derive(PartialEq, Eq, Clone, Debug)]
355#[derive(serde::Serialize, serde::Deserialize)]
356#[derive(Parse, Formattable, Format, Print)]
357pub struct TypeParamColonBounds {
358 pub colon: token::Colon,
359 #[format(prefix_ws = Whitespace::SINGLE)]
360 pub bounds: Option<TypeParamBounds>,
361}
362
363#[derive(PartialEq, Eq, Clone, Debug)]
364#[derive(serde::Serialize, serde::Deserialize)]
365#[derive(Parse, Formattable, Format, Print)]
366pub struct TypeParamEqType {
367 pub eq: token::Eq,
368 #[format(prefix_ws = Whitespace::SINGLE)]
369 pub ty: Box<Type>,
370}
371
372#[derive(PartialEq, Eq, Clone, Debug)]
374#[derive(serde::Serialize, serde::Deserialize)]
375#[derive(Parse, Formattable, Format, Print)]
376pub struct TypeParamBounds(
377 #[format(args = punct::fmt(Whitespace::SINGLE, Whitespace::SINGLE))]
378 pub PunctuatedTrailing<TypeParamBound, token::Plus>,
379);
380
381#[derive(PartialEq, Eq, Clone, Debug)]
383#[derive(serde::Serialize, serde::Deserialize)]
384#[derive(Parse, Formattable, Format, Print)]
385pub enum TypeParamBound {
386 Lifetime(Lifetime),
387 Trait(TraitBound),
388 UseBound(UseBound),
389}
390
391#[derive(PartialEq, Eq, Clone, Debug)]
393#[derive(serde::Serialize, serde::Deserialize)]
394#[derive(Parse, Formattable, Format, Print)]
395pub enum TraitBound {
396 #[format(args = delimited::fmt_preserve())]
397 Parenthesized(Parenthesized<TraitBoundInner>),
398 Normal(TraitBoundInner),
399}
400
401#[derive(PartialEq, Eq, Clone, Debug)]
402#[derive(serde::Serialize, serde::Deserialize)]
403#[derive(Parse, Formattable, Format, Print)]
404pub struct TraitBoundInner {
405 pub prefix: Option<TraitBoundInnerPrefix>,
406 #[format(prefix_ws(if_ = let Some(prefix) = &self.prefix, expr = match prefix {
407 TraitBoundInnerPrefix::Question(_) => Whitespace::REMOVE,
408 TraitBoundInnerPrefix::ForLifetimes(_) => Whitespace::SINGLE,
409 }))]
410 pub path: TypePath,
411}
412
413#[derive(PartialEq, Eq, Clone, Debug)]
414#[derive(serde::Serialize, serde::Deserialize)]
415#[derive(Parse, Formattable, Format, Print)]
416pub enum TraitBoundInnerPrefix {
417 Question(token::Question),
418 ForLifetimes(Box<ForLifetimes>),
419}
420
421#[derive(PartialEq, Eq, Clone, Debug)]
423#[derive(serde::Serialize, serde::Deserialize)]
424#[derive(Parse, Formattable, Format, Print)]
425pub struct WhereClause {
426 pub where_: token::Where,
427 #[format(prefix_ws = Whitespace::INDENT)]
430 #[format(indent)]
431 #[format(args = punct::fmt(Whitespace::INDENT, Whitespace::REMOVE))]
432 pub items: Option<PunctuatedTrailing<WhereClauseItem, token::Comma>>,
433}
434
435#[derive(PartialEq, Eq, Clone, Debug)]
437#[derive(serde::Serialize, serde::Deserialize)]
438#[derive(Parse, Formattable, Format, Print)]
439pub enum WhereClauseItem {
440 Lifetime(LifetimeWhereClauseItem),
441 Type(TypeBoundWhereClauseItem),
442}
443
444#[derive(PartialEq, Eq, Clone, Debug)]
446#[derive(serde::Serialize, serde::Deserialize)]
447#[derive(Parse, Formattable, Format, Print)]
448pub struct LifetimeWhereClauseItem {
449 pub lifetime: Lifetime,
450 #[format(prefix_ws = Whitespace::REMOVE)]
451 pub colon: token::Colon,
452 #[parse(fatal)]
453 #[format(prefix_ws = Whitespace::SINGLE)]
454 pub bounds: LifetimeBounds,
455}
456
457#[derive(PartialEq, Eq, Clone, Debug)]
459#[derive(serde::Serialize, serde::Deserialize)]
460#[derive(Parse, Formattable, Format, Print)]
461pub struct TypeBoundWhereClauseItem {
462 pub for_lifetimes: Option<ForLifetimes>,
463 #[format(prefix_ws(expr = Whitespace::SINGLE, if_ = self.for_lifetimes.is_some()))]
464 pub ty: Type,
465 #[format(prefix_ws = Whitespace::REMOVE)]
466 pub colon: token::Colon,
467 #[parse(fatal)]
468 #[format(prefix_ws = Whitespace::SINGLE)]
469 pub bounds: Option<TypeParamBounds>,
470}
471
472#[derive(PartialEq, Eq, Clone, Debug)]
474#[derive(serde::Serialize, serde::Deserialize)]
475#[derive(Parse, Formattable, Format, Print)]
476pub struct ForLifetimes {
477 pub for_: token::For,
478 #[format(prefix_ws = Whitespace::REMOVE)]
479 pub params: GenericParams,
480}
481
482#[derive(PartialEq, Eq, Clone, Debug)]
484#[derive(serde::Serialize, serde::Deserialize)]
485#[derive(Parse, Formattable, Format, Print)]
486pub struct ConstParam {
487 pub const_: token::Const,
488 #[format(prefix_ws = Whitespace::SINGLE)]
489 pub ident: Identifier,
490 #[format(prefix_ws = Whitespace::REMOVE)]
491 pub colon: token::Colon,
492 #[format(prefix_ws = Whitespace::SINGLE)]
493 pub ty: Box<Type>,
494 #[format(prefix_ws = Whitespace::SINGLE)]
495 pub eq: Option<ConstParamEq>,
496}
497
498#[derive(PartialEq, Eq, Clone, Debug)]
499#[derive(serde::Serialize, serde::Deserialize)]
500#[derive(Parse, Formattable, Format, Print)]
501pub struct ConstParamEq {
502 eq: token::Eq,
503 #[format(prefix_ws = Whitespace::SINGLE)]
504 rest: ConstParamEqRest,
505}
506
507#[derive(PartialEq, Eq, Clone, Debug)]
508#[derive(serde::Serialize, serde::Deserialize)]
509#[derive(Parse, Formattable, Format, Print)]
510pub enum ConstParamEqRest {
511 Eq(Box<BlockExpression>),
512 Ident(Identifier),
513 Literal(ConstParamEqRestLiteral),
514}
515
516#[derive(PartialEq, Eq, Clone, Debug)]
517#[derive(serde::Serialize, serde::Deserialize)]
518#[derive(Parse, Formattable, Format, Print)]
519pub struct ConstParamEqRestLiteral {
520 neg: Option<token::Minus>,
521 #[format(prefix_ws = Whitespace::REMOVE)]
522 expr: Box<LiteralExpression>,
523}
524
525#[derive(PartialEq, Eq, Clone, Debug)]
527#[derive(serde::Serialize, serde::Deserialize)]
528#[derive(Parse, Formattable, Format, Print)]
529pub struct UseBound {
530 pub use_: token::Use,
531 #[parse(fatal)]
532 pub args: UseBoundGenericArgs,
533}
534
535#[derive(PartialEq, Eq, Clone, Debug)]
537#[derive(serde::Serialize, serde::Deserialize)]
538#[derive(Parse, Formattable, Format, Print)]
539pub struct UseBoundGenericArgs(
540 #[format(args = delimited::fmt_preserve())]
541 pub Delimited<UseBoundGenericArgsInner, token::Lt, token::Gt>,
542);
543
544#[derive(PartialEq, Eq, Clone, Debug)]
545#[derive(serde::Serialize, serde::Deserialize)]
546#[derive(Parse, Formattable, Format, Print)]
547pub struct UseBoundGenericArgsInner(
548 #[format(args = punct::fmt(Whitespace::PRESERVE, Whitespace::PRESERVE))]
549 pub PunctuatedTrailing<UseBoundGenericArg, token::Comma>,
550);
551
552#[derive(PartialEq, Eq, Clone, Debug)]
554#[derive(serde::Serialize, serde::Deserialize)]
555#[derive(Parse, Formattable, Format, Print)]
556pub enum UseBoundGenericArg {
557 Lifetime(Lifetime),
558 Identifier(Identifier),
559 SelfUpper(token::SelfUpper),
560}