darklua_core/rules/convert_require/
instance_path.rs

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
use crate::nodes::{FieldExpression, FunctionCall, Identifier, Prefix, StringExpression};

use super::RobloxIndexStyle;

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) struct InstancePath {
    root: InstancePathRoot,
    components: Vec<InstancePathComponent>,
}

impl InstancePath {
    pub(crate) fn from_root() -> Self {
        Self {
            root: InstancePathRoot::Root,
            components: Vec::new(),
        }
    }

    pub(crate) fn from_script() -> Self {
        Self {
            root: InstancePathRoot::Script,
            components: Vec::new(),
        }
    }

    pub(crate) fn parent(&mut self) {
        self.components.push(InstancePathComponent::Parent);
    }

    pub(crate) fn child(&mut self, child_name: impl Into<String>) {
        self.components
            .push(InstancePathComponent::Child(child_name.into()));
    }

    pub(crate) fn convert(&self, index_style: &RobloxIndexStyle) -> Prefix {
        let mut components_iter = self.components.iter();

        let mut prefix = match &self.root {
            InstancePathRoot::Root => {
                let mut prefix: Prefix = datamodel_identifier().into();
                if let Some(InstancePathComponent::Child(service_name)) = components_iter.next() {
                    prefix = FunctionCall::from_prefix(prefix)
                        .with_method("GetService")
                        .with_argument(StringExpression::from_value(service_name))
                        .into();
                }
                prefix
            }
            InstancePathRoot::Script => script_identifier().into(),
        };

        for component in components_iter {
            match component {
                InstancePathComponent::Parent => {
                    prefix = get_parent_instance(prefix);
                }
                InstancePathComponent::Child(child_name) => {
                    prefix = index_style.index(prefix, child_name);
                }
            }
        }

        prefix
    }
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum InstancePathRoot {
    Root,
    Script,
}

#[derive(Debug, Clone, PartialEq, Eq)]
pub(crate) enum InstancePathComponent {
    Parent,
    Child(String),
}

pub(crate) fn script_identifier() -> Identifier {
    Identifier::new("script")
}

pub(crate) fn datamodel_identifier() -> Identifier {
    Identifier::new("game")
}

pub(crate) fn get_parent_instance(instance: impl Into<Prefix>) -> Prefix {
    FieldExpression::new(instance.into(), "Parent").into()
}