Skip to main content

oak_typescript/builder/
mod.rs

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/// TypeScript 语言的 AST 构建器
5#[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                                // Fallback for other potential expression nodes
130                                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                                // Parse class members
216                                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                // 如果是一个包裹节点,递归处理
571                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}