Skip to main content

dry4rust/rust/normalizer/
pat.rs

1// Copyright (c) 2026 Matjaz Domen Pecan
2// Copyright 2026 Umberto Gotti <umberto.gotti@umbertogotti.dev>
3// Licensed under the MIT License
4// SPDX-License-Identifier: MIT
5
6use crate::node::{NodeKind, NormalizedNode, PlaceholderKind};
7use crate::normalization_context::NormalizationContext;
8use syn::Pat;
9use syn::Type;
10
11use super::helpers::{member_to_string, normalize_lit};
12
13impl NormalizationContext {
14    pub fn normalize_type(&mut self, ty: &Type) -> NormalizedNode {
15        match ty {
16            Type::Path(tp) => {
17                // Single-segment paths become type placeholders
18                if tp.qself.is_none() && tp.path.segments.len() == 1 {
19                    let seg = &tp.path.segments[0];
20                    let idx = self.placeholder(&seg.ident.to_string(), PlaceholderKind::Type);
21                    NormalizedNode::leaf(NodeKind::TypePlaceholder(PlaceholderKind::Type, idx))
22                } else {
23                    let segments: Vec<NormalizedNode> = tp
24                        .path
25                        .segments
26                        .iter()
27                        .map(|seg| {
28                            let idx =
29                                self.placeholder(&seg.ident.to_string(), PlaceholderKind::Type);
30                            NormalizedNode::leaf(NodeKind::TypePlaceholder(
31                                PlaceholderKind::Type,
32                                idx,
33                            ))
34                        })
35                        .collect();
36                    NormalizedNode::with_children(NodeKind::TypePath, segments)
37                }
38            }
39            Type::Reference(r) => NormalizedNode::with_children(
40                NodeKind::TypeReference {
41                    mutable: r.mutability.is_some(),
42                },
43                vec![self.normalize_type(&r.elem)],
44            ),
45            Type::Tuple(t) => {
46                if t.elems.is_empty() {
47                    NormalizedNode::leaf(NodeKind::TypeUnit)
48                } else {
49                    NormalizedNode::with_children(
50                        NodeKind::TypeTuple,
51                        t.elems.iter().map(|e| self.normalize_type(e)).collect(),
52                    )
53                }
54            }
55            Type::Slice(s) => NormalizedNode::with_children(
56                NodeKind::TypeSlice,
57                vec![self.normalize_type(&s.elem)],
58            ),
59            Type::Array(a) => NormalizedNode::with_children(
60                NodeKind::TypeArray,
61                vec![self.normalize_type(&a.elem), self.normalize_expr(&a.len)],
62            ),
63            Type::ImplTrait(i) => NormalizedNode::with_children(
64                NodeKind::TypeImplTrait,
65                i.bounds
66                    .iter()
67                    .filter_map(|b| {
68                        if let syn::TypeParamBound::Trait(t) = b {
69                            let segments: Vec<NormalizedNode> = t
70                                .path
71                                .segments
72                                .iter()
73                                .map(|seg| {
74                                    let idx = self
75                                        .placeholder(&seg.ident.to_string(), PlaceholderKind::Type);
76                                    NormalizedNode::leaf(NodeKind::TypePlaceholder(
77                                        PlaceholderKind::Type,
78                                        idx,
79                                    ))
80                                })
81                                .collect();
82                            Some(if segments.len() == 1 {
83                                segments.into_iter().next().unwrap()
84                            } else {
85                                NormalizedNode::with_children(NodeKind::TypePath, segments)
86                            })
87                        } else {
88                            None
89                        }
90                    })
91                    .collect(),
92            ),
93            Type::Infer(_) => NormalizedNode::leaf(NodeKind::TypeInfer),
94            Type::Never(_) => NormalizedNode::leaf(NodeKind::TypeNever),
95            Type::Paren(p) => self.normalize_type(&p.elem),
96            Type::Macro(tm) => self.normalize_macro(&tm.mac),
97            _ => NormalizedNode::leaf(NodeKind::Opaque),
98        }
99    }
100
101    pub fn normalize_pat(&mut self, pat: &Pat) -> NormalizedNode {
102        match pat {
103            Pat::Ident(pi) => {
104                let idx = self.placeholder(&pi.ident.to_string(), PlaceholderKind::Variable);
105                NormalizedNode::leaf(NodeKind::PatPlaceholder(PlaceholderKind::Variable, idx))
106            }
107            Pat::Wild(_) => NormalizedNode::leaf(NodeKind::PatWild),
108            Pat::Tuple(pt) => NormalizedNode::with_children(
109                NodeKind::PatTuple,
110                pt.elems.iter().map(|p| self.normalize_pat(p)).collect(),
111            ),
112            Pat::TupleStruct(pts) => NormalizedNode::with_children(
113                NodeKind::PatStruct,
114                pts.elems.iter().map(|p| self.normalize_pat(p)).collect(),
115            ),
116            Pat::Struct(ps) => NormalizedNode::with_children(
117                NodeKind::PatStruct,
118                ps.fields
119                    .iter()
120                    .map(|f| {
121                        let value = self.normalize_pat(&f.pat);
122                        let name_idx = self
123                            .placeholder(&member_to_string(&f.member), PlaceholderKind::Variable);
124                        NormalizedNode::with_children(
125                            NodeKind::FieldValue,
126                            vec![
127                                NormalizedNode::leaf(NodeKind::PatPlaceholder(
128                                    PlaceholderKind::Variable,
129                                    name_idx,
130                                )),
131                                value,
132                            ],
133                        )
134                    })
135                    .collect(),
136            ),
137            Pat::Or(po) => NormalizedNode::with_children(
138                NodeKind::PatOr,
139                po.cases.iter().map(|p| self.normalize_pat(p)).collect(),
140            ),
141            Pat::Lit(pl) => {
142                NormalizedNode::with_children(NodeKind::PatLiteral, vec![normalize_lit(&pl.lit)])
143            }
144            Pat::Reference(pr) => NormalizedNode::with_children(
145                NodeKind::PatReference {
146                    mutable: pr.mutability.is_some(),
147                },
148                vec![self.normalize_pat(&pr.pat)],
149            ),
150            Pat::Slice(ps) => NormalizedNode::with_children(
151                NodeKind::PatSlice,
152                ps.elems.iter().map(|p| self.normalize_pat(p)).collect(),
153            ),
154            Pat::Rest(_) => NormalizedNode::leaf(NodeKind::PatRest),
155            // PatRange -> [from_or_None, to_or_None]
156            Pat::Range(pr) => NormalizedNode::with_children(
157                NodeKind::PatRange,
158                vec![
159                    NormalizedNode::opt(pr.start.as_ref().map(|e| self.normalize_expr(e))),
160                    NormalizedNode::opt(pr.end.as_ref().map(|e| self.normalize_expr(e))),
161                ],
162            ),
163            Pat::Path(pp) => {
164                if pp.path.segments.len() == 1 {
165                    let seg = &pp.path.segments[0];
166                    let idx = self.placeholder(&seg.ident.to_string(), PlaceholderKind::Variable);
167                    NormalizedNode::leaf(NodeKind::PatPlaceholder(PlaceholderKind::Variable, idx))
168                } else {
169                    NormalizedNode::with_children(
170                        NodeKind::PatStruct,
171                        pp.path
172                            .segments
173                            .iter()
174                            .map(|seg| {
175                                let idx = self
176                                    .placeholder(&seg.ident.to_string(), PlaceholderKind::Variable);
177                                NormalizedNode::leaf(NodeKind::PatPlaceholder(
178                                    PlaceholderKind::Variable,
179                                    idx,
180                                ))
181                            })
182                            .collect(),
183                    )
184                }
185            }
186            Pat::Type(pt) => self.normalize_pat(&pt.pat),
187            Pat::Macro(pm) => self.normalize_macro(&pm.mac),
188            _ => NormalizedNode::leaf(NodeKind::Opaque),
189        }
190    }
191}