pub(crate) fn is_simple_accessor_body(syn_func: &syn::ItemFn) -> bool {
if !has_immutable_self_receiver(syn_func) {
return false;
}
let stmts = &syn_func.block.stmts;
if stmts.is_empty() {
return false;
}
match stmts.len() {
1 => {
match &stmts[0] {
syn::Stmt::Expr(expr, _) => is_simple_accessor_expr(expr),
_ => false,
}
}
2 => {
is_simple_binding_pattern(stmts)
}
_ => false, }
}
fn is_simple_accessor_expr(expr: &syn::Expr) -> bool {
match expr {
syn::Expr::Field(field_expr) => {
matches!(&*field_expr.base, syn::Expr::Path(path)
if path.path.is_ident("self"))
}
syn::Expr::Reference(ref_expr) => is_simple_accessor_expr(&ref_expr.expr),
syn::Expr::MethodCall(method_call) => {
is_simple_accessor_expr(&method_call.receiver)
&& is_simple_accessor_method(&method_call.method)
}
syn::Expr::Match(_) | syn::Expr::If(_) => {
true
}
_ => false,
}
}
fn is_simple_accessor_method(method: &syn::Ident) -> bool {
matches!(
method.to_string().as_str(),
"clone" | "to_string" | "as_ref" | "as_str" | "as_bytes" | "copied"
)
}
pub(crate) fn has_immutable_self_receiver(syn_func: &syn::ItemFn) -> bool {
if let Some(syn::FnArg::Receiver(receiver)) = syn_func.sig.inputs.first() {
receiver.mutability.is_none()
} else {
false
}
}
fn is_simple_binding_pattern(stmts: &[syn::Stmt]) -> bool {
if stmts.len() != 2 {
return false;
}
let _binding = match &stmts[0] {
syn::Stmt::Local(_) => true,
_ => return false,
};
matches!(&stmts[1], syn::Stmt::Expr(_, _))
}