Skip to main content

sim_codec_typescript/
types.rs

1//! Public TypeScript extension data.
2
3use sim_codec_javascript::{Node, Span, Token};
4
5/// TypeScript or TSX input mode.
6#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum Language {
8    /// TypeScript module notation.
9    TypeScript,
10    /// TypeScript with JSX notation.
11    Tsx,
12}
13
14/// Resource limits for the extension scan.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct Limits {
17    /// Maximum source bytes.
18    pub max_bytes: usize,
19    /// Maximum extension nodes.
20    pub max_nodes: usize,
21    /// Maximum delimiter nesting.
22    pub max_nesting: usize,
23}
24impl Default for Limits {
25    fn default() -> Self {
26        Self {
27            max_bytes: 4 * 1024 * 1024,
28            max_nodes: 1_000_000,
29            max_nesting: 256,
30        }
31    }
32}
33
34/// TypeScript-only concrete syntax category.
35#[derive(Clone, Copy, Debug, Eq, PartialEq)]
36pub enum SyntaxKind {
37    /// `interface`, `type`, `enum`, `namespace`, or ambient declaration.
38    Declaration,
39    /// A `: Type` annotation.
40    Annotation,
41    /// A generic parameter or argument list.
42    TypeArguments,
43    /// A TypeScript type node or operator.
44    TypeNode,
45    /// A TypeScript declaration/member modifier.
46    Modifier,
47    /// A JSX element, fragment, attribute, expression, or text region.
48    Jsx,
49}
50
51/// A syntax node in the composed tree.
52#[derive(Clone, Debug, Eq, PartialEq)]
53pub enum SyntaxNode {
54    /// An unchanged ECMAScript node produced by the JavaScript frontend.
55    JavaScript(Node),
56    /// TypeScript-only notation layered over JavaScript.
57    TypeScript {
58        /// Extension category.
59        kind: SyntaxKind,
60        /// Exact byte range in the source.
61        span: Span,
62        /// Parser context recorded at the node.
63        context: Vec<String>,
64    },
65}
66
67/// Complete lossless composed syntax tree.
68#[derive(Clone, Debug, Eq, PartialEq)]
69pub struct SyntaxTree {
70    pub(crate) source: String,
71    /// Selected language mode.
72    pub language: Language,
73    /// Lossless JavaScript token seam, including trivia.
74    pub tokens: Vec<Token>,
75    /// JavaScript and TypeScript nodes.
76    pub nodes: Vec<SyntaxNode>,
77}
78impl SyntaxTree {
79    /// Returns the exact admitted input.
80    #[must_use]
81    pub fn source(&self) -> &str {
82        &self.source
83    }
84    /// Re-emits the admitted input byte-for-byte.
85    #[must_use]
86    pub fn preserve_source(&self) -> String {
87        self.source.clone()
88    }
89}
90
91/// Stable diagnostic category.
92#[derive(Clone, Copy, Debug, Eq, PartialEq)]
93pub enum DiagnosticCode {
94    /// A configured resource bound was crossed.
95    ResourceLimit,
96    /// Delimiters, strings, comments, templates, or JSX were not closed.
97    UnclosedSyntax,
98    /// JSX notation was used outside TSX mode.
99    JsxInTypeScript,
100}
101
102/// Deterministic located frontend failure.
103#[derive(Clone, Debug, Eq, PartialEq)]
104pub struct Diagnostic {
105    /// Stable category.
106    pub code: DiagnosticCode,
107    /// Offending source range.
108    pub span: Span,
109    /// One-based line.
110    pub line: usize,
111    /// Zero-based Unicode-scalar column.
112    pub column: usize,
113    /// Stable detail.
114    pub message: String,
115}
116impl std::fmt::Display for Diagnostic {
117    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
118        write!(f, "{}:{}: {}", self.line, self.column, self.message)
119    }
120}
121impl std::error::Error for Diagnostic {}