zen_expression/intellisense/
mod.rs1use 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 ..Default::default()
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(|| 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.shallow_clone(),
100 root_data: data.shallow_clone(),
101 current_data: data.shallow_clone(),
102 ..Default::default()
103 },
104 );
105
106 let results = RefCell::new(Vec::new());
107 ast.walk(|node| {
108 let addr = node as *const Node as usize;
109 let mut r = results.borrow_mut();
110 let typ = type_data.get_type(node);
111
112 r.push(IntelliSenseToken {
113 span: metadata.get(&addr).map(|s| s.span).unwrap_or_default(),
114 node_kind: node.into(),
115 error: typ.map(|t| t.error.clone()).flatten(),
116 kind: typ
117 .map(|t| t.kind.clone())
118 .unwrap_or_else(|| VariableType::Any),
119 });
120 });
121
122 self.arena.with_mut(|a| a.reset());
123 Some(results.into_inner())
124 }
125}
126
127#[cfg(test)]
128mod tests {
129 use crate::intellisense::IntelliSense;
130 use crate::variable::VariableType;
131 use serde_json::json;
132
133 #[test]
134 fn sample_test() {
135 let mut is = IntelliSense::new();
136
137 let data = json!({ "customer": { "firstName": "John", "lastName": "Doe", "array": [{"a": 5}, {"a": 6}] } });
138 let data_type: VariableType = data.into();
139
140 let typ = is.type_check("customer.array[0]", &data_type);
141 println!("{:?}", typ);
142 }
143
144 #[test]
145 fn sample_test_unary() {
146 let mut is = IntelliSense::new();
147
148 let data = json!({ "customer": { "firstName": "John", "lastName": "Doe" }, "$": 10});
149 let data_type: VariableType = data.into();
150
151 let typ = is.type_check_unary("> 10", &data_type);
152 println!("{typ:?}");
153 }
154}