1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
//! Extensions to TypeScript AST elements

use crate::{
    ast::*,
    syntax_node::SyntaxNode,
    SyntaxKind::{self, *},
};

#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub enum TsTypeQueryExpr {
    TsEntityName(TsEntityName),
    TsImport(TsImport),
}

impl AstNode for TsTypeQueryExpr {
    fn can_cast(kind: SyntaxKind) -> bool {
        TsEntityName::can_cast(kind) || TsImport::can_cast(kind)
    }

    fn cast(syntax: SyntaxNode) -> Option<Self> {
        match syntax.kind() {
            n if TsEntityName::can_cast(n) => Some(TsTypeQueryExpr::TsEntityName(
                TsEntityName::cast(syntax).unwrap(),
            )),
            _ => Some(TsTypeQueryExpr::TsImport(TsImport::cast(syntax)?)),
        }
    }

    fn syntax(&self) -> &SyntaxNode {
        match self {
            TsTypeQueryExpr::TsEntityName(it) => it.syntax(),
            TsTypeQueryExpr::TsImport(it) => it.syntax(),
        }
    }
}

impl TsImport {
    pub fn arg(&self) -> Option<SyntaxToken> {
        self.syntax()
            .tokens()
            .into_iter()
            .find(|t| t.kind() == STRING)
    }
}

impl TsMappedTypeParam {
    /// present for alias
    pub fn as_token(&self) -> Option<SyntaxToken> {
        self.syntax()
            .children_with_tokens()
            .filter_map(|x| x.into_token())
            .find(|x| x.kind() == IDENT && x.text() == "as")
    }

    pub fn alias(&self) -> Option<TsType> {
        self.syntax()
            .children()
            .filter_map(|x| x.try_to::<TsType>())
            .nth(1)
    }
}

impl TsExternalModuleRef {
    pub fn string_token(&self) -> Option<SyntaxToken> {
        support::token(self.syntax(), STRING)
    }
}

#[derive(Debug, Clone, PartialEq)]
pub enum TsModuleRef {
    TsExternalModuleRef(TsExternalModuleRef),
    TsEntityName(TsEntityName),
}

impl AstNode for TsModuleRef {
    fn can_cast(kind: SyntaxKind) -> bool {
        kind == TS_EXTERNAL_MODULE_REF || TsEntityName::can_cast(kind)
    }

    fn cast(syntax: SyntaxNode) -> Option<Self> {
        if Self::can_cast(syntax.kind()) {
            None
        } else {
            Some(match syntax.kind() {
                TS_EXTERNAL_MODULE_REF => TsModuleRef::TsExternalModuleRef(syntax.to()),
                _ => TsModuleRef::TsEntityName(syntax.to()),
            })
        }
    }

    fn syntax(&self) -> &SyntaxNode {
        match self {
            TsModuleRef::TsExternalModuleRef(it) => it.syntax(),
            TsModuleRef::TsEntityName(it) => it.syntax(),
        }
    }
}