yog_script_analyze/ast/
accessor.rs1use super::{Accessor, Name, Param, Type};
6use crate::words::{field, init, set, value};
7
8pub fn accessor_scope(ty: &Type, a: &Accessor, property: bool) -> Vec<Param> {
11 let writes = [set::WORD.text, init::WORD.text].contains(&a.name.text.as_str());
12 let mut names = Vec::new();
13 if writes {
14 names.push(named(value::WORD.text, ty, &a.name));
15 }
16 if property {
17 names.push(named(field::WORD.text, ty, &a.name));
18 }
19 names
20}
21
22pub fn value_param(ty: &Type, at: &Name) -> Param {
24 named(value::WORD.text, ty, at)
25}
26
27fn named(text: &str, ty: &Type, at: &Name) -> Param {
28 Param {
29 params: false,
30 extension: false,
31 pass: None,
32 lifetime: None,
33 ty: ty.clone(),
34 name: Name {
35 text: text.to_string(),
36 span: at.span,
37 },
38 default: None,
39 }
40}
41
42pub fn stores_value(d: &super::Decl) -> bool {
46 match &d.kind {
47 super::DeclKind::Property { accessors, .. } => {
48 accessors.iter().all(|a| a.body.is_none()) && !d.has(super::Modifier::Abstract)
49 }
50 _ => false,
51 }
52}
53
54pub fn keeps_value(accessors: &[Accessor]) -> bool {
58 let bodies = accessors.iter().filter(|a| a.body.is_some()).count();
59 if bodies == 0 {
60 return false;
61 }
62 bodies < accessors.len()
63 || accessors
64 .iter()
65 .filter_map(|a| a.body.as_ref())
66 .any(reaches_field)
67}
68
69fn reaches_field(body: &super::MethodBody) -> bool {
70 let mut found = false;
71 match body {
72 super::MethodBody::Expr(e) => found = names_field(e),
73 super::MethodBody::Block(b) => b
74 .stmts
75 .iter()
76 .for_each(|s| s.each_expr(&mut |e| found |= names_field(e))),
77 }
78 found
79}
80
81fn names_field(e: &super::Expr) -> bool {
82 if matches!(&e.kind, super::ExprKind::Ident(n) if n == field::WORD.text) {
83 return true;
84 }
85 let mut found = false;
86 e.each_child(|c| found |= names_field(c));
87 found
88}