1use crate::{ast::*, kind::TypeScriptSyntaxKind, language::TypeScriptLanguage, lexer::TypeScriptLexer, parser::TypeScriptParser};
2use oak_core::{Builder, BuilderCache, GreenNode, Lexer, OakDiagnostics, OakError, Parser, RedNode, RedTree, SourceText, TextEdit, TokenType, source::Source};
3
4#[derive(Clone)]
6pub struct TypeScriptBuilder<'config> {
7 config: &'config TypeScriptLanguage,
8}
9
10impl<'config> TypeScriptBuilder<'config> {
11 pub fn new(config: &'config TypeScriptLanguage) -> Self {
12 Self { config }
13 }
14}
15
16impl<'config> Builder<TypeScriptLanguage> for TypeScriptBuilder<'config> {
17 fn build<'a, S: Source + ?Sized>(&self, source: &'a S, edits: &[TextEdit], _cache: &'a mut impl BuilderCache<TypeScriptLanguage>) -> OakDiagnostics<TypeScriptRoot> {
18 let parser = TypeScriptParser::new(self.config);
19 let lexer = TypeScriptLexer::new(&self.config);
20
21 let mut session = oak_core::parser::session::ParseSession::<TypeScriptLanguage>::default();
22 lexer.lex(source, edits, &mut session);
23 let parse_result = parser.parse(source, edits, &mut session);
24
25 match parse_result.result {
26 Ok(green_tree) => {
27 let source_text = SourceText::new(source.get_text_in((0..source.length()).into()).into_owned());
28 match self.build_root(green_tree, &source_text) {
29 Ok(ast_root) => OakDiagnostics { result: Ok(ast_root), diagnostics: parse_result.diagnostics },
30 Err(build_error) => {
31 let mut diagnostics = parse_result.diagnostics;
32 diagnostics.push(build_error.clone());
33 OakDiagnostics { result: Err(build_error), diagnostics }
34 }
35 }
36 }
37 Err(parse_error) => OakDiagnostics { result: Err(parse_error), diagnostics: parse_result.diagnostics },
38 }
39 }
40}
41
42impl<'config> TypeScriptBuilder<'config> {
43 pub(crate) fn build_root(&self, green_tree: &GreenNode<TypeScriptLanguage>, source: &SourceText) -> Result<TypeScriptRoot, OakError> {
44 let red_root = RedNode::new(green_tree, 0);
45 let span = red_root.span();
46 let mut statements = Vec::new();
47
48 println!("Root node kind: {:?}", red_root.green.kind);
49
50 if red_root.green.kind == TypeScriptSyntaxKind::SourceFile {
51 for child in red_root.children() {
52 if let RedTree::Node(node) = child {
53 println!(" Root child kind: {:?}", node.green.kind);
54 if let Some(stmt) = self.build_statement(&node, source)? {
55 statements.push(stmt);
56 }
57 }
58 }
59 }
60 else {
61 for child in red_root.children() {
62 if let RedTree::Node(node) = child {
63 println!(" Root child kind (non-sourcefile): {:?}", node.green.kind);
64 if node.green.kind == TypeScriptSyntaxKind::SourceFile {
65 for sub_child in node.children() {
66 if let RedTree::Node(sub_node) = sub_child {
67 println!(" Sub-child kind: {:?}", sub_node.green.kind);
68 if let Some(stmt) = self.build_statement(&sub_node, source)? {
69 statements.push(stmt);
70 }
71 }
72 }
73 }
74 else {
75 if let Some(stmt) = self.build_statement(&node, source)? {
76 statements.push(stmt);
77 }
78 }
79 }
80 }
81 }
82
83 println!("Total statements built: {}", statements.len());
84 Ok(TypeScriptRoot { statements, span: span.into() })
85 }
86
87 fn build_statement(&self, node: &RedNode<TypeScriptLanguage>, source: &SourceText) -> Result<Option<Statement>, OakError> {
88 let kind = node.green.kind;
89 let span = node.span();
90 println!(" Building statement: {:?}", kind);
91
92 match kind {
93 TypeScriptSyntaxKind::SourceFile => {
94 for child in node.children() {
95 if let RedTree::Node(child_node) = child {
96 if let Some(stmt) = self.build_statement(&child_node, source)? {
97 return Ok(Some(stmt));
98 }
99 }
100 }
101 Ok(None)
102 }
103 TypeScriptSyntaxKind::VariableDeclaration => {
104 let mut name = String::new();
105 let mut value = None;
106 for child in node.children() {
107 match child {
108 RedTree::Node(child_node) => {
109 let child_kind = child_node.green.kind;
110 if child_kind == TypeScriptSyntaxKind::IdentifierName {
111 name = source.get_text_in(child_node.span().into()).to_string();
112 }
113 else if child_kind == TypeScriptSyntaxKind::BinaryExpression
114 || child_kind == TypeScriptSyntaxKind::NewExpression
115 || child_kind == TypeScriptSyntaxKind::CallExpression
116 || child_kind == TypeScriptSyntaxKind::MemberExpression
117 || child_kind == TypeScriptSyntaxKind::NumericLiteral
118 || child_kind == TypeScriptSyntaxKind::StringLiteral
119 || child_kind == TypeScriptSyntaxKind::BooleanLiteral
120 || child_kind == TypeScriptSyntaxKind::True
121 || child_kind == TypeScriptSyntaxKind::False
122 || child_kind == TypeScriptSyntaxKind::Null
123 {
124 if value.is_none() {
125 value = self.build_expression(&child_node, source)?;
126 }
127 }
128 else {
129 if value.is_none() {
131 if let Some(expr) = self.build_expression(&child_node, source)? {
132 value = Some(expr);
133 }
134 }
135 }
136 }
137 RedTree::Leaf(leaf) => {
138 if leaf.kind == TypeScriptSyntaxKind::IdentifierName {
139 name = source.get_text_in(leaf.span.into()).to_string();
140 }
141 }
142 }
143 }
144 Ok(Some(Statement::VariableDeclaration(VariableDeclaration { name, value, span: span.into() })))
145 }
146 TypeScriptSyntaxKind::FunctionDeclaration => {
147 let mut name = String::new();
148 let mut params = Vec::new();
149 let mut body = Vec::new();
150
151 for child in node.children() {
152 match child {
153 RedTree::Node(child_node) => {
154 let child_kind = child_node.green.kind;
155 if child_kind == TypeScriptSyntaxKind::IdentifierName {
156 if name.is_empty() {
157 name = source.get_text_in(child_node.span().into()).to_string();
158 }
159 }
160 else if child_kind == TypeScriptSyntaxKind::Parameter {
161 for sub_child in child_node.children() {
162 match sub_child {
163 RedTree::Node(sub_node) => {
164 if sub_node.green.kind == TypeScriptSyntaxKind::IdentifierName {
165 params.push(source.get_text_in(sub_node.span().into()).to_string());
166 }
167 }
168 RedTree::Leaf(leaf) => {
169 if leaf.kind == TypeScriptSyntaxKind::IdentifierName {
170 params.push(source.get_text_in(leaf.span.into()).to_string());
171 }
172 }
173 }
174 }
175 }
176 else if child_kind == TypeScriptSyntaxKind::BlockStatement {
177 for sub_child in child_node.children() {
178 if let RedTree::Node(sub_node) = sub_child {
179 if let Some(s) = self.build_statement(&sub_node, source)? {
180 body.push(s);
181 }
182 }
183 }
184 }
185 }
186 RedTree::Leaf(leaf) => {
187 if leaf.kind == TypeScriptSyntaxKind::IdentifierName {
188 if name.is_empty() {
189 name = source.get_text_in(leaf.span.into()).to_string();
190 }
191 }
192 }
193 }
194 }
195 Ok(Some(Statement::FunctionDeclaration(FunctionDeclaration { name, params, body, span: span.into() })))
196 }
197 TypeScriptSyntaxKind::ClassDeclaration => {
198 let mut name = String::new();
199 let mut extends = None;
200 let mut body = Vec::new();
201
202 for child in node.children() {
203 match child {
204 RedTree::Node(child_node) => {
205 let child_kind = child_node.green.kind;
206 if child_kind == TypeScriptSyntaxKind::IdentifierName {
207 if name.is_empty() {
208 name = source.get_text_in(child_node.span().into()).to_string();
209 }
210 else {
211 extends = Some(source.get_text_in(child_node.span().into()).to_string());
212 }
213 }
214 else if child_kind == TypeScriptSyntaxKind::ClassBody {
215 for member_child in child_node.children() {
217 if let RedTree::Node(member_node) = member_child {
218 let member_kind = member_node.green.kind;
219 let member_span = member_node.span();
220 match member_kind {
221 TypeScriptSyntaxKind::PropertyDeclaration => {
222 let mut prop_name = String::new();
223 let mut prop_type = None;
224 let mut initializer = None;
225 for p_child in member_node.children() {
226 if let RedTree::Node(p_node) = p_child {
227 let p_kind = p_node.green.kind;
228 if p_kind == TypeScriptSyntaxKind::IdentifierName {
229 if prop_name.is_empty() {
230 prop_name = source.get_text_in(p_node.span().into()).to_string();
231 }
232 else {
233 prop_type = Some(source.get_text_in(p_node.span().into()).to_string());
234 }
235 }
236 else if let Some(expr) = self.build_expression(&p_node, source)? {
237 initializer = Some(expr);
238 }
239 }
240 }
241 let prop_name = prop_name.trim();
242 if !prop_name.is_empty() && prop_name != ";" {
243 body.push(ClassMember::Property { name: prop_name.to_string(), ty: prop_type, initializer, span: member_span.into() });
244 }
245 }
246 TypeScriptSyntaxKind::MethodDeclaration | TypeScriptSyntaxKind::ConstructorDeclaration => {
247 let mut meth_name = if member_kind == TypeScriptSyntaxKind::ConstructorDeclaration { "constructor".to_string() } else { String::new() };
248 let mut meth_params = Vec::new();
249 let mut meth_body = Vec::new();
250 for m_child in member_node.children() {
251 if let RedTree::Node(m_node) = m_child {
252 let m_kind = m_node.green.kind;
253 if m_kind == TypeScriptSyntaxKind::IdentifierName && meth_name.is_empty() {
254 meth_name = source.get_text_in(m_node.span().into()).to_string();
255 }
256 else if m_kind == TypeScriptSyntaxKind::Parameter {
257 for param_child in m_node.children() {
258 if let RedTree::Node(pn) = param_child {
259 if pn.green.kind == TypeScriptSyntaxKind::IdentifierName {
260 meth_params.push(source.get_text_in(pn.span().into()).to_string());
261 }
262 }
263 }
264 }
265 else if m_kind == TypeScriptSyntaxKind::BlockStatement {
266 for b_child in m_node.children() {
267 if let RedTree::Node(bn) = b_child {
268 if let Some(s) = self.build_statement(&bn, source)? {
269 meth_body.push(s);
270 }
271 }
272 }
273 }
274 }
275 }
276 let meth_name = meth_name.trim();
277 if !meth_name.is_empty() {
278 body.push(ClassMember::Method { name: meth_name.to_string(), params: meth_params, body: meth_body, span: member_span.into() });
279 }
280 }
281 _ => {}
282 }
283 }
284 }
285 }
286 }
287 _ => {}
288 }
289 }
290 Ok(Some(Statement::ClassDeclaration(ClassDeclaration { name, extends, body, span: span.into() })))
291 }
292 TypeScriptSyntaxKind::ExpressionStatement => {
293 for child in node.children() {
294 if let RedTree::Node(child_node) = child {
295 if let Some(expr) = self.build_expression(&child_node, source)? {
296 return Ok(Some(Statement::ExpressionStatement(expr)));
297 }
298 }
299 }
300 Ok(None)
301 }
302 TypeScriptSyntaxKind::ImportDeclaration => {
303 let mut module_specifier = String::new();
304 let mut imports = Vec::new();
305
306 fn walk_import(node: &RedNode<TypeScriptLanguage>, source: &SourceText, module_specifier: &mut String, imports: &mut Vec<String>) {
307 for child in node.children() {
308 match child {
309 RedTree::Node(child_node) => match child_node.green.kind {
310 TypeScriptSyntaxKind::StringLiteral => {
311 let text = source.get_text_in(child_node.span().into());
312 if text.len() >= 2 {
313 *module_specifier = text[1..text.len() - 1].to_string();
314 }
315 }
316 TypeScriptSyntaxKind::IdentifierName => {
317 imports.push(source.get_text_in(child_node.span().into()).to_string());
318 }
319 _ => walk_import(&child_node, source, module_specifier, imports),
320 },
321 RedTree::Leaf(leaf) => match leaf.kind {
322 TypeScriptSyntaxKind::StringLiteral => {
323 let text = source.get_text_in(leaf.span.into());
324 if text.len() >= 2 {
325 *module_specifier = text[1..text.len() - 1].to_string();
326 }
327 }
328 TypeScriptSyntaxKind::IdentifierName => {
329 imports.push(source.get_text_in(leaf.span.into()).to_string());
330 }
331 _ => {}
332 },
333 }
334 }
335 }
336
337 walk_import(node, source, &mut module_specifier, &mut imports);
338
339 Ok(Some(Statement::ImportDeclaration(ImportDeclaration { module_specifier, imports, span: span.into() })))
340 }
341 TypeScriptSyntaxKind::ExportDeclaration => {
342 for child in node.children() {
343 if let RedTree::Node(child_node) = child {
344 if let Some(stmt) = self.build_statement(&child_node, source)? {
345 return Ok(Some(Statement::ExportDeclaration(ExportDeclaration { declaration: Box::new(stmt), span: span.into() })));
346 }
347 }
348 }
349 Ok(None)
350 }
351 TypeScriptSyntaxKind::ReturnStatement => {
352 let mut value = None;
353 for child in node.children() {
354 if let RedTree::Node(child_node) = child {
355 if let Some(expr) = self.build_expression(&child_node, source)? {
356 value = Some(expr);
357 break;
358 }
359 }
360 }
361 Ok(Some(Statement::ReturnStatement(value)))
362 }
363 _ => Ok(None),
364 }
365 }
366
367 fn build_expression(&self, node: &RedNode<TypeScriptLanguage>, source: &SourceText) -> Result<Option<Expression>, OakError> {
368 let kind = node.green.kind;
369
370 match kind {
371 TypeScriptSyntaxKind::IdentifierName => Ok(Some(Expression::Identifier(source.get_text_in(node.span().into()).to_string()))),
372 TypeScriptSyntaxKind::NumericLiteral => Ok(Some(Expression::NumericLiteral(source.get_text_in(node.span().into()).parse().unwrap_or(0.0)))),
373 TypeScriptSyntaxKind::StringLiteral => {
374 let text = source.get_text_in(node.span().into());
375 if text.len() >= 2 { Ok(Some(Expression::StringLiteral(text[1..text.len() - 1].to_string()))) } else { Ok(Some(Expression::StringLiteral(text.to_string()))) }
376 }
377 TypeScriptSyntaxKind::BigIntLiteral => Ok(Some(Expression::BigIntLiteral(source.get_text_in(node.span().into()).to_string()))),
378 TypeScriptSyntaxKind::True => Ok(Some(Expression::BooleanLiteral(true))),
379 TypeScriptSyntaxKind::False => Ok(Some(Expression::BooleanLiteral(false))),
380 TypeScriptSyntaxKind::CallExpression => {
381 let mut func = None;
382 let mut args = Vec::new();
383 for child in node.children() {
384 if let RedTree::Node(child_node) = child {
385 if func.is_none() {
386 func = self.build_expression(&child_node, source)?;
387 }
388 else if child_node.green.kind == TypeScriptSyntaxKind::CallArgument {
389 for sub_child in child_node.children() {
390 if let RedTree::Node(sub_node) = sub_child {
391 if let Some(arg) = self.build_expression(&sub_node, source)? {
392 args.push(arg);
393 }
394 }
395 }
396 }
397 else if let Some(arg) = self.build_expression(&child_node, source)? {
398 args.push(arg);
399 }
400 }
401 }
402 if let Some(f) = func { Ok(Some(Expression::CallExpression { func: Box::new(f), args })) } else { Ok(None) }
403 }
404
405 TypeScriptSyntaxKind::NewExpression => {
406 let mut func = None;
407 let mut args = Vec::new();
408 for child in node.children() {
409 if let RedTree::Node(child_node) = child {
410 if func.is_none() {
411 func = self.build_expression(&child_node, source)?;
412 }
413 else if child_node.green.kind == TypeScriptSyntaxKind::CallArgument {
414 for sub_child in child_node.children() {
415 if let RedTree::Node(sub_node) = sub_child {
416 if let Some(arg) = self.build_expression(&sub_node, source)? {
417 args.push(arg);
418 }
419 }
420 }
421 }
422 else if let Some(arg) = self.build_expression(&child_node, source)? {
423 args.push(arg);
424 }
425 }
426 }
427 if let Some(f) = func { Ok(Some(Expression::NewExpression { func: Box::new(f), args })) } else { Ok(None) }
428 }
429
430 TypeScriptSyntaxKind::MemberExpression => {
431 let mut object = None;
432 let mut property = None;
433 let mut computed = false;
434 for child in node.children() {
435 match child {
436 RedTree::Node(child_node) => {
437 if object.is_none() {
438 object = self.build_expression(&child_node, source)?;
439 }
440 else {
441 property = self.build_expression(&child_node, source)?;
442 }
443 }
444 RedTree::Leaf(leaf) => {
445 if leaf.kind == TypeScriptSyntaxKind::LeftBracket {
446 computed = true;
447 }
448 }
449 }
450 }
451 if let (Some(obj), Some(prop)) = (object, property) { Ok(Some(Expression::MemberExpression { object: Box::new(obj), property: Box::new(prop), computed, optional: false })) } else { Ok(None) }
452 }
453
454 TypeScriptSyntaxKind::AsExpression => {
455 let mut expression = None;
456 let mut type_annotation = String::new();
457 for child in node.children() {
458 match child {
459 RedTree::Node(child_node) => {
460 if expression.is_none() {
461 expression = self.build_expression(&child_node, source)?;
462 }
463 else {
464 type_annotation = source.get_text_in(child_node.span().into()).to_string();
465 }
466 }
467 RedTree::Leaf(leaf) => {
468 if expression.is_some() && leaf.kind == TypeScriptSyntaxKind::IdentifierName {
469 type_annotation = source.get_text_in(leaf.span.into()).to_string();
470 }
471 }
472 }
473 }
474 if let Some(expr) = expression { Ok(Some(Expression::AsExpression { expression: Box::new(expr), type_annotation })) } else { Ok(None) }
475 }
476
477 TypeScriptSyntaxKind::Null => Ok(Some(Expression::NullLiteral)),
478 TypeScriptSyntaxKind::RegexLiteral => Ok(Some(Expression::RegexLiteral(source.get_text_in(node.span().into()).to_string()))),
479 TypeScriptSyntaxKind::TemplateString => Ok(Some(Expression::TemplateString(source.get_text_in(node.span().into()).to_string()))),
480
481 TypeScriptSyntaxKind::UnaryExpression => {
482 let mut operator = String::new();
483 let mut argument = None;
484 for child in node.children() {
485 match child {
486 RedTree::Leaf(leaf) => {
487 if operator.is_empty() {
488 operator = source.get_text_in(leaf.span.into()).to_string();
489 }
490 }
491 RedTree::Node(child_node) => {
492 argument = self.build_expression(&child_node, source)?;
493 }
494 }
495 }
496 if let Some(arg) = argument { Ok(Some(Expression::UnaryExpression { operator, argument: Box::new(arg) })) } else { Ok(None) }
497 }
498
499 TypeScriptSyntaxKind::BinaryExpression => {
500 let mut left = None;
501 let mut operator = String::new();
502 let mut right = None;
503
504 for child in node.children() {
505 match child {
506 RedTree::Node(child_node) => {
507 if left.is_none() {
508 left = self.build_expression(&child_node, source)?;
509 }
510 else {
511 right = self.build_expression(&child_node, source)?;
512 }
513 }
514 RedTree::Leaf(leaf) => {
515 if left.is_some() && operator.is_empty() && !leaf.kind.is_ignored() {
516 operator = source.get_text_in(leaf.span.into()).to_string();
517 }
518 }
519 }
520 }
521
522 if let (Some(l), Some(r)) = (left, right) {
523 if operator == "="
524 || operator == "+="
525 || operator == "-="
526 || operator == "*="
527 || operator == "/="
528 || operator == "%="
529 || operator == "**="
530 || operator == "<<="
531 || operator == ">>="
532 || operator == ">>>="
533 || operator == "&="
534 || operator == "|="
535 || operator == "^="
536 || operator == "&&="
537 || operator == "||="
538 || operator == "??="
539 {
540 Ok(Some(Expression::AssignmentExpression { left: Box::new(l), operator, right: Box::new(r) }))
541 }
542 else {
543 Ok(Some(Expression::BinaryExpression { left: Box::new(l), operator, right: Box::new(r) }))
544 }
545 }
546 else {
547 Ok(None)
548 }
549 }
550
551 TypeScriptSyntaxKind::ConditionalExpression => {
552 let mut parts = Vec::new();
553 for child in node.children() {
554 if let RedTree::Node(child_node) = child {
555 if let Some(expr) = self.build_expression(&child_node, source)? {
556 parts.push(expr);
557 }
558 }
559 }
560 if parts.len() == 3 {
561 let mut iter = parts.into_iter();
562 Ok(Some(Expression::ConditionalExpression { test: Box::new(iter.next().unwrap()), consequent: Box::new(iter.next().unwrap()), alternate: Box::new(iter.next().unwrap()) }))
563 }
564 else {
565 Ok(None)
566 }
567 }
568
569 _ => {
570 for child in node.children() {
572 if let RedTree::Node(child_node) = child {
573 if let Some(expr) = self.build_expression(&child_node, source)? {
574 return Ok(Some(expr));
575 }
576 }
577 }
578 Ok(None)
579 }
580 }
581 }
582}