oak-typescript 0.0.11

TypeScript frontend for Oak
Documentation
use crate::{ast::*, builder::TypeScriptBuilder, language::TypeScriptLanguage, lexer::token_type::TypeScriptTokenType, parser::element_type::TypeScriptElementType};
use oak_core::{OakError, RedNode, RedTree, Source, SourceText};

impl<'config> TypeScriptBuilder<'config> {
    pub(crate) fn build_class_member(&self, node: &RedNode<TypeScriptLanguage>, source: &SourceText) -> Result<Option<ClassMember>, OakError> {
        let kind = node.green.kind;
        let span = node.span();

        match kind {
            TypeScriptElementType::PropertyDeclaration | TypeScriptElementType::PropertySignature => {
                let mut name = String::new();
                let mut ty = None;
                let mut value = None;
                let mut visibility = Visibility::Public;
                let mut is_static = false;
                let mut is_readonly = false;
                let mut is_optional = false;
                let mut decorators = Vec::new();

                for child in node.children() {
                    match child {
                        RedTree::Node(child_node) => {
                            let child_kind = child_node.green.kind;
                            match child_kind {
                                TypeScriptElementType::IdentifierName => {
                                    name = source.get_text_in(child_node.span().into()).to_string();
                                }
                                TypeScriptElementType::TypeAnnotation => {
                                    if !self.erase_types {
                                        ty = self.build_type_annotation(&child_node, source)?;
                                    }
                                }
                                TypeScriptElementType::Decorator => {
                                    if let Some(d) = self.build_decorator(&child_node, source)? {
                                        decorators.push(d);
                                    }
                                }
                                _ => {
                                    if value.is_none() {
                                        value = self.build_expression(&child_node, source)?;
                                    }
                                }
                            }
                        }
                        RedTree::Leaf(leaf) => match leaf.kind {
                            TypeScriptTokenType::Public => visibility = Visibility::Public,
                            TypeScriptTokenType::Private => visibility = Visibility::Private,
                            TypeScriptTokenType::Protected => visibility = Visibility::Protected,
                            TypeScriptTokenType::Static => is_static = true,
                            TypeScriptTokenType::Readonly => is_readonly = true,
                            TypeScriptTokenType::Question => is_optional = true,
                            _ => {}
                        },
                    }
                }
                Ok(Some(ClassMember::Property { decorators, name, ty, initializer: value, visibility: Some(visibility), is_static, is_readonly, is_optional, span: span.into(), is_abstract: false }))
            }
            TypeScriptElementType::MethodDeclaration | TypeScriptElementType::MethodSignature | TypeScriptElementType::Constructor => {
                let mut name = if kind == TypeScriptElementType::Constructor { "constructor".to_string() } else { String::new() };
                let mut type_params = Vec::new();
                let mut params = Vec::new();
                let mut return_type = None;
                let mut body = Vec::new();
                let mut visibility = Visibility::Public;
                let mut is_static = false;
                let mut is_abstract = false;
                let mut is_getter = false;
                let mut is_setter = false;
                let mut is_optional = false;
                let mut decorators = Vec::new();

                for child in node.children() {
                    match child {
                        RedTree::Node(child_node) => {
                            let child_kind = child_node.green.kind;
                            match child_kind {
                                TypeScriptElementType::IdentifierName => {
                                    if name.is_empty() {
                                        name = source.get_text_in(child_node.span().into()).to_string();
                                    }
                                }
                                TypeScriptElementType::TypeParameter => {
                                    if !self.erase_types {
                                        if let Some(tp) = self.build_type_parameter(&child_node, source)? {
                                            type_params.push(tp);
                                        }
                                    }
                                }
                                TypeScriptElementType::Parameter => {
                                    if let Some(p) = self.build_parameter(&child_node, source)? {
                                        params.push(p);
                                    }
                                }
                                TypeScriptElementType::TypeAnnotation => {
                                    if !self.erase_types {
                                        return_type = self.build_type_annotation(&child_node, source)?;
                                    }
                                }
                                TypeScriptElementType::BlockStatement => {
                                    if let Some(Statement::BlockStatement(block)) = self.build_statement(&child_node, source)? {
                                        body = block.statements;
                                    }
                                }
                                TypeScriptElementType::Decorator => {
                                    if let Some(d) = self.build_decorator(&child_node, source)? {
                                        decorators.push(d);
                                    }
                                }
                                _ => {}
                            }
                        }
                        RedTree::Leaf(leaf) => match leaf.kind {
                            TypeScriptTokenType::Public => visibility = Visibility::Public,
                            TypeScriptTokenType::Private => visibility = Visibility::Private,
                            TypeScriptTokenType::Protected => visibility = Visibility::Protected,
                            TypeScriptTokenType::Static => is_static = true,
                            TypeScriptTokenType::Abstract => is_abstract = true,
                            TypeScriptTokenType::Get => is_getter = true,
                            TypeScriptTokenType::Set => is_setter = true,
                            TypeScriptTokenType::Question => is_optional = true,
                            _ => {}
                        },
                    }
                }

                Ok(Some(ClassMember::Method { decorators, name, type_params, params, return_type, body, visibility: Some(visibility), is_static, is_abstract, is_getter, is_setter, is_optional, span: span.into() }))
            }
            _ => Ok(None),
        }
    }
}