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