darklua_core/rules/convert_require/
instance_path.rs

1use crate::nodes::{FieldExpression, FunctionCall, Identifier, Prefix, StringExpression};
2
3use super::RobloxIndexStyle;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
6pub(crate) struct InstancePath {
7    root: InstancePathRoot,
8    components: Vec<InstancePathComponent>,
9}
10
11impl InstancePath {
12    pub(crate) fn from_root() -> Self {
13        Self {
14            root: InstancePathRoot::Root,
15            components: Vec::new(),
16        }
17    }
18
19    pub(crate) fn from_script() -> Self {
20        Self {
21            root: InstancePathRoot::Script,
22            components: Vec::new(),
23        }
24    }
25
26    pub(crate) fn parent(&mut self) {
27        self.components.push(InstancePathComponent::Parent);
28    }
29
30    pub(crate) fn child(&mut self, child_name: impl Into<String>) {
31        self.components
32            .push(InstancePathComponent::Child(child_name.into()));
33    }
34
35    pub(crate) fn convert(&self, index_style: &RobloxIndexStyle) -> Prefix {
36        let mut components_iter = self.components.iter();
37
38        let mut prefix = match &self.root {
39            InstancePathRoot::Root => {
40                let mut prefix: Prefix = datamodel_identifier().into();
41                if let Some(InstancePathComponent::Child(service_name)) = components_iter.next() {
42                    prefix = FunctionCall::from_prefix(prefix)
43                        .with_method("GetService")
44                        .with_argument(StringExpression::from_value(service_name))
45                        .into();
46                }
47                prefix
48            }
49            InstancePathRoot::Script => script_identifier().into(),
50        };
51
52        for component in components_iter {
53            match component {
54                InstancePathComponent::Parent => {
55                    prefix = get_parent_instance(prefix);
56                }
57                InstancePathComponent::Child(child_name) => {
58                    prefix = index_style.index(prefix, child_name);
59                }
60            }
61        }
62
63        prefix
64    }
65}
66
67#[derive(Debug, Clone, PartialEq, Eq)]
68pub(crate) enum InstancePathRoot {
69    Root,
70    Script,
71}
72
73#[derive(Debug, Clone, PartialEq, Eq)]
74pub(crate) enum InstancePathComponent {
75    Parent,
76    Child(String),
77}
78
79pub(crate) fn script_identifier() -> Identifier {
80    Identifier::new("script")
81}
82
83pub(crate) fn datamodel_identifier() -> Identifier {
84    Identifier::new("game")
85}
86
87pub(crate) fn get_parent_instance(instance: impl Into<Prefix>) -> Prefix {
88    FieldExpression::new(instance.into(), "Parent").into()
89}