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