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