sphinx_rustdocgen/
nodes.rs

1// sphinxcontrib_rust - Sphinx extension for the Rust programming language
2// Copyright (C) 2024  Munir Contractor
3//
4// This program is free software: you can redistribute it and/or modify
5// it under the terms of the GNU General Public License as published by
6// the Free Software Foundation, either version 3 of the License, or
7// (at your option) any later version.
8//
9// This program is distributed in the hope that it will be useful,
10// but WITHOUT ANY WARRANTY; without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12// GNU General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program.  If not, see <https://www.gnu.org/licenses/>.
16
17//! Module for generating a semi-structured representation of Rust signatures.
18//!
19//! The module helps with mapping the content of Rust signatures to the
20//! appropriate docutils node type.
21
22use std::fmt::Debug;
23
24use quote::ToTokens;
25use serde::ser::SerializeMap;
26use serde::{Serialize, Serializer};
27use syn::punctuated::Punctuated;
28use syn::{
29    Abi,
30    AngleBracketedGenericArguments,
31    BoundLifetimes,
32    Expr,
33    ExprLit,
34    GenericArgument,
35    GenericParam,
36    Generics,
37    LifetimeParam,
38    ParenthesizedGenericArguments,
39    Pat,
40    PatType,
41    Path,
42    PathArguments,
43    PathSegment,
44    ReturnType,
45    Token,
46    TraitBoundModifier,
47    Type,
48    TypeBareFn,
49    TypeParam,
50    TypeParamBound,
51    TypePath,
52    WhereClause,
53    WherePredicate,
54};
55
56/// Enum representing various docutils nodes for item signatures
57#[derive(Clone, Debug, Eq, PartialEq)]
58pub(crate) enum Node {
59    /// The node for a name in the signature.
60    Name(String),
61    /// A node for link to another item in the signature.
62    Link { value: String, target: String },
63    /// A node for a keyword in the signature.
64    Keyword(&'static str),
65    /// A node for a punctuation in the signature.
66    Punctuation(&'static str),
67    /// A node for a single space in the signature.
68    Space,
69    /// A node for a newline in the signature.
70    Newline,
71    /// A node for adding an indentation before the line.
72    Indent,
73    /// A node for an operator in the signature.
74    Operator(&'static str),
75    /// A node for the returns symbol.
76    Returns,
77    /// A literal string to include in the signature.
78    Literal(String),
79    /// A node for a lifetime name. This is not a docutils node, but kept
80    /// separate for easier identification.
81    Lifetime(String),
82}
83
84impl Serialize for Node {
85    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86    where
87        S: Serializer,
88    {
89        match self {
90            Node::Name(n) => {
91                let mut map = serializer.serialize_map(Some(2))?;
92                map.serialize_entry("type", "name")?;
93                map.serialize_entry("value", n)?;
94                map.end()
95            }
96            Node::Link {
97                value,
98                target,
99            } => {
100                let mut map = serializer.serialize_map(Some(3))?;
101                map.serialize_entry("type", "link")?;
102                map.serialize_entry("value", value)?;
103                map.serialize_entry("target", target)?;
104                map.end()
105            }
106            Node::Keyword(k) => {
107                let mut map = serializer.serialize_map(Some(2))?;
108                map.serialize_entry("type", "keyword")?;
109                map.serialize_entry("value", k)?;
110                map.end()
111            }
112            Node::Punctuation(p) => {
113                let mut map = serializer.serialize_map(Some(2))?;
114                map.serialize_entry("type", "punctuation")?;
115                map.serialize_entry("value", p)?;
116                map.end()
117            }
118            Node::Space => {
119                let mut map = serializer.serialize_map(Some(1))?;
120                map.serialize_entry("type", "space")?;
121                map.end()
122            }
123            Node::Newline => {
124                let mut map = serializer.serialize_map(Some(1))?;
125                map.serialize_entry("type", "newline")?;
126                map.end()
127            }
128            Node::Indent => {
129                let mut map = serializer.serialize_map(Some(1))?;
130                map.serialize_entry("type", "indent")?;
131                map.end()
132            }
133            Node::Operator(o) => {
134                let mut map = serializer.serialize_map(Some(2))?;
135                map.serialize_entry("type", "operator")?;
136                map.serialize_entry("value", o)?;
137                map.end()
138            }
139            Node::Returns => {
140                let mut map = serializer.serialize_map(Some(1))?;
141                map.serialize_entry("type", "returns")?;
142                map.end()
143            }
144            Node::Literal(l) => {
145                let mut map = serializer.serialize_map(Some(2))?;
146                map.serialize_entry("type", "literal")?;
147                map.serialize_entry("value", l)?;
148                map.end()
149            }
150            Node::Lifetime(lt) => {
151                let mut map = serializer.serialize_map(Some(2))?;
152                map.serialize_entry("type", "lifetime")?;
153                map.serialize_entry("value", lt)?;
154                map.end()
155            }
156        }
157    }
158}
159
160/// Get simple name for a type parameter bound.
161///
162/// The simple name is the name without any generic arguments.
163fn type_param_bound_name(type_param_bound: &TypeParamBound) -> String {
164    match type_param_bound {
165        TypeParamBound::Trait(t) => t.path.segments.last().map(|s| s.ident.to_string()).unwrap(),
166        TypeParamBound::Lifetime(l) => l.to_string(),
167        TypeParamBound::Verbatim(_) => panic!("Cannot determine name for verbatim type"),
168        x => {
169            panic!("Unsupported bound type {:?}", x)
170        }
171    }
172}
173
174/// Get simple name for a type path.
175///
176/// The simple name is essentially the path created from the identifiers of
177/// each segment of the type path.
178fn type_path_name(type_path: &TypePath) -> String {
179    type_path
180        .path
181        .segments
182        .iter()
183        .map(|s| s.ident.to_string())
184        .collect::<Vec<String>>()
185        .join("::")
186}
187
188/// Get simple name for a type.
189///
190/// The simple name is the name without any generic arguments.
191pub(crate) fn type_name(ty: &Type) -> String {
192    match ty {
193        Type::Array(a) => format!("[{}; ?]", type_name(&a.elem)),
194        Type::BareFn(f) => format!(
195            "fn ({}){}",
196            f.inputs
197                .iter()
198                .map(|i| type_name(&i.ty))
199                .collect::<Vec<String>>()
200                .join(", "),
201            match &f.output {
202                ReturnType::Type(_, r_ty) => {
203                    format!(" -> {}", type_name(r_ty))
204                }
205                _ => String::new(),
206            }
207        ),
208        Type::Group(g) => type_name(&g.elem),
209        Type::ImplTrait(t) => format!(
210            "impl {}",
211            t.bounds
212                .iter()
213                .map(type_param_bound_name)
214                .collect::<Vec<String>>()
215                .join(" + ")
216        ),
217        Type::Infer(_) | Type::Macro(_) => "_".into(),
218        Type::Never(_) => "!".into(),
219        Type::Paren(p) => format!("({})", type_name(&p.elem)),
220        Type::Path(p) => type_path_name(p),
221        Type::Ptr(p) => format!("*{}", type_name(&p.elem)),
222        Type::Reference(r) => format!("&{}", type_name(&r.elem)),
223        Type::Slice(s) => format!("[{}]", type_name(&s.elem)),
224        Type::TraitObject(t) => format!(
225            "dyn {}",
226            t.bounds
227                .iter()
228                .map(type_param_bound_name)
229                .collect::<Vec<String>>()
230                .join(" + ")
231        ),
232        Type::Tuple(t) => format!(
233            "({})",
234            t.elems
235                .iter()
236                .map(type_name)
237                .collect::<Vec<String>>()
238                .join(", ")
239        ),
240        Type::Verbatim(_) => panic!("Cannot determine name for verbatim type"),
241        x => panic!("Unsupported type category {:?}", x),
242    }
243}
244
245/// Create nodes for a literal expression.
246fn nodes_for_expr_lit(expr_lit: &ExprLit) -> Vec<Node> {
247    // TODO: Better handling for expressions. Not sure if required.
248    // If this implemented for all expr variants, update the Const and
249    // AssocConst branches below.
250    vec![Node::Literal(expr_lit.lit.to_token_stream().to_string())]
251}
252
253/// Create nodes for a generic argument.
254fn nodes_for_generic_argument(generic_arg: &GenericArgument) -> Vec<Node> {
255    let mut nodes = vec![];
256    match generic_arg {
257        GenericArgument::Lifetime(lt) => nodes.push(Node::Lifetime(lt.to_string())),
258        GenericArgument::Type(t) => nodes.extend(nodes_for_type(t)),
259        GenericArgument::Const(_) => {
260            // XXX: Can't really do much here since the expr would have to be evaluated
261            // with compiler context, and that is way beyond the scope of the project.
262            nodes.push(Node::Keyword("<const arg>"));
263        }
264        GenericArgument::AssocType(at) => {
265            nodes.push(Node::Name(at.ident.to_string()));
266            if let Some(ab) = &at.generics {
267                nodes.extend(nodes_for_angle_bracket_generic_args(ab));
268            }
269            nodes.push(Node::Punctuation(" = "));
270            nodes.extend(nodes_for_type(&at.ty));
271        }
272        GenericArgument::AssocConst(ac) => {
273            nodes.push(Node::Name(ac.ident.to_string()));
274            if let Some(ab) = &ac.generics {
275                nodes.extend(nodes_for_angle_bracket_generic_args(ab));
276            }
277            // Same issue as with const. The expr has to be evaluated to get the actual type
278            nodes.push(Node::Punctuation(" = "));
279            nodes.push(Node::Keyword("<default>"));
280        }
281        GenericArgument::Constraint(c) => {
282            nodes.push(Node::Name(c.ident.to_string()));
283            if let Some(ab) = &c.generics {
284                nodes.extend(nodes_for_angle_bracket_generic_args(ab));
285            }
286            nodes.push(Node::Punctuation(": "));
287            nodes.extend(nodes_for_type_param_bounds(&c.bounds));
288        }
289        x => panic!("Unknown generic argument type {:?}", x),
290    }
291    nodes
292}
293
294/// Create nodes for angle bracket generic arguments in paths.
295fn nodes_for_angle_bracket_generic_args(angled_args: &AngleBracketedGenericArguments) -> Vec<Node> {
296    let mut nodes = vec![];
297    if angled_args.colon2_token.is_some() {
298        nodes.push(Node::Punctuation("::"));
299    }
300    nodes.push(Node::Punctuation("<"));
301    for arg in &angled_args.args {
302        nodes.extend(nodes_for_generic_argument(arg));
303        nodes.push(Node::Punctuation(", "));
304    }
305
306    nodes.pop();
307    nodes.push(Node::Punctuation(">"));
308    nodes
309}
310
311/// Create nodes for parenthesized generic arguments in paths.
312fn nodes_for_parenthesized_generic_args(paren_args: &ParenthesizedGenericArguments) -> Vec<Node> {
313    let mut nodes = vec![Node::Punctuation("(")];
314    for ty in &paren_args.inputs {
315        nodes.extend(nodes_for_type(ty));
316        nodes.push(Node::Punctuation(", "));
317    }
318    nodes.pop();
319    nodes.push(Node::Punctuation(")"));
320    nodes.extend(nodes_for_return_type(&paren_args.output));
321    nodes
322}
323
324/// Create nodes for a path segment.
325fn nodes_for_path_segment(segment: &PathSegment, make_link: bool) -> Vec<Node> {
326    let mut nodes = if make_link {
327        vec![Node::Link {
328            value: segment.ident.to_string(),
329            target: segment.ident.to_string(),
330        }]
331    }
332    else {
333        vec![Node::Name(segment.ident.to_string())]
334    };
335    match &segment.arguments {
336        PathArguments::None => {}
337        PathArguments::AngleBracketed(ab) => {
338            nodes.extend(nodes_for_angle_bracket_generic_args(ab));
339        }
340        PathArguments::Parenthesized(p) => {
341            nodes.extend(nodes_for_parenthesized_generic_args(p));
342        }
343    }
344    nodes
345}
346
347/// Create nodes for a path.
348pub(crate) fn nodes_for_path(path: &Path) -> Vec<Node> {
349    let mut nodes = vec![];
350    if path.leading_colon.is_some() {
351        nodes.push(Node::Punctuation("::"));
352    }
353    for (idx, segment) in path.segments.iter().enumerate() {
354        nodes.extend(nodes_for_path_segment(segment, idx == 0));
355        nodes.push(Node::Punctuation("::"));
356    }
357    nodes.pop();
358    nodes
359}
360
361/// Create nodes for an optional ABI specification.
362pub(crate) fn nodes_for_abi_opt(abi: &Option<Abi>) -> Vec<Node> {
363    abi.as_ref()
364        .map(|abi| {
365            let mut nodes = vec![Node::Keyword("extern"), Node::Space];
366            if let Some(s) = &abi.name {
367                nodes.extend_from_slice(&[Node::Literal(s.value()), Node::Space]);
368            }
369            nodes
370        })
371        .unwrap_or_default()
372}
373
374/// Create nodes for a type specification.
375pub(crate) fn nodes_for_type(ty: &Type) -> Vec<Node> {
376    let mut nodes = vec![];
377    match ty {
378        Type::Array(a) => {
379            nodes.push(Node::Punctuation("["));
380            nodes.extend(nodes_for_type(&a.elem));
381            nodes.push(Node::Punctuation("; "));
382
383            // XXX: Array len is an expression that has to be evaluated.
384            // In some cases, it may be a simple constant, but it can also be a variable,
385            // and its value can't be determined simply from the AST.
386            if let Expr::Lit(l) = &a.len {
387                nodes.extend(nodes_for_expr_lit(l));
388            }
389            else {
390                nodes.push(Node::Punctuation("?"))
391            }
392
393            nodes.push(Node::Punctuation("]"));
394        }
395        Type::BareFn(bf) => {
396            nodes.extend(nodes_for_bare_fn(bf));
397        }
398        Type::Group(_) => {} // Unsure if this needs to be supported
399        Type::ImplTrait(i) => {
400            nodes.push(Node::Keyword("impl"));
401            nodes.push(Node::Space);
402            nodes.extend(nodes_for_type_param_bounds(&i.bounds));
403        }
404        Type::Infer(_) => {
405            nodes.push(Node::Punctuation("_"));
406        }
407        Type::Macro(_) => {
408            nodes.push(Node::Punctuation("?"));
409        }
410        Type::Never(_) => {
411            nodes.push(Node::Punctuation("!"));
412        }
413        Type::Paren(p) => {
414            nodes.push(Node::Punctuation("("));
415            nodes.extend(nodes_for_type(&p.elem));
416            nodes.push(Node::Punctuation(")"));
417        }
418        Type::Path(p) => {
419            // TODO: Figure out whether supporting QSelf if necessary or not
420            // TODO: Check whether path needs to be link or not based on its name.
421            nodes.extend(nodes_for_path(&p.path));
422        }
423        Type::Ptr(p) => {
424            nodes.push(Node::Operator("*"));
425            if p.const_token.is_some() {
426                nodes.push(Node::Keyword("const"));
427                nodes.push(Node::Space);
428            }
429            if p.mutability.is_some() {
430                nodes.push(Node::Keyword("mut"));
431                nodes.push(Node::Space);
432            }
433            nodes.extend(nodes_for_type(&p.elem));
434        }
435        Type::Reference(r) => {
436            nodes.push(Node::Punctuation("&"));
437            if let Some(lt) = &r.lifetime {
438                nodes.push(Node::Lifetime(lt.to_string()));
439                nodes.push(Node::Space);
440            }
441            if r.mutability.is_some() {
442                nodes.push(Node::Keyword("mut"));
443                nodes.push(Node::Space);
444            }
445            nodes.extend(nodes_for_type(&r.elem));
446        }
447        Type::Slice(s) => {
448            nodes.push(Node::Punctuation("["));
449            nodes.extend(nodes_for_type(&s.elem));
450            nodes.push(Node::Punctuation("]"));
451        }
452        Type::TraitObject(t) => {
453            nodes.push(Node::Keyword("dyn"));
454            nodes.push(Node::Space);
455            nodes.extend(nodes_for_type_param_bounds(&t.bounds));
456        }
457        Type::Tuple(t) => {
458            nodes.push(Node::Punctuation("("));
459            for elem in &t.elems {
460                nodes.extend(nodes_for_type(elem));
461                nodes.push(Node::Punctuation(", "));
462            }
463            if !t.elems.is_empty() {
464                nodes.pop();
465            }
466            nodes.push(Node::Punctuation(")"));
467        }
468        Type::Verbatim(_) => {}
469        x => panic!("Unsupported type category {:?}", x),
470    }
471
472    nodes
473}
474
475/// Create nodes for a lifetime parameter.
476fn nodes_for_lifetime_param(lifetime_param: &LifetimeParam) -> Vec<Node> {
477    let mut nodes = vec![Node::Lifetime(lifetime_param.lifetime.to_string())];
478    if lifetime_param.colon_token.is_some() {
479        nodes.push(Node::Punctuation(": "));
480        for bound in &lifetime_param.bounds {
481            nodes.push(Node::Lifetime(bound.to_string()));
482            nodes.push(Node::Punctuation(" + "));
483        }
484        nodes.pop();
485    }
486
487    nodes
488}
489
490/// Create nodes for bound lifetimes.
491fn nodes_for_bound_lifetimes(bound_lts: &BoundLifetimes) -> Vec<Node> {
492    let mut nodes = vec![];
493    nodes.extend_from_slice(&[Node::Keyword("for"), Node::Punctuation("<")]);
494    for lt in &bound_lts.lifetimes {
495        nodes.extend(nodes_for_generic_param(lt));
496        nodes.push(Node::Punctuation(", "));
497    }
498    nodes.pop();
499    nodes.extend_from_slice(&[Node::Punctuation(">"), Node::Space]);
500    nodes
501}
502
503/// Create nodes for a type parameter binding.
504fn nodes_for_type_param_bound(type_param_bound: &TypeParamBound) -> Vec<Node> {
505    let mut nodes = vec![];
506    match type_param_bound {
507        TypeParamBound::Trait(t) => {
508            if t.paren_token.is_some() {
509                nodes.push(Node::Punctuation("("));
510            }
511            if matches!(t.modifier, TraitBoundModifier::Maybe(_)) {
512                nodes.push(Node::Punctuation("?"));
513            }
514            if let Some(blt) = &t.lifetimes {
515                nodes.extend(nodes_for_bound_lifetimes(blt));
516            }
517            nodes.extend(nodes_for_path(&t.path));
518            if t.paren_token.is_some() {
519                nodes.push(Node::Punctuation(")"));
520            }
521        }
522        TypeParamBound::Lifetime(lt) => {
523            nodes.push(Node::Lifetime(lt.to_string()));
524        }
525        TypeParamBound::Verbatim(_) => {}
526        x => {
527            panic!("Unsupported bound type {:?}", x)
528        }
529    }
530
531    nodes
532}
533
534/// Create nodes for all type parameters in a binding.
535fn nodes_for_type_param_bounds(
536    type_param_bounds: &Punctuated<TypeParamBound, Token![+]>,
537) -> Vec<Node> {
538    let mut nodes = vec![];
539    for bound in type_param_bounds {
540        nodes.extend(nodes_for_type_param_bound(bound));
541        nodes.push(Node::Punctuation(" + "))
542    }
543    nodes.pop();
544    nodes
545}
546
547/// Create nodes for a type parameter, along with its bounds.
548fn nodes_for_type_param(type_param: &TypeParam) -> Vec<Node> {
549    let mut nodes = vec![Node::Name(type_param.ident.to_string())];
550    if type_param.colon_token.is_some() {
551        nodes.push(Node::Punctuation(": "));
552        nodes.extend(nodes_for_type_param_bounds(&type_param.bounds));
553    }
554
555    nodes
556}
557
558/// Create nodes for a generic parameter, along with its bounds.
559fn nodes_for_generic_param(generic_param: &GenericParam) -> Vec<Node> {
560    match generic_param {
561        GenericParam::Lifetime(lt) => nodes_for_lifetime_param(lt),
562        GenericParam::Type(ty) => nodes_for_type_param(ty),
563        GenericParam::Const(c) => {
564            let mut nodes = vec![
565                Node::Keyword("const"),
566                Node::Space,
567                Node::Name(c.ident.to_string()),
568                Node::Punctuation(": "),
569            ];
570            nodes.extend(nodes_for_type(&c.ty));
571
572            nodes
573        }
574    }
575}
576
577/// Create nodes for generics declared for an item.
578///
579/// The function does not create nodes for the where clause of the generics.
580/// Use :rust:fn:`nodes_for_where_clause` to generate nodes for it.
581pub(crate) fn nodes_for_generics(generics: &Generics) -> Vec<Node> {
582    if generics.params.is_empty() {
583        return vec![];
584    }
585
586    let mut nodes = vec![Node::Punctuation("<")];
587
588    for generic in &generics.params {
589        nodes.extend(nodes_for_generic_param(generic));
590        nodes.push(Node::Punctuation(", "));
591    }
592
593    // Remove last ", " and add the closing >
594    nodes.pop();
595    nodes.push(Node::Punctuation(">"));
596
597    nodes
598}
599
600/// Create nodes for the where clause of generics for an item.
601///
602/// The created nodes will insert a newline node as the first node, and
603/// between each predicate.
604pub(crate) fn nodes_for_where_clause(where_clause: &WhereClause) -> Vec<Node> {
605    let mut nodes = vec![Node::Newline, Node::Keyword("where")];
606    for predicate in &where_clause.predicates {
607        nodes.extend_from_slice(&[Node::Newline, Node::Indent]);
608        match predicate {
609            WherePredicate::Lifetime(lt) => {
610                nodes.extend_from_slice(&[
611                    Node::Lifetime(lt.lifetime.to_string()),
612                    Node::Punctuation(": "),
613                ]);
614                for bound in &lt.bounds {
615                    nodes.extend_from_slice(&[
616                        Node::Lifetime(bound.to_string()),
617                        Node::Punctuation(" + "),
618                    ]);
619                }
620                nodes.pop();
621            }
622            WherePredicate::Type(ty) => {
623                if let Some(blt) = &ty.lifetimes {
624                    nodes.extend(nodes_for_bound_lifetimes(blt));
625                }
626                nodes.extend(nodes_for_type(&ty.bounded_ty));
627                nodes.push(Node::Punctuation(": "));
628                nodes.extend(nodes_for_type_param_bounds(&ty.bounds));
629            }
630            x => {
631                panic!("Unknown where predicate type {:?}", x)
632            }
633        }
634        nodes.push(Node::Punctuation(","))
635    }
636    nodes.pop();
637
638    nodes
639}
640
641/// Create nodes for a type pattern binding.
642pub(crate) fn nodes_for_pat_type(pat_type: &PatType) -> Vec<Node> {
643    let mut nodes = vec![];
644    nodes.extend(nodes_for_pat(&pat_type.pat));
645    nodes.push(Node::Punctuation(": "));
646    nodes.extend(nodes_for_type(&pat_type.ty));
647    nodes
648}
649
650/// Create nodes for a pattern binding.
651fn nodes_for_pat(pat: &Pat) -> Vec<Node> {
652    let mut nodes = vec![];
653    match pat {
654        Pat::Const(_) => {
655            nodes.push(Node::Keyword("<const block>"));
656        }
657        Pat::Ident(i) => {
658            if i.by_ref.is_some() {
659                nodes.push(Node::Keyword("ref"));
660                nodes.push(Node::Space);
661            }
662            if i.mutability.is_some() {
663                nodes.push(Node::Keyword("mut"));
664                nodes.push(Node::Space);
665            }
666            nodes.push(Node::Name(i.ident.to_string()));
667        }
668        Pat::Lit(l) => nodes.extend(nodes_for_expr_lit(l)),
669        Pat::Macro(_) => nodes.push(Node::Literal("macro".into())),
670        Pat::Or(o) => {
671            if o.leading_vert.is_some() {
672                nodes.push(Node::Operator("| "));
673            }
674            for case in &o.cases {
675                nodes.extend(nodes_for_pat(case));
676                nodes.push(Node::Operator(" | "));
677            }
678            nodes.pop();
679        }
680        Pat::Paren(p) => {
681            nodes.push(Node::Punctuation("("));
682            nodes.extend(nodes_for_pat(&p.pat));
683            nodes.push(Node::Punctuation(")"));
684        }
685        Pat::Path(p) => {
686            // TODO: Figure out whether supporting QSelf if necessary or not
687            nodes.extend(nodes_for_path(&p.path))
688        }
689        Pat::Range(_) => {
690            nodes.push(Node::Literal("range".into()));
691        }
692        Pat::Reference(r) => {
693            nodes.push(Node::Punctuation("&"));
694            if r.mutability.is_some() {
695                nodes.push(Node::Keyword("mut"));
696            }
697            nodes.push(Node::Space);
698            nodes.extend(nodes_for_pat(&r.pat))
699        }
700        Pat::Rest(_) => {
701            nodes.push(Node::Operator(".."));
702        }
703        Pat::Slice(s) => {
704            nodes.push(Node::Punctuation("["));
705            for pat in &s.elems {
706                nodes.extend(nodes_for_pat(pat));
707                nodes.push(Node::Punctuation(", "));
708            }
709            nodes.pop();
710            nodes.push(Node::Punctuation("]"));
711        }
712        Pat::Struct(s) => {
713            // TODO: Figure out whether supporting QSelf if necessary or not
714            // TODO: Figure out whether listing fields is necessary or not
715            nodes.extend(nodes_for_path(&s.path));
716            nodes.push(Node::Space);
717            nodes.push(Node::Punctuation("{..}"));
718        }
719        Pat::Tuple(t) => {
720            nodes.push(Node::Punctuation("("));
721            for pat in &t.elems {
722                nodes.extend(nodes_for_pat(pat));
723                nodes.push(Node::Punctuation(", "));
724            }
725            nodes.pop();
726            nodes.push(Node::Punctuation(")"));
727        }
728        Pat::TupleStruct(ts) => {
729            // TODO: Figure out whether supporting QSelf if necessary or not
730            nodes.extend(nodes_for_path(&ts.path));
731            nodes.push(Node::Punctuation("("));
732            for pat in &ts.elems {
733                nodes.extend(nodes_for_pat(pat));
734                nodes.push(Node::Punctuation(", "));
735            }
736            nodes.pop();
737            nodes.push(Node::Punctuation(")"));
738        }
739        Pat::Type(t) => {
740            nodes.extend(nodes_for_pat_type(t));
741        }
742        Pat::Verbatim(_) => {}
743        Pat::Wild(_) => {
744            nodes.push(Node::Punctuation("_"));
745        }
746        x => panic!("Unsupported pattern type {:?} in fn inputs", x),
747    }
748    nodes
749}
750
751/// Create nodes for the return type of function.
752pub(crate) fn nodes_for_return_type(return_type: &ReturnType) -> Vec<Node> {
753    let mut nodes = vec![];
754    if let ReturnType::Type(_, ty) = return_type {
755        nodes.extend_from_slice(&[Node::Space, Node::Returns, Node::Space]);
756        nodes.extend(nodes_for_type(ty));
757    }
758
759    nodes
760}
761
762/// Create nodes for a bare fn type.
763pub(crate) fn nodes_for_bare_fn(bare_fn: &TypeBareFn) -> Vec<Node> {
764    let mut nodes = Vec::new();
765    if bare_fn.unsafety.is_some() {
766        nodes.push(Node::Keyword("unsafe"));
767        nodes.push(Node::Space);
768    }
769    nodes.extend(nodes_for_abi_opt(&bare_fn.abi));
770    nodes.push(Node::Keyword("fn"));
771    nodes.push(Node::Space);
772
773    // Nodes for arguments
774    nodes.push(Node::Punctuation("("));
775    for arg in &bare_fn.inputs {
776        nodes.extend(nodes_for_type(&arg.ty));
777        nodes.push(Node::Punctuation(", "));
778    }
779
780    // If variadic, add the "..." otherwise remove the last ", ".
781    if bare_fn.variadic.is_some() {
782        nodes.push(Node::Punctuation("..."));
783    }
784    else if !bare_fn.inputs.is_empty() {
785        nodes.pop();
786    }
787    // Closing parenthesis
788    nodes.push(Node::Punctuation(")"));
789
790    // Return type
791    nodes.extend(nodes_for_return_type(&bare_fn.output));
792
793    nodes
794}