use crate::node::{NodeKind, NormalizedNode, PlaceholderKind};
use crate::normalization_context::NormalizationContext;
use super::expr::{normalize_block, normalize_expr};
use super::pat::{normalize_pat, normalize_type};
use syn::Block;
use syn::ExprClosure;
use syn::ImplItemFn;
use syn::ItemFn;
use syn::ItemImpl;
use syn::Signature;
pub fn normalize_signature(sig: &Signature, ctx: &mut NormalizationContext) -> NormalizedNode {
let return_type = match &sig.output {
syn::ReturnType::Default => NormalizedNode::none(),
syn::ReturnType::Type(_, ty) => normalize_type(ty, ctx),
};
let mut children = vec![return_type];
children.extend(sig.inputs.iter().map(|arg| match arg {
syn::FnArg::Receiver(r) => {
let idx = ctx.placeholder("self", PlaceholderKind::Variable);
let self_node =
NormalizedNode::leaf(NodeKind::Placeholder(PlaceholderKind::Variable, idx));
if r.reference.is_some() {
NormalizedNode::with_children(
NodeKind::Reference {
mutable: r.mutability.is_some(),
},
vec![self_node],
)
} else {
self_node
}
}
syn::FnArg::Typed(pt) => {
let pat = normalize_pat(&pt.pat, ctx);
let ty = normalize_type(&pt.ty, ctx);
NormalizedNode::with_children(NodeKind::FieldValue, vec![pat, ty])
}
}));
NormalizedNode::with_children(NodeKind::FnSignature, children)
}
fn normalize_fn_parts(sig: &Signature, block: &Block) -> (NormalizedNode, NormalizedNode) {
let mut ctx = NormalizationContext::new();
let sig = normalize_signature(sig, &mut ctx);
let body = normalize_block(block, &mut ctx);
(sig, body)
}
#[must_use]
pub fn normalize_item_fn(func: &ItemFn) -> (NormalizedNode, NormalizedNode) {
normalize_fn_parts(&func.sig, &func.block)
}
#[must_use]
pub fn normalize_impl_item_fn(method: &ImplItemFn) -> (NormalizedNode, NormalizedNode) {
normalize_fn_parts(&method.sig, &method.block)
}
#[must_use]
pub fn normalize_closure_expr(closure: &ExprClosure) -> NormalizedNode {
let mut ctx = NormalizationContext::new();
let mut children = vec![normalize_expr(&closure.body, &mut ctx)];
children.extend(closure.inputs.iter().map(|p| normalize_pat(p, &mut ctx)));
NormalizedNode::with_children(NodeKind::Closure, children)
}
#[must_use]
pub fn normalize_impl_block(imp: &ItemImpl) -> Vec<(String, NormalizedNode, NormalizedNode)> {
imp.items
.iter()
.filter_map(|item| {
if let syn::ImplItem::Fn(method) = item {
let name = method.sig.ident.to_string();
let (sig, body) = normalize_impl_item_fn(method);
Some((name, sig, body))
} else {
None
}
})
.collect()
}