Skip to main content

luaparse_rs/ast/
types.rs

1//! Luau type annotation nodes.
2//!
3//! These types represent the Luau type system's syntax: named types,
4//! unions, intersections, function types, table types, and more.
5//! They only appear when parsing with [`Luau`](crate::Luau) and using
6//! [`parse_with_types`](crate::Parser::parse_with_types).
7
8use alloc::{boxed::Box, string::String, vec::Vec};
9
10use crate::Span;
11use super::common::Identifier;
12
13/// A single Luau type expression.
14///
15/// Works the same way as [`Expr`](super::expr::Expr): a [`kind`](Self::kind)
16/// telling you what it is, and a [`span`](Self::span) pointing into the source.
17#[derive(Debug, Clone, PartialEq)]
18pub struct TypeExpr {
19    /// What kind of type expression this is.
20    pub kind: TypeExprKind,
21    /// Where it appears in the source.
22    pub span: Span,
23}
24
25impl TypeExpr {
26    pub fn new(kind: TypeExprKind, span: Span) -> Self {
27        Self { kind, span }
28    }
29}
30
31/// All the different kinds of Luau type expression.
32#[derive(Debug, Clone, PartialEq)]
33pub enum TypeExprKind {
34    /// The `nil` type.
35    Nil,
36    /// A singleton boolean type (`true` or `false`).
37    Boolean(bool),
38    /// A singleton string type (e.g. `"success"`).
39    String(String),
40    /// A singleton number type.
41    Number(String),
42
43    /// A named type, possibly with a module path and generics.
44    ///
45    /// Examples: `string`, `React.Element<Props>`, `Module.Type`.
46    Named {
47        /// The dotted path (e.g. `[React, Element]`).
48        path: Vec<Identifier>,
49        /// Optional generic type arguments.
50        generics: Option<Vec<TypeExpr>>,
51    },
52
53    /// A table type: `{x: number, y: number}`.
54    Table(Box<TableType>),
55    /// A function type: `(number, string) -> boolean`.
56    Function(Box<FunctionType>),
57
58    /// A union type: `string | number`.
59    Union(Vec<TypeExpr>),
60    /// An intersection type: `Readable & Writable`.
61    Intersection(Vec<TypeExpr>),
62
63    /// An optional type: `string?` (shorthand for `string | nil`).
64    Optional(Box<TypeExpr>),
65
66    /// A `typeof(expr)` type.
67    Typeof(Box<super::expr::Expr>),
68
69    /// A generic type pack: `T...`.
70    GenericPack(Identifier),
71    /// A variadic type pack: `...number`.
72    VariadicPack(Box<TypeExpr>),
73
74    /// A parenthesized type: `(string)`.
75    Parenthesized(Box<TypeExpr>),
76}
77
78/// A Luau table type: `{x: number, y: number, [string]: any}`.
79#[derive(Debug, Clone, PartialEq)]
80pub struct TableType {
81    /// Named properties (e.g. `x: number`).
82    pub properties: Vec<TableProperty>,
83    /// An optional indexer (e.g. `[string]: any`).
84    pub indexer: Option<Box<TableIndexer>>,
85    /// Where it appears in the source.
86    pub span: Span,
87}
88
89impl TableType {
90    pub fn new(properties: Vec<TableProperty>, indexer: Option<Box<TableIndexer>>, span: Span) -> Self {
91        Self {
92            properties,
93            indexer,
94            span,
95        }
96    }
97}
98
99/// A single property in a table type: `name: Type`.
100#[derive(Debug, Clone, PartialEq)]
101pub struct TableProperty {
102    /// The property name.
103    pub name: Identifier,
104    /// The property's type.
105    pub type_expr: TypeExpr,
106    /// Optional `read` or `write` modifier.
107    pub read_write: Option<ReadWrite>,
108    /// Where it appears in the source.
109    pub span: Span,
110}
111
112impl TableProperty {
113    pub fn new(
114        name: Identifier,
115        type_expr: TypeExpr,
116        read_write: Option<ReadWrite>,
117        span: Span,
118    ) -> Self {
119        Self {
120            name,
121            type_expr,
122            read_write,
123            span,
124        }
125    }
126}
127
128/// A read/write modifier on a table property.
129#[derive(Debug, Clone, Copy, PartialEq, Eq)]
130pub enum ReadWrite {
131    /// `read` access only.
132    Read,
133    /// `write` access only.
134    Write,
135}
136
137/// An indexer in a table type: `[KeyType]: ValueType`.
138#[derive(Debug, Clone, PartialEq)]
139pub struct TableIndexer {
140    /// The key type (e.g. `string` in `[string]: any`).
141    pub key_type: Box<TypeExpr>,
142    /// The value type.
143    pub value_type: Box<TypeExpr>,
144    /// Optional `read` or `write` modifier.
145    pub read_write: Option<ReadWrite>,
146    /// Where it appears in the source.
147    pub span: Span,
148}
149
150impl TableIndexer {
151    pub fn new(
152        key_type: TypeExpr,
153        value_type: TypeExpr,
154        read_write: Option<ReadWrite>,
155        span: Span,
156    ) -> Self {
157        Self {
158            key_type: Box::new(key_type),
159            value_type: Box::new(value_type),
160            read_write,
161            span,
162        }
163    }
164}
165
166/// A function type: `<T>(x: T, y: number) -> T`.
167#[derive(Debug, Clone, PartialEq)]
168pub struct FunctionType {
169    /// Generic type parameters (e.g. `<T, U>`).
170    pub generics: Vec<GenericParameter>,
171    /// The parameter types.
172    pub parameters: Vec<FunctionTypeParameter>,
173    /// The return type.
174    pub return_type: Box<TypeExpr>,
175    /// Where it appears in the source.
176    pub span: Span,
177}
178
179impl FunctionType {
180    pub fn new(
181        generics: Vec<GenericParameter>,
182        parameters: Vec<FunctionTypeParameter>,
183        return_type: TypeExpr,
184        span: Span,
185    ) -> Self {
186        Self {
187            generics,
188            parameters,
189            return_type: Box::new(return_type),
190            span,
191        }
192    }
193}
194
195/// A single parameter in a function type.
196#[derive(Debug, Clone, PartialEq)]
197pub struct FunctionTypeParameter {
198    /// An optional parameter name (e.g. `x` in `x: number`).
199    pub name: Option<Identifier>,
200    /// The parameter's type.
201    pub type_expr: TypeExpr,
202    /// Where it appears in the source.
203    pub span: Span,
204}
205
206impl FunctionTypeParameter {
207    pub fn new(name: Option<Identifier>, type_expr: TypeExpr, span: Span) -> Self {
208        Self {
209            name,
210            type_expr,
211            span,
212        }
213    }
214}
215
216/// A generic type parameter in a declaration or function type.
217///
218/// Examples: `T`, `T...` (type pack), `T = string` (with default).
219#[derive(Debug, Clone, PartialEq)]
220pub struct GenericParameter {
221    /// The parameter name.
222    pub name: Identifier,
223    /// An optional constraint type.
224    pub constraint: Option<TypeExpr>,
225    /// An optional default type.
226    pub default: Option<TypeExpr>,
227    /// `true` if this is a type pack parameter (`T...`).
228    pub is_pack: bool,
229    /// Where it appears in the source.
230    pub span: Span,
231}
232
233impl GenericParameter {
234    pub fn new(
235        name: Identifier,
236        constraint: Option<TypeExpr>,
237        default: Option<TypeExpr>,
238        is_pack: bool,
239        span: Span,
240    ) -> Self {
241        Self {
242            name,
243            constraint,
244            default,
245            is_pack,
246            span,
247        }
248    }
249}
250
251/// A fully resolved `type` or `export type` declaration.
252///
253/// Unlike [`TypeDeclaration`](super::stmt::TypeDeclaration), which only stores
254/// spans, this variant includes the actual parsed type expression. You get
255/// these from [`AstWithTypes::type_declarations`](super::AstWithTypes::type_declarations).
256#[derive(Debug, Clone, PartialEq)]
257pub struct TypeDeclarationFull {
258    /// Whether this was declared with `export`.
259    pub exported: bool,
260    /// The name of the type alias.
261    pub name: Identifier,
262    /// The generic parameters.
263    pub generics: Vec<GenericParameter>,
264    /// The right side type expression.
265    pub type_expr: TypeExpr,
266    /// Where it appears in the source.
267    pub span: Span,
268}
269
270impl TypeDeclarationFull {
271    pub fn new(
272        exported: bool,
273        name: Identifier,
274        generics: Vec<GenericParameter>,
275        type_expr: TypeExpr,
276        span: Span,
277    ) -> Self {
278        Self {
279            exported,
280            name,
281            generics,
282            type_expr,
283            span,
284        }
285    }
286}