mf_expression/intellisense/
mod.rs

1use crate::arena::UnsafeArena;
2use crate::intellisense::scope::IntelliSenseScope;
3use crate::intellisense::types::provider::TypesProvider;
4use crate::lexer::Lexer;
5use crate::parser::{Node, Parser};
6use crate::variable::VariableType;
7use serde::Serialize;
8use std::cell::RefCell;
9use std::rc::Rc;
10
11mod scope;
12mod types;
13
14#[derive(Debug, Serialize)]
15#[serde(rename_all = "camelCase")]
16pub struct IntelliSenseToken {
17    pub span: (u32, u32),
18    pub kind: Rc<VariableType>,
19    pub node_kind: &'static str,
20    pub error: Option<String>,
21}
22
23pub struct IntelliSense<'arena> {
24    arena: UnsafeArena<'arena>,
25    lexer: Lexer<'arena>,
26}
27
28impl<'arena> IntelliSense<'arena> {
29    pub fn new() -> Self {
30        Self { arena: UnsafeArena::new(), lexer: Lexer::new() }
31    }
32
33    pub fn type_check(
34        &mut self,
35        source: &'arena str,
36        data: &VariableType,
37    ) -> Option<Vec<IntelliSenseToken>> {
38        let arena = self.arena.get();
39
40        let tokens = self.lexer.tokenize(source).ok()?;
41        let parser =
42            Parser::try_new(tokens, &arena).map(|p| p.standard()).ok()?;
43
44        let parser_result = parser.with_metadata().parse();
45        let ast = parser_result.root;
46        let metadata = parser_result.metadata?;
47
48        let type_data = TypesProvider::generate(
49            ast,
50            IntelliSenseScope {
51                pointer_data: data,
52                root_data: data,
53                current_data: data,
54            },
55        );
56
57        let results = RefCell::new(Vec::new());
58        ast.walk(|node| {
59            let addr = node as *const Node as usize;
60            let mut r = results.borrow_mut();
61            let typ = type_data.get_type(node);
62
63            r.push(IntelliSenseToken {
64                span: node
65                    .span()
66                    .or_else(|| metadata.get(&addr).map(|s| s.span))
67                    .unwrap_or_default(),
68                node_kind: node.into(),
69                error: typ.map(|t| t.error.clone()).flatten(),
70                kind: typ
71                    .map(|t| t.kind.clone())
72                    .unwrap_or_else(|| Rc::new(VariableType::Any)),
73            });
74        });
75
76        self.arena.with_mut(|a| a.reset());
77        Some(results.into_inner())
78    }
79
80    pub fn type_check_unary(
81        &mut self,
82        source: &'arena str,
83        data: &VariableType,
84    ) -> Option<Vec<IntelliSenseToken>> {
85        let arena = self.arena.get();
86
87        let tokens = self.lexer.tokenize(source).ok()?;
88        let parser = Parser::try_new(tokens, &arena).map(|p| p.unary()).ok()?;
89
90        let parser_result = parser.with_metadata().parse();
91        let ast = parser_result.root;
92        let metadata = parser_result.metadata?;
93
94        let type_data = TypesProvider::generate(
95            ast,
96            IntelliSenseScope {
97                pointer_data: data,
98                root_data: data,
99                current_data: data,
100            },
101        );
102
103        let results = RefCell::new(Vec::new());
104        ast.walk(|node| {
105            let addr = node as *const Node as usize;
106            let mut r = results.borrow_mut();
107            let typ = type_data.get_type(node);
108
109            r.push(IntelliSenseToken {
110                span: metadata.get(&addr).map(|s| s.span).unwrap_or_default(),
111                node_kind: node.into(),
112                error: typ.map(|t| t.error.clone()).flatten(),
113                kind: typ
114                    .map(|t| t.kind.clone())
115                    .unwrap_or_else(|| Rc::new(VariableType::Any)),
116            });
117        });
118
119        self.arena.with_mut(|a| a.reset());
120        Some(results.into_inner())
121    }
122}
123
124#[cfg(test)]
125mod tests {
126    use crate::intellisense::IntelliSense;
127    use crate::variable::VariableType;
128    use serde_json::json;
129
130    #[test]
131    fn sample_test() {
132        let mut is = IntelliSense::new();
133
134        let data = json!({ "customer": { "firstName": "John", "lastName": "Doe", "array": [{"a": 5}, {"a": 6}] } });
135        let data_type: VariableType = data.into();
136
137        let typ = is.type_check("customer.array[0]", &data_type);
138        println!("{:?}", typ);
139    }
140
141    #[test]
142    fn sample_test_unary() {
143        let mut is = IntelliSense::new();
144
145        let data = json!({ "customer": { "firstName": "John", "lastName": "Doe" }, "$": 10});
146        let data_type: VariableType = data.into();
147
148        let typ = is.type_check_unary("> 10", &data_type);
149        println!("{typ:?}");
150    }
151}