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}