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