Skip to main content

dry4rust/rust/normalizer/
normalize.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;
8
9use syn::Block;
10use syn::ExprClosure;
11use syn::ImplItemFn;
12use syn::ItemFn;
13use syn::ItemImpl;
14use syn::Signature;
15
16impl NormalizationContext {
17    pub fn normalize_signature(&mut self, sig: &Signature) -> NormalizedNode {
18        // FnSignature -> [return_type_or_None, param0, param1, ...]
19        let return_type = match &sig.output {
20            syn::ReturnType::Default => NormalizedNode::none(),
21            syn::ReturnType::Type(_, ty) => self.normalize_type(ty),
22        };
23        let mut children = vec![return_type];
24        children.extend(sig.inputs.iter().map(|arg| match arg {
25            syn::FnArg::Receiver(r) => {
26                let idx = self.placeholder("self", PlaceholderKind::Variable);
27                let self_node =
28                    NormalizedNode::leaf(NodeKind::Placeholder(PlaceholderKind::Variable, idx));
29                if r.reference.is_some() {
30                    NormalizedNode::with_children(
31                        NodeKind::Reference {
32                            mutable: r.mutability.is_some(),
33                        },
34                        vec![self_node],
35                    )
36                } else {
37                    self_node
38                }
39            }
40            syn::FnArg::Typed(pt) => {
41                let pat = self.normalize_pat(&pt.pat);
42                let ty = self.normalize_type(&pt.ty);
43                NormalizedNode::with_children(NodeKind::FieldValue, vec![pat, ty])
44            }
45        }));
46        NormalizedNode::with_children(NodeKind::FnSignature, children)
47    }
48}
49
50// -- Public entry points ------------------------------------------------------
51
52fn normalize_fn_parts(sig: &Signature, block: &Block) -> (NormalizedNode, NormalizedNode) {
53    let mut ctx = NormalizationContext::new();
54    let sig = ctx.normalize_signature(sig);
55    let body = ctx.normalize_block(block);
56    (sig, body)
57}
58
59/// Normalize a top-level function.
60#[must_use]
61pub fn normalize_item_fn(func: &ItemFn) -> (NormalizedNode, NormalizedNode) {
62    normalize_fn_parts(&func.sig, &func.block)
63}
64
65/// Normalize a method within an impl block.
66#[must_use]
67pub fn normalize_impl_item_fn(method: &ImplItemFn) -> (NormalizedNode, NormalizedNode) {
68    normalize_fn_parts(&method.sig, &method.block)
69}
70
71/// Normalize a closure expression.
72#[must_use]
73pub fn normalize_closure_expr(closure: &ExprClosure) -> NormalizedNode {
74    let mut ctx = NormalizationContext::new();
75    let mut children = vec![ctx.normalize_expr(&closure.body)];
76    children.extend(closure.inputs.iter().map(|p| ctx.normalize_pat(p)));
77    NormalizedNode::with_children(NodeKind::Closure, children)
78}
79
80/// Normalize an impl block -- normalizes each method body.
81#[must_use]
82pub fn normalize_impl_block(imp: &ItemImpl) -> Vec<(String, NormalizedNode, NormalizedNode)> {
83    imp.items
84        .iter()
85        .filter_map(|item| {
86            if let syn::ImplItem::Fn(method) = item {
87                let name = method.sig.ident.to_string();
88                let (sig, body) = normalize_impl_item_fn(method);
89                Some((name, sig, body))
90            } else {
91                None
92            }
93        })
94        .collect()
95}