Skip to main content

a9_prettyplease/
path.rs

1use crate::algorithm::Printer;
2use crate::iter::IterDelimited;
3use crate::INDENT;
4use std::ptr;
5use syn::{
6    AngleBracketedGenericArguments, AssocConst, AssocType, Constraint, GenericArgument,
7    ParenthesizedGenericArguments, Path, PathArguments, PathSegment, QSelf,
8};
9
10#[derive(#[automatically_derived]
impl ::core::marker::Copy for PathKind { }Copy, #[automatically_derived]
impl ::core::clone::Clone for PathKind {
    #[inline]
    fn clone(&self) -> PathKind { *self }
}Clone, #[automatically_derived]
impl ::core::cmp::PartialEq for PathKind {
    #[inline]
    fn eq(&self, other: &PathKind) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
11pub enum PathKind {
12    // a::B
13    Simple,
14    // a::B<T>
15    Type,
16    // a::B::<T>
17    Expr,
18}
19
20impl Printer {
21    pub fn path(&mut self, path: &Path, kind: PathKind) {
22        if !!path.segments.is_empty() {
    ::core::panicking::panic("assertion failed: !path.segments.is_empty()")
};assert!(!path.segments.is_empty());
23        for segment in path.segments.iter().delimited() {
24            if !segment.is_first || path.leading_colon.is_some() {
25                self.word("::");
26            }
27            self.path_segment(&segment, kind);
28        }
29    }
30
31    pub fn path_segment(&mut self, segment: &PathSegment, kind: PathKind) {
32        self.ident(&segment.ident);
33        self.path_arguments(&segment.arguments, kind);
34    }
35
36    fn path_arguments(&mut self, arguments: &PathArguments, kind: PathKind) {
37        match arguments {
38            PathArguments::None => {}
39            PathArguments::AngleBracketed(arguments) => {
40                self.angle_bracketed_generic_arguments(arguments, kind);
41            }
42            PathArguments::Parenthesized(arguments) => {
43                self.parenthesized_generic_arguments(arguments);
44            }
45        }
46    }
47
48    fn generic_argument(&mut self, arg: &GenericArgument) {
49        match arg {
50            #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
51            GenericArgument::Lifetime(lifetime) => self.lifetime(lifetime),
52            GenericArgument::Type(ty) => self.ty(ty),
53            GenericArgument::Const(expr) => self.const_argument(expr),
54            GenericArgument::AssocType(assoc) => self.assoc_type(assoc),
55            GenericArgument::AssocConst(assoc) => self.assoc_const(assoc),
56            GenericArgument::Constraint(constraint) => self.constraint(constraint),
57            _ => {
    ::core::panicking::panic_fmt(format_args!("not implemented: {0}",
            format_args!("unknown GenericArgument")));
}unimplemented!("unknown GenericArgument"),
58        }
59    }
60
61    pub fn angle_bracketed_generic_arguments(
62        &mut self,
63        generic: &AngleBracketedGenericArguments,
64        path_kind: PathKind,
65    ) {
66        if generic.args.is_empty() || path_kind == PathKind::Simple {
67            return;
68        }
69
70        if path_kind == PathKind::Expr {
71            self.word("::");
72        }
73        self.word("<");
74        self.cbox(INDENT);
75        self.zerobreak();
76
77        // Print lifetimes before types/consts/bindings, regardless of their
78        // order in self.args.
79        #[derive(#[automatically_derived]
impl ::core::cmp::Ord for Group {
    #[inline]
    fn cmp(&self, other: &Group) -> ::core::cmp::Ordering {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr)
    }
}Ord, #[automatically_derived]
impl ::core::cmp::PartialOrd for Group {
    #[inline]
    fn partial_cmp(&self, other: &Group)
        -> ::core::option::Option<::core::cmp::Ordering> {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        ::core::cmp::PartialOrd::partial_cmp(&__self_discr, &__arg1_discr)
    }
}PartialOrd, #[automatically_derived]
impl ::core::cmp::Eq for Group {
    #[inline]
    #[doc(hidden)]
    #[coverage(off)]
    fn assert_fields_are_eq(&self) {}
}Eq, #[automatically_derived]
impl ::core::cmp::PartialEq for Group {
    #[inline]
    fn eq(&self, other: &Group) -> bool {
        let __self_discr = ::core::intrinsics::discriminant_value(self);
        let __arg1_discr = ::core::intrinsics::discriminant_value(other);
        __self_discr == __arg1_discr
    }
}PartialEq)]
80        enum Group {
81            First,
82            Second,
83        }
84        fn group(arg: &GenericArgument) -> Group {
85            match arg {
86                #![cfg_attr(all(test, exhaustive), deny(non_exhaustive_omitted_patterns))]
87                GenericArgument::Lifetime(_) => Group::First,
88                GenericArgument::Type(_)
89                | GenericArgument::Const(_)
90                | GenericArgument::AssocType(_)
91                | GenericArgument::AssocConst(_)
92                | GenericArgument::Constraint(_) => Group::Second,
93                _ => Group::Second,
94            }
95        }
96        let last = generic.args.iter().max_by_key(|param| group(param));
97        for current_group in [Group::First, Group::Second] {
98            for arg in &generic.args {
99                if group(arg) == current_group {
100                    self.generic_argument(arg);
101                    self.trailing_comma(ptr::eq(arg, last.unwrap()));
102                }
103            }
104        }
105
106        self.offset(-INDENT);
107        self.end();
108        self.word(">");
109    }
110
111    fn assoc_type(&mut self, assoc: &AssocType) {
112        self.ident(&assoc.ident);
113        if let Some(generics) = &assoc.generics {
114            self.angle_bracketed_generic_arguments(generics, PathKind::Type);
115        }
116        self.word(" = ");
117        self.ty(&assoc.ty);
118    }
119
120    fn assoc_const(&mut self, assoc: &AssocConst) {
121        self.ident(&assoc.ident);
122        if let Some(generics) = &assoc.generics {
123            self.angle_bracketed_generic_arguments(generics, PathKind::Type);
124        }
125        self.word(" = ");
126        self.const_argument(&assoc.value);
127    }
128
129    fn constraint(&mut self, constraint: &Constraint) {
130        self.ident(&constraint.ident);
131        if let Some(generics) = &constraint.generics {
132            self.angle_bracketed_generic_arguments(generics, PathKind::Type);
133        }
134        self.ibox(INDENT);
135        for bound in constraint.bounds.iter().delimited() {
136            if bound.is_first {
137                self.word(": ");
138            } else {
139                self.space();
140                self.word("+ ");
141            }
142            self.type_param_bound(&bound);
143        }
144        self.end();
145    }
146
147    fn parenthesized_generic_arguments(&mut self, arguments: &ParenthesizedGenericArguments) {
148        self.cbox(INDENT);
149        self.word("(");
150        self.zerobreak();
151        for ty in arguments.inputs.iter().delimited() {
152            self.ty(&ty);
153            self.trailing_comma(ty.is_last);
154        }
155        self.offset(-INDENT);
156        self.word(")");
157        self.return_type(&arguments.output);
158        self.end();
159    }
160
161    pub fn qpath(&mut self, qself: &Option<QSelf>, path: &Path, kind: PathKind) {
162        let Some(qself) = qself else {
163            self.path(path, kind);
164            return;
165        };
166
167        if !(qself.position < path.segments.len()) {
    ::core::panicking::panic("assertion failed: qself.position < path.segments.len()")
};assert!(qself.position < path.segments.len());
168
169        self.word("<");
170        self.ty(&qself.ty);
171
172        let mut segments = path.segments.iter();
173        if qself.position > 0 {
174            self.word(" as ");
175            for segment in segments.by_ref().take(qself.position).delimited() {
176                if !segment.is_first || path.leading_colon.is_some() {
177                    self.word("::");
178                }
179                self.path_segment(&segment, PathKind::Type);
180                if segment.is_last {
181                    self.word(">");
182                }
183            }
184        } else {
185            self.word(">");
186        }
187        for segment in segments {
188            self.word("::");
189            self.path_segment(segment, kind);
190        }
191    }
192}