use super::{Accessor, Name, Param, Type};
use crate::words::{field, init, set, value};
pub fn accessor_scope(ty: &Type, a: &Accessor, property: bool) -> Vec<Param> {
let writes = [set::WORD.text, init::WORD.text].contains(&a.name.text.as_str());
let mut names = Vec::new();
if writes {
names.push(named(value::WORD.text, ty, &a.name));
}
if property {
names.push(named(field::WORD.text, ty, &a.name));
}
names
}
pub fn value_param(ty: &Type, at: &Name) -> Param {
named(value::WORD.text, ty, at)
}
fn named(text: &str, ty: &Type, at: &Name) -> Param {
Param {
params: false,
extension: false,
pass: None,
lifetime: None,
ty: ty.clone(),
name: Name {
text: text.to_string(),
span: at.span,
},
default: None,
}
}
pub fn stores_value(d: &super::Decl) -> bool {
match &d.kind {
super::DeclKind::Property { accessors, .. } => {
accessors.iter().all(|a| a.body.is_none()) && !d.has(super::Modifier::Abstract)
}
_ => false,
}
}
pub fn keeps_value(accessors: &[Accessor]) -> bool {
let bodies = accessors.iter().filter(|a| a.body.is_some()).count();
if bodies == 0 {
return false;
}
bodies < accessors.len()
|| accessors
.iter()
.filter_map(|a| a.body.as_ref())
.any(reaches_field)
}
fn reaches_field(body: &super::MethodBody) -> bool {
let mut found = false;
match body {
super::MethodBody::Expr(e) => found = names_field(e),
super::MethodBody::Block(b) => b
.stmts
.iter()
.for_each(|s| s.each_expr(&mut |e| found |= names_field(e))),
}
found
}
fn names_field(e: &super::Expr) -> bool {
if matches!(&e.kind, super::ExprKind::Ident(n) if n == field::WORD.text) {
return true;
}
let mut found = false;
e.each_child(|c| found |= names_field(c));
found
}