Skip to main content

full_moon/ast/
mod.rs

1use std::fmt::Formatter;
2use std::{borrow::Cow, fmt};
3
4use derive_more::Display;
5#[cfg(feature = "serde")]
6use serde::{Deserialize, Serialize};
7
8use full_moon_derive::{Node, Visit};
9#[cfg(any(feature = "lua52", feature = "luajit"))]
10use lua52::*;
11#[cfg(feature = "lua54")]
12use lua54::*;
13
14#[cfg(feature = "luau")]
15use luau::*;
16
17#[cfg(any(feature = "luau", feature = "cfxlua"))]
18mod compound;
19#[cfg(any(feature = "luau", feature = "cfxlua"))]
20pub use compound::*;
21
22pub use parser_structs::AstResult;
23use punctuated::{Pair, Punctuated};
24use span::ContainedSpan;
25pub use versions::*;
26
27use crate::{
28    tokenizer::{Position, Symbol, Token, TokenReference, TokenType},
29    util::*,
30};
31
32mod parser_structs;
33#[macro_use]
34mod parser_util;
35mod parsers;
36pub mod punctuated;
37pub mod span;
38mod update_positions;
39mod visitors;
40
41#[cfg(feature = "luau")]
42pub mod luau;
43#[cfg(feature = "luau")]
44mod luau_visitors;
45mod versions;
46
47#[cfg(any(feature = "lua52", feature = "luajit"))]
48pub mod lua52;
49#[cfg(feature = "lua54")]
50pub mod lua54;
51/// A block of statements, such as in if/do/etc block
52#[derive(Clone, Debug, Default, Display, PartialEq, Node, Visit)]
53#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
54#[display(
55    "{}{}",
56    display_optional_punctuated_vec(stmts),
57    display_option(last_stmt.as_ref().map(display_optional_punctuated))
58)]
59pub struct Block {
60    stmts: Vec<(Stmt, Option<TokenReference>)>,
61    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
62    last_stmt: Option<(LastStmt, Option<TokenReference>)>,
63}
64
65impl Block {
66    /// Creates an empty block
67    pub fn new() -> Self {
68        Self {
69            stmts: Vec::new(),
70            last_stmt: None,
71        }
72    }
73
74    /// An iterator over the statements in the block, such as `local foo = 1`.
75    ///
76    /// Note that this does not contain the final statement which can be
77    /// attained via [`Block::last_stmt`].
78    pub fn stmts(&self) -> impl Iterator<Item = &Stmt> {
79        self.stmts.iter().map(|(stmt, _)| stmt)
80    }
81
82    /// An iterator over the statements in the block, including any optional
83    /// semicolon token reference present
84    pub fn stmts_with_semicolon(&self) -> impl Iterator<Item = &(Stmt, Option<TokenReference>)> {
85        self.stmts.iter()
86    }
87
88    /// The last statement of the block if one exists, such as `return foo`
89    pub fn last_stmt(&self) -> Option<&LastStmt> {
90        Some(&self.last_stmt.as_ref()?.0)
91    }
92
93    /// The last statement of the block if on exists, including any optional semicolon token reference present
94    pub fn last_stmt_with_semicolon(&self) -> Option<&(LastStmt, Option<TokenReference>)> {
95        self.last_stmt.as_ref()
96    }
97
98    /// Returns a new block with the given statements
99    /// Takes a vector of statements, followed by an optional semicolon token reference
100    pub fn with_stmts(self, stmts: Vec<(Stmt, Option<TokenReference>)>) -> Self {
101        Self { stmts, ..self }
102    }
103
104    /// Returns a new block with the given last statement, if one is given
105    /// Takes an optional last statement, with an optional semicolon
106    pub fn with_last_stmt(self, last_stmt: Option<(LastStmt, Option<TokenReference>)>) -> Self {
107        Self { last_stmt, ..self }
108    }
109
110    pub(crate) fn merge_blocks(&mut self, other: Self) {
111        self.stmts.extend(other.stmts);
112
113        if self.last_stmt.is_none() {
114            self.last_stmt = other.last_stmt;
115        }
116    }
117}
118
119/// The last statement of a [`Block`]
120#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
121#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
122#[non_exhaustive]
123pub enum LastStmt {
124    /// A `break` statement
125    Break(TokenReference),
126    /// A continue statement
127    /// Only available when the "luau" feature flag is enabled.
128    #[cfg(feature = "luau")]
129    Continue(TokenReference),
130    /// A `return` statement
131    Return(Return),
132}
133
134/// A `return` statement
135#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
136#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
137#[display("{token}{returns}")]
138pub struct Return {
139    token: TokenReference,
140    returns: Punctuated<Expression>,
141}
142
143impl Return {
144    /// Creates a new empty Return
145    /// Default return token is followed by a single space
146    pub fn new() -> Self {
147        Self {
148            token: TokenReference::basic_symbol("return "),
149            returns: Punctuated::new(),
150        }
151    }
152
153    /// The `return` token
154    pub fn token(&self) -> &TokenReference {
155        &self.token
156    }
157
158    /// The values being returned
159    pub fn returns(&self) -> &Punctuated<Expression> {
160        &self.returns
161    }
162
163    /// Returns a new Return with the given `return` token
164    pub fn with_token(self, token: TokenReference) -> Self {
165        Self { token, ..self }
166    }
167
168    /// Returns a new Return with the given punctuated sequence
169    pub fn with_returns(self, returns: Punctuated<Expression>) -> Self {
170        Self { returns, ..self }
171    }
172}
173
174impl Default for Return {
175    fn default() -> Self {
176        Self::new()
177    }
178}
179
180/// Fields of a [`TableConstructor`]
181#[derive(Clone, Debug, Display, PartialEq, Node)]
182#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
183#[non_exhaustive]
184pub enum Field {
185    /// A key in the format of `[expression] = value`
186    #[display(
187        "{}{}{}{}{}",
188        brackets.tokens().0,
189        key,
190        brackets.tokens().1,
191        equal,
192        value
193    )]
194    ExpressionKey {
195        /// The `[...]` part of `[expression] = value`
196        brackets: ContainedSpan,
197        /// The `expression` part of `[expression] = value`
198        key: Expression,
199        /// The `=` part of `[expression] = value`
200        equal: TokenReference,
201        /// The `value` part of `[expression] = value`
202        value: Expression,
203    },
204
205    /// A key in the format of `name = value`
206    #[display("{key}{equal}{value}")]
207    NameKey {
208        /// The `name` part of `name = value`
209        key: TokenReference,
210        /// The `=` part of `name = value`
211        equal: TokenReference,
212        /// The `value` part of `name = value`
213        value: Expression,
214    },
215
216    /// A set constructor field, such as .a inside { .a } which is equivalent to { a = true }
217    #[display("{dot}{name}")]
218    #[cfg(feature = "cfxlua")]
219    SetConstructor {
220        /// The `.` part of `.a`
221        dot: TokenReference,
222        /// The `a` part of `.a`
223        name: TokenReference,
224    },
225
226    /// A field with no key, just a value (such as `"a"` in `{ "a" }`)
227    #[display("{_0}")]
228    NoKey(Expression),
229}
230
231/// A table being constructed, such as `{ 1, 2, 3 }` or `{ a = 1 }`
232#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
233#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
234#[display("{}{}{}", braces.tokens().0, fields, braces.tokens().1)]
235pub struct TableConstructor {
236    #[node(full_range)]
237    #[visit(contains = "fields")]
238    braces: ContainedSpan,
239    fields: Punctuated<Field>,
240}
241
242impl TableConstructor {
243    /// Creates a new empty TableConstructor
244    /// Brace tokens are followed by spaces, such that { `fields` }
245    pub fn new() -> Self {
246        Self {
247            braces: ContainedSpan::new(
248                TokenReference::basic_symbol("{ "),
249                TokenReference::basic_symbol(" }"),
250            ),
251            fields: Punctuated::new(),
252        }
253    }
254
255    /// The braces of the constructor
256    pub fn braces(&self) -> &ContainedSpan {
257        &self.braces
258    }
259
260    /// Returns the [`Punctuated`] sequence of the fields used to create the table
261    pub fn fields(&self) -> &Punctuated<Field> {
262        &self.fields
263    }
264
265    /// Returns a new TableConstructor with the given braces
266    pub fn with_braces(self, braces: ContainedSpan) -> Self {
267        Self { braces, ..self }
268    }
269
270    /// Returns a new TableConstructor with the given fields
271    pub fn with_fields(self, fields: Punctuated<Field>) -> Self {
272        Self { fields, ..self }
273    }
274}
275
276impl Default for TableConstructor {
277    fn default() -> Self {
278        Self::new()
279    }
280}
281
282/// An anonymous function, such as `function() end`
283#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
284#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
285#[cfg_attr(not(feature = "luau"), display("{function_token}{body}"))]
286#[cfg_attr(
287    feature = "luau",
288    display("{}{}{}", join_vec(attributes), function_token, body)
289)]
290pub struct AnonymousFunction {
291    #[cfg(feature = "luau")]
292    attributes: Vec<LuauAttribute>,
293    function_token: TokenReference,
294    body: FunctionBody,
295}
296
297impl AnonymousFunction {
298    /// Returns a new AnonymousFunction
299    pub fn new() -> Self {
300        AnonymousFunction {
301            #[cfg(feature = "luau")]
302            attributes: Vec::new(),
303            function_token: TokenReference::basic_symbol("function"),
304            body: FunctionBody::new(),
305        }
306    }
307
308    /// The attributes in the function, e.g. `@native`
309    #[cfg(feature = "luau")]
310    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
311        self.attributes.iter()
312    }
313
314    /// The `function` token
315    pub fn function_token(&self) -> &TokenReference {
316        &self.function_token
317    }
318
319    /// The function body, everything except `function` in `function(a, b, c) call() end`
320    pub fn body(&self) -> &FunctionBody {
321        &self.body
322    }
323
324    /// Returns a new AnonymousFunction with the given attributes (e.g. `@native`)
325    #[cfg(feature = "luau")]
326    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
327        Self { attributes, ..self }
328    }
329
330    /// Returns a new AnonymousFunction with the given `function` token
331    pub fn with_function_token(self, function_token: TokenReference) -> Self {
332        Self {
333            function_token,
334            ..self
335        }
336    }
337
338    /// Returns a new AnonymousFunction with the given function body
339    pub fn with_body(self, body: FunctionBody) -> Self {
340        Self { body, ..self }
341    }
342}
343
344impl Default for AnonymousFunction {
345    fn default() -> Self {
346        Self::new()
347    }
348}
349
350/// An expression, mostly useful for getting values
351#[derive(Clone, Debug, Display, PartialEq, Node)]
352#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
353#[non_exhaustive]
354pub enum Expression {
355    /// A binary operation, such as `1 + 3`
356    #[display("{lhs}{binop}{rhs}")]
357    BinaryOperator {
358        /// The left hand side of the binary operation, the `1` part of `1 + 3`
359        lhs: Box<Expression>,
360        /// The binary operation used, the `+` part of `1 + 3`
361        binop: BinOp,
362        /// The right hand side of the binary operation, the `3` part of `1 + 3`
363        rhs: Box<Expression>,
364    },
365
366    /// A statement in parentheses, such as `(#list)`
367    #[display("{}{}{}", contained.tokens().0, expression, contained.tokens().1)]
368    Parentheses {
369        /// The parentheses of the expression
370        #[node(full_range)]
371        contained: ContainedSpan,
372        /// The expression inside the parentheses
373        expression: Box<Expression>,
374    },
375
376    /// A unary operation, such as `#list`
377    #[display("{unop}{expression}")]
378    UnaryOperator {
379        /// The unary operation, the `#` part of `#list`
380        unop: UnOp,
381        /// The expression the operation is being done on, the `list` part of `#list`
382        expression: Box<Expression>,
383    },
384
385    /// An anonymous function, such as `function() end`
386    #[display("{_0}")]
387    Function(Box<AnonymousFunction>),
388
389    /// A call of a function, such as `call()`
390    #[display("{_0}")]
391    FunctionCall(FunctionCall),
392
393    /// An if expression, such as `if foo then true else false`.
394    /// Only available when the "luau" feature flag is enabled.
395    #[cfg(feature = "luau")]
396    #[display("{_0}")]
397    IfExpression(IfExpression),
398
399    /// An interpolated string, such as `` `hello {"world"}` ``
400    /// Only available when the "luau" feature flag is enabled.
401    #[cfg(feature = "luau")]
402    #[display("{_0}")]
403    InterpolatedString(InterpolatedString),
404
405    /// A table constructor, such as `{ 1, 2, 3 }`
406    #[display("{_0}")]
407    TableConstructor(TableConstructor),
408
409    /// A number token, such as `3.3`
410    #[display("{_0}")]
411    Number(TokenReference),
412
413    /// A string token, such as `"hello"`
414    #[display("{_0}")]
415    String(TokenReference),
416
417    /// A symbol, such as `true`
418    #[display("{_0}")]
419    Symbol(TokenReference),
420
421    /// A value that has been asserted for a particular type, for use in Luau.
422    /// Only available when the "luau" feature flag is enabled.
423    #[cfg(feature = "luau")]
424    #[display("{expression}{type_assertion}")]
425    TypeAssertion {
426        /// The expression being asserted
427        expression: Box<Expression>,
428
429        /// The type assertion
430        type_assertion: TypeAssertion,
431    },
432
433    /// A more complex value, such as `call().x`
434    #[display("{_0}")]
435    Var(Var),
436}
437
438/// A statement that stands alone
439#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
440#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
441#[non_exhaustive]
442pub enum Stmt {
443    /// An assignment, such as `x = 1`
444    #[display("{_0}")]
445    Assignment(Assignment),
446    /// A do block, `do end`
447    #[display("{_0}")]
448    Do(Do),
449    /// A function call on its own, such as `call()`
450    #[display("{_0}")]
451    FunctionCall(FunctionCall),
452    /// A function declaration, such as `function x() end`
453    #[display("{_0}")]
454    FunctionDeclaration(FunctionDeclaration),
455    /// A generic for loop, such as `for index, value in pairs(list) do end`
456    #[display("{_0}")]
457    GenericFor(GenericFor),
458    /// An if statement
459    #[display("{_0}")]
460    If(If),
461    /// A local assignment, such as `local x = 1`
462    #[display("{_0}")]
463    LocalAssignment(LocalAssignment),
464    /// A local function declaration, such as `local function x() end`
465    #[display("{_0}")]
466    LocalFunction(LocalFunction),
467    /// A numeric for loop, such as `for index = 1, 10 do end`
468    #[display("{_0}")]
469    NumericFor(NumericFor),
470    /// A repeat loop
471    #[display("{_0}")]
472    Repeat(Repeat),
473    /// A while loop
474    #[display("{_0}")]
475    While(While),
476
477    /// A compound assignment, such as `+=`
478    /// Only available when the "luau" feature flag is enabled
479    #[cfg(any(feature = "luau", feature = "cfxlua"))]
480    #[display("{_0}")]
481    CompoundAssignment(CompoundAssignment),
482    /// A const variable assignment, such as `const x = 1`
483    /// Only available when the "luau" feature flag is enabled.
484    #[cfg(feature = "luau")]
485    #[display("{_0}")]
486    ConstAssignment(ConstAssignment),
487    /// A const function declaration, such as `const function x() end`
488    /// Only available when the "luau" feature flag is enabled.
489    #[cfg(feature = "luau")]
490    #[display("{_0}")]
491    ConstFunction(ConstFunction),
492    /// An exported type declaration, such as `export type Meters = number`
493    /// Only available when the "luau" feature flag is enabled.
494    #[cfg(feature = "luau")]
495    ExportedTypeDeclaration(ExportedTypeDeclaration),
496    /// A type declaration, such as `type Meters = number`
497    /// Only available when the "luau" feature flag is enabled.
498    #[cfg(feature = "luau")]
499    TypeDeclaration(TypeDeclaration),
500    /// An exported type function, such as `export type function Pairs(...) end`
501    /// Only available when the "luau" feature flag is enabled.
502    #[cfg(feature = "luau")]
503    ExportedTypeFunction(ExportedTypeFunction),
504    /// A type function, such as `type function Pairs(...) end`
505    /// Only available when the "luau" feature flag is enabled.
506    #[cfg(feature = "luau")]
507    TypeFunction(TypeFunction),
508
509    /// A goto statement, such as `goto label`
510    /// Only available when the "lua52" or "luajit" feature flag is enabled.
511    #[cfg(any(feature = "lua52", feature = "luajit"))]
512    Goto(Goto),
513    /// A label, such as `::label::`
514    /// Only available when the "lua52" or "luajit" feature flag is enabled.
515    #[cfg(any(feature = "lua52", feature = "luajit"))]
516    Label(Label),
517}
518
519/// A node used before another in cases such as function calling
520/// The `("foo")` part of `("foo"):upper()`
521#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
522#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
523#[non_exhaustive]
524pub enum Prefix {
525    #[display("{_0}")]
526    /// A complicated expression, such as `("foo")`
527    Expression(Box<Expression>),
528    #[display("{_0}")]
529    /// Just a name, such as `foo`
530    Name(TokenReference),
531}
532
533/// The indexing of something, such as `x.y` or `x["y"]`
534/// Values of variants are the keys, such as `"y"`
535#[derive(Clone, Debug, Display, PartialEq, Node)]
536#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
537#[non_exhaustive]
538pub enum Index {
539    /// Indexing in the form of `x["y"]`
540    #[display("{}{}{}", brackets.tokens().0, expression, brackets.tokens().1)]
541    Brackets {
542        /// The `[...]` part of `["y"]`
543        brackets: ContainedSpan,
544        /// The `"y"` part of `["y"]`
545        expression: Expression,
546    },
547
548    /// Indexing in the form of `x.y`
549    #[display("{dot}{name}")]
550    Dot {
551        /// The `.` part of `.y`
552        dot: TokenReference,
553        /// The `y` part of `.y`
554        name: TokenReference,
555    },
556}
557
558/// Arguments used for a function
559#[derive(Clone, Debug, Display, PartialEq, Node)]
560#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
561#[non_exhaustive]
562pub enum FunctionArgs {
563    /// Used when a function is called in the form of `call(1, 2, 3)`
564    #[display(
565        "{}{}{}",
566        parentheses.tokens().0,
567        arguments,
568        parentheses.tokens().1
569    )]
570    Parentheses {
571        /// The `(...) part of (1, 2, 3)`
572        #[node(full_range)]
573        parentheses: ContainedSpan,
574        /// The `1, 2, 3` part of `1, 2, 3`
575        arguments: Punctuated<Expression>,
576    },
577    /// Used when a function is called in the form of `call "foobar"`
578    #[display("{_0}")]
579    String(TokenReference),
580    /// Used when a function is called in the form of `call { 1, 2, 3 }`
581    #[display("{_0}")]
582    TableConstructor(TableConstructor),
583}
584
585impl FunctionArgs {
586    pub(crate) fn empty() -> Self {
587        FunctionArgs::Parentheses {
588            parentheses: ContainedSpan::new(
589                TokenReference::basic_symbol("("),
590                TokenReference::basic_symbol(")"),
591            ),
592
593            arguments: Punctuated::new(),
594        }
595    }
596}
597
598/// A numeric for loop, such as `for index = 1, 10 do end`
599#[derive(Clone, Debug, PartialEq, Node)]
600#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
601pub struct NumericFor {
602    for_token: TokenReference,
603    index_variable: TokenReference,
604    equal_token: TokenReference,
605    start: Expression,
606    start_end_comma: TokenReference,
607    end: Expression,
608    end_step_comma: Option<TokenReference>,
609    step: Option<Expression>,
610    do_token: TokenReference,
611    block: Block,
612    end_token: TokenReference,
613    #[cfg(feature = "luau")]
614    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
615    type_specifier: Option<TypeSpecifier>,
616}
617
618impl NumericFor {
619    /// Creates a new NumericFor from the given index variable, start, and end expressions
620    pub fn new(index_variable: TokenReference, start: Expression, end: Expression) -> Self {
621        Self {
622            for_token: TokenReference::basic_symbol("for "),
623            index_variable,
624            equal_token: TokenReference::basic_symbol(" = "),
625            start,
626            start_end_comma: TokenReference::basic_symbol(", "),
627            end,
628            end_step_comma: None,
629            step: None,
630            do_token: TokenReference::basic_symbol(" do\n"),
631            block: Block::new(),
632            end_token: TokenReference::basic_symbol("\nend"),
633            #[cfg(feature = "luau")]
634            type_specifier: None,
635        }
636    }
637
638    /// The `for` token
639    pub fn for_token(&self) -> &TokenReference {
640        &self.for_token
641    }
642
643    /// The index identity, `index` in the initial example
644    pub fn index_variable(&self) -> &TokenReference {
645        &self.index_variable
646    }
647
648    /// The `=` token
649    pub fn equal_token(&self) -> &TokenReference {
650        &self.equal_token
651    }
652
653    /// The starting point, `1` in the initial example
654    pub fn start(&self) -> &Expression {
655        &self.start
656    }
657
658    /// The comma in between the starting point and end point
659    /// for _ = 1, 10 do
660    ///          ^
661    pub fn start_end_comma(&self) -> &TokenReference {
662        &self.start_end_comma
663    }
664
665    /// The ending point, `10` in the initial example
666    pub fn end(&self) -> &Expression {
667        &self.end
668    }
669
670    /// The comma in between the ending point and limit, if one exists
671    /// for _ = 0, 10, 2 do
672    ///              ^
673    pub fn end_step_comma(&self) -> Option<&TokenReference> {
674        self.end_step_comma.as_ref()
675    }
676
677    /// The step if one exists, `2` in `for index = 0, 10, 2 do end`
678    pub fn step(&self) -> Option<&Expression> {
679        self.step.as_ref()
680    }
681
682    /// The `do` token
683    pub fn do_token(&self) -> &TokenReference {
684        &self.do_token
685    }
686
687    /// The code inside the for loop
688    pub fn block(&self) -> &Block {
689        &self.block
690    }
691
692    /// The `end` token
693    pub fn end_token(&self) -> &TokenReference {
694        &self.end_token
695    }
696
697    /// The type specifiers of the index variable
698    /// `for i: number = 1, 10 do` returns:
699    /// `Some(TypeSpecifier(number))`
700    /// Only available when the "luau" feature flag is enabled.
701    #[cfg(feature = "luau")]
702    pub fn type_specifier(&self) -> Option<&TypeSpecifier> {
703        self.type_specifier.as_ref()
704    }
705
706    /// Returns a new NumericFor with the given for token
707    pub fn with_for_token(self, for_token: TokenReference) -> Self {
708        Self { for_token, ..self }
709    }
710
711    /// Returns a new NumericFor with the given index variable
712    pub fn with_index_variable(self, index_variable: TokenReference) -> Self {
713        Self {
714            index_variable,
715            ..self
716        }
717    }
718
719    /// Returns a new NumericFor with the given `=` token
720    pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
721        Self {
722            equal_token,
723            ..self
724        }
725    }
726
727    /// Returns a new NumericFor with the given start expression
728    pub fn with_start(self, start: Expression) -> Self {
729        Self { start, ..self }
730    }
731
732    /// Returns a new NumericFor with the given comma between the start and end expressions
733    pub fn with_start_end_comma(self, start_end_comma: TokenReference) -> Self {
734        Self {
735            start_end_comma,
736            ..self
737        }
738    }
739
740    /// Returns a new NumericFor with the given end expression
741    pub fn with_end(self, end: Expression) -> Self {
742        Self { end, ..self }
743    }
744
745    /// Returns a new NumericFor with the given comma between the end and the step expressions
746    pub fn with_end_step_comma(self, end_step_comma: Option<TokenReference>) -> Self {
747        Self {
748            end_step_comma,
749            ..self
750        }
751    }
752
753    /// Returns a new NumericFor with the given step expression
754    pub fn with_step(self, step: Option<Expression>) -> Self {
755        Self { step, ..self }
756    }
757
758    /// Returns a new NumericFor with the given `do` token
759    pub fn with_do_token(self, do_token: TokenReference) -> Self {
760        Self { do_token, ..self }
761    }
762
763    /// Returns a new NumericFor with the given block
764    pub fn with_block(self, block: Block) -> Self {
765        Self { block, ..self }
766    }
767
768    /// Returns a new NumericFor with the given `end` token
769    pub fn with_end_token(self, end_token: TokenReference) -> Self {
770        Self { end_token, ..self }
771    }
772
773    /// Returns a new NumericFor with the given type specifiers
774    /// Only available when the "luau" feature flag is enabled.
775    #[cfg(feature = "luau")]
776    pub fn with_type_specifier(self, type_specifier: Option<TypeSpecifier>) -> Self {
777        Self {
778            type_specifier,
779            ..self
780        }
781    }
782}
783
784impl fmt::Display for NumericFor {
785    #[cfg(feature = "luau")]
786    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
787        write!(
788            formatter,
789            "{}{}{}{}{}{}{}{}{}{}{}{}",
790            self.for_token,
791            self.index_variable,
792            display_option(self.type_specifier()),
793            self.equal_token,
794            self.start,
795            self.start_end_comma,
796            self.end,
797            display_option(self.end_step_comma()),
798            display_option(self.step()),
799            self.do_token,
800            self.block,
801            self.end_token,
802        )
803    }
804
805    #[cfg(not(feature = "luau"))]
806    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
807        write!(
808            formatter,
809            "{}{}{}{}{}{}{}{}{}{}{}",
810            self.for_token,
811            self.index_variable,
812            self.equal_token,
813            self.start,
814            self.start_end_comma,
815            self.end,
816            display_option(self.end_step_comma()),
817            display_option(self.step()),
818            self.do_token,
819            self.block,
820            self.end_token,
821        )
822    }
823}
824
825/// A generic for loop, such as `for index, value in pairs(list) do end`
826#[derive(Clone, Debug, PartialEq, Node)]
827#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
828pub struct GenericFor {
829    for_token: TokenReference,
830    names: Punctuated<TokenReference>,
831    in_token: TokenReference,
832    expr_list: Punctuated<Expression>,
833    do_token: TokenReference,
834    block: Block,
835    end_token: TokenReference,
836    #[cfg(feature = "luau")]
837    #[cfg_attr(
838        feature = "serde",
839        serde(skip_serializing_if = "vec_empty_or_all_none")
840    )]
841    type_specifiers: Vec<Option<TypeSpecifier>>,
842}
843
844impl GenericFor {
845    /// Creates a new GenericFor from the given names and expressions
846    pub fn new(names: Punctuated<TokenReference>, expr_list: Punctuated<Expression>) -> Self {
847        Self {
848            for_token: TokenReference::basic_symbol("for "),
849            names,
850            in_token: TokenReference::basic_symbol(" in "),
851            expr_list,
852            do_token: TokenReference::basic_symbol(" do\n"),
853            block: Block::new(),
854            end_token: TokenReference::basic_symbol("\nend"),
855            #[cfg(feature = "luau")]
856            type_specifiers: Vec::new(),
857        }
858    }
859
860    /// The `for` token
861    pub fn for_token(&self) -> &TokenReference {
862        &self.for_token
863    }
864
865    /// Returns the punctuated sequence of names
866    /// In `for index, value in pairs(list) do`, iterates over `index` and `value`
867    pub fn names(&self) -> &Punctuated<TokenReference> {
868        &self.names
869    }
870
871    /// The `in` token
872    pub fn in_token(&self) -> &TokenReference {
873        &self.in_token
874    }
875
876    /// Returns the punctuated sequence of the expressions looped over
877    /// In `for index, value in pairs(list) do`, iterates over `pairs(list)`
878    pub fn expressions(&self) -> &Punctuated<Expression> {
879        &self.expr_list
880    }
881
882    /// The `do` token
883    pub fn do_token(&self) -> &TokenReference {
884        &self.do_token
885    }
886
887    /// The code inside the for loop
888    pub fn block(&self) -> &Block {
889        &self.block
890    }
891
892    /// The `end` token
893    pub fn end_token(&self) -> &TokenReference {
894        &self.end_token
895    }
896
897    /// The type specifiers of the named variables, in the order that they were assigned.
898    /// `for i, v: string in pairs() do` returns an iterator containing:
899    /// `None, Some(TypeSpecifier(string))`
900    /// Only available when the "luau" feature flag is enabled.
901    #[cfg(feature = "luau")]
902    pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
903        self.type_specifiers.iter().map(Option::as_ref)
904    }
905
906    /// Returns a new GenericFor with the given `for` token
907    pub fn with_for_token(self, for_token: TokenReference) -> Self {
908        Self { for_token, ..self }
909    }
910
911    /// Returns a new GenericFor with the given names
912    pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
913        Self { names, ..self }
914    }
915
916    /// Returns a new GenericFor with the given `in` token
917    pub fn with_in_token(self, in_token: TokenReference) -> Self {
918        Self { in_token, ..self }
919    }
920
921    /// Returns a new GenericFor with the given expression list
922    pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
923        Self { expr_list, ..self }
924    }
925
926    /// Returns a new GenericFor with the given `do` token
927    pub fn with_do_token(self, do_token: TokenReference) -> Self {
928        Self { do_token, ..self }
929    }
930
931    /// Returns a new GenericFor with the given block
932    pub fn with_block(self, block: Block) -> Self {
933        Self { block, ..self }
934    }
935
936    /// Returns a new GenericFor with the given `end` token
937    pub fn with_end_token(self, end_token: TokenReference) -> Self {
938        Self { end_token, ..self }
939    }
940
941    /// Returns a new GenericFor with the given type specifiers
942    /// Only available when the "luau" feature flag is enabled.
943    #[cfg(feature = "luau")]
944    pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
945        Self {
946            type_specifiers,
947            ..self
948        }
949    }
950}
951
952impl fmt::Display for GenericFor {
953    #[cfg(feature = "luau")]
954    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
955        write!(
956            formatter,
957            "{}{}{}{}{}{}{}",
958            self.for_token,
959            join_type_specifiers(&self.names, self.type_specifiers()),
960            self.in_token,
961            self.expr_list,
962            self.do_token,
963            self.block,
964            self.end_token
965        )
966    }
967
968    #[cfg(not(feature = "luau"))]
969    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
970        write!(
971            formatter,
972            "{}{}{}{}{}{}{}",
973            self.for_token,
974            self.names,
975            self.in_token,
976            self.expr_list,
977            self.do_token,
978            self.block,
979            self.end_token
980        )
981    }
982}
983
984/// An if statement
985#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
986#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
987#[display(
988    "{}{}{}{}{}{}{}{}",
989    if_token,
990    condition,
991    then_token,
992    block,
993    display_option(else_if.as_ref().map(join_vec)),
994    display_option(else_token),
995    display_option(r#else),
996    end_token
997)]
998pub struct If {
999    if_token: TokenReference,
1000    condition: Expression,
1001    then_token: TokenReference,
1002    block: Block,
1003    else_if: Option<Vec<ElseIf>>,
1004    else_token: Option<TokenReference>,
1005    #[cfg_attr(feature = "serde", serde(rename = "else"))]
1006    r#else: Option<Block>,
1007    end_token: TokenReference,
1008}
1009
1010impl If {
1011    /// Creates a new If from the given condition
1012    pub fn new(condition: Expression) -> Self {
1013        Self {
1014            if_token: TokenReference::basic_symbol("if "),
1015            condition,
1016            then_token: TokenReference::basic_symbol(" then"),
1017            block: Block::new(),
1018            else_if: None,
1019            else_token: None,
1020            r#else: None,
1021            end_token: TokenReference::basic_symbol("\nend"),
1022        }
1023    }
1024
1025    /// The `if` token
1026    pub fn if_token(&self) -> &TokenReference {
1027        &self.if_token
1028    }
1029
1030    /// The condition of the if statement, `condition` in `if condition then`
1031    pub fn condition(&self) -> &Expression {
1032        &self.condition
1033    }
1034
1035    /// The `then` token
1036    pub fn then_token(&self) -> &TokenReference {
1037        &self.then_token
1038    }
1039
1040    /// The block inside the initial if statement
1041    pub fn block(&self) -> &Block {
1042        &self.block
1043    }
1044
1045    /// The `else` token if one exists
1046    pub fn else_token(&self) -> Option<&TokenReference> {
1047        self.else_token.as_ref()
1048    }
1049
1050    /// If there are `elseif` conditions, returns a vector of them
1051    /// Expression is the condition, block is the code if the condition is true
1052    // TODO: Make this return an iterator, and remove Option part entirely?
1053    pub fn else_if(&self) -> Option<&Vec<ElseIf>> {
1054        self.else_if.as_ref()
1055    }
1056
1057    /// The code inside an `else` block if one exists
1058    pub fn else_block(&self) -> Option<&Block> {
1059        self.r#else.as_ref()
1060    }
1061
1062    /// The `end` token
1063    pub fn end_token(&self) -> &TokenReference {
1064        &self.end_token
1065    }
1066
1067    /// Returns a new If with the given `if` token
1068    pub fn with_if_token(self, if_token: TokenReference) -> Self {
1069        Self { if_token, ..self }
1070    }
1071
1072    /// Returns a new If with the given condition
1073    pub fn with_condition(self, condition: Expression) -> Self {
1074        Self { condition, ..self }
1075    }
1076
1077    /// Returns a new If with the given `then` token
1078    pub fn with_then_token(self, then_token: TokenReference) -> Self {
1079        Self { then_token, ..self }
1080    }
1081
1082    /// Returns a new If with the given block
1083    pub fn with_block(self, block: Block) -> Self {
1084        Self { block, ..self }
1085    }
1086
1087    /// Returns a new If with the given list of `elseif` blocks
1088    pub fn with_else_if(self, else_if: Option<Vec<ElseIf>>) -> Self {
1089        Self { else_if, ..self }
1090    }
1091
1092    /// Returns a new If with the given `else` token
1093    pub fn with_else_token(self, else_token: Option<TokenReference>) -> Self {
1094        Self { else_token, ..self }
1095    }
1096
1097    /// Returns a new If with the given `else` body
1098    pub fn with_else(self, r#else: Option<Block>) -> Self {
1099        Self { r#else, ..self }
1100    }
1101
1102    /// Returns a new If with the given `end` token
1103    pub fn with_end_token(self, end_token: TokenReference) -> Self {
1104        Self { end_token, ..self }
1105    }
1106}
1107
1108/// An elseif block in a bigger [`If`] statement
1109#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1110#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1111#[display("{else_if_token}{condition}{then_token}{block}")]
1112pub struct ElseIf {
1113    else_if_token: TokenReference,
1114    condition: Expression,
1115    then_token: TokenReference,
1116    block: Block,
1117}
1118
1119impl ElseIf {
1120    /// Creates a new ElseIf from the given condition
1121    pub fn new(condition: Expression) -> Self {
1122        Self {
1123            else_if_token: TokenReference::basic_symbol("elseif "),
1124            condition,
1125            then_token: TokenReference::basic_symbol(" then\n"),
1126            block: Block::new(),
1127        }
1128    }
1129
1130    /// The `elseif` token
1131    pub fn else_if_token(&self) -> &TokenReference {
1132        &self.else_if_token
1133    }
1134
1135    /// The condition of the `elseif`, `condition` in `elseif condition then`
1136    pub fn condition(&self) -> &Expression {
1137        &self.condition
1138    }
1139
1140    /// The `then` token
1141    pub fn then_token(&self) -> &TokenReference {
1142        &self.then_token
1143    }
1144
1145    /// The body of the `elseif`
1146    pub fn block(&self) -> &Block {
1147        &self.block
1148    }
1149
1150    /// Returns a new ElseIf with the given `elseif` token
1151    pub fn with_else_if_token(self, else_if_token: TokenReference) -> Self {
1152        Self {
1153            else_if_token,
1154            ..self
1155        }
1156    }
1157
1158    /// Returns a new ElseIf with the given condition
1159    pub fn with_condition(self, condition: Expression) -> Self {
1160        Self { condition, ..self }
1161    }
1162
1163    /// Returns a new ElseIf with the given `then` token
1164    pub fn with_then_token(self, then_token: TokenReference) -> Self {
1165        Self { then_token, ..self }
1166    }
1167
1168    /// Returns a new ElseIf with the given block
1169    pub fn with_block(self, block: Block) -> Self {
1170        Self { block, ..self }
1171    }
1172}
1173
1174/// A while loop
1175#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1176#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1177#[display("{while_token}{condition}{do_token}{block}{end_token}")]
1178pub struct While {
1179    while_token: TokenReference,
1180    condition: Expression,
1181    do_token: TokenReference,
1182    block: Block,
1183    end_token: TokenReference,
1184}
1185
1186impl While {
1187    /// Creates a new While from the given condition
1188    pub fn new(condition: Expression) -> Self {
1189        Self {
1190            while_token: TokenReference::basic_symbol("while "),
1191            condition,
1192            do_token: TokenReference::basic_symbol(" do\n"),
1193            block: Block::new(),
1194            end_token: TokenReference::basic_symbol("end\n"),
1195        }
1196    }
1197
1198    /// The `while` token
1199    pub fn while_token(&self) -> &TokenReference {
1200        &self.while_token
1201    }
1202
1203    /// The `condition` part of `while condition do`
1204    pub fn condition(&self) -> &Expression {
1205        &self.condition
1206    }
1207
1208    /// The `do` token
1209    pub fn do_token(&self) -> &TokenReference {
1210        &self.do_token
1211    }
1212
1213    /// The code inside the while loop
1214    pub fn block(&self) -> &Block {
1215        &self.block
1216    }
1217
1218    /// The `end` token
1219    pub fn end_token(&self) -> &TokenReference {
1220        &self.end_token
1221    }
1222
1223    /// Returns a new While with the given `while` token
1224    pub fn with_while_token(self, while_token: TokenReference) -> Self {
1225        Self {
1226            while_token,
1227            ..self
1228        }
1229    }
1230
1231    /// Returns a new While with the given condition
1232    pub fn with_condition(self, condition: Expression) -> Self {
1233        Self { condition, ..self }
1234    }
1235
1236    /// Returns a new While with the given `do` token
1237    pub fn with_do_token(self, do_token: TokenReference) -> Self {
1238        Self { do_token, ..self }
1239    }
1240
1241    /// Returns a new While with the given block
1242    pub fn with_block(self, block: Block) -> Self {
1243        Self { block, ..self }
1244    }
1245
1246    /// Returns a new While with the given `end` token
1247    pub fn with_end_token(self, end_token: TokenReference) -> Self {
1248        Self { end_token, ..self }
1249    }
1250}
1251
1252/// A repeat loop
1253#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1254#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1255#[display("{repeat_token}{block}{until_token}{until}")]
1256pub struct Repeat {
1257    repeat_token: TokenReference,
1258    block: Block,
1259    until_token: TokenReference,
1260    until: Expression,
1261}
1262
1263impl Repeat {
1264    /// Creates a new Repeat from the given expression to repeat until
1265    pub fn new(until: Expression) -> Self {
1266        Self {
1267            repeat_token: TokenReference::basic_symbol("repeat\n"),
1268            block: Block::new(),
1269            until_token: TokenReference::basic_symbol("\nuntil "),
1270            until,
1271        }
1272    }
1273
1274    /// The `repeat` token
1275    pub fn repeat_token(&self) -> &TokenReference {
1276        &self.repeat_token
1277    }
1278
1279    /// The code inside the `repeat` block
1280    pub fn block(&self) -> &Block {
1281        &self.block
1282    }
1283
1284    /// The `until` token
1285    pub fn until_token(&self) -> &TokenReference {
1286        &self.until_token
1287    }
1288
1289    /// The condition for the `until` part
1290    pub fn until(&self) -> &Expression {
1291        &self.until
1292    }
1293
1294    /// Returns a new Repeat with the given `repeat` token
1295    pub fn with_repeat_token(self, repeat_token: TokenReference) -> Self {
1296        Self {
1297            repeat_token,
1298            ..self
1299        }
1300    }
1301
1302    /// Returns a new Repeat with the given block
1303    pub fn with_block(self, block: Block) -> Self {
1304        Self { block, ..self }
1305    }
1306
1307    /// Returns a new Repeat with the given `until` token
1308    pub fn with_until_token(self, until_token: TokenReference) -> Self {
1309        Self {
1310            until_token,
1311            ..self
1312        }
1313    }
1314
1315    /// Returns a new Repeat with the given `until` block
1316    pub fn with_until(self, until: Expression) -> Self {
1317        Self { until, ..self }
1318    }
1319}
1320
1321/// A method call, such as `x:y()`
1322#[derive(Clone, Debug, PartialEq, Node, Visit)]
1323#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1324pub struct MethodCall {
1325    colon_token: TokenReference,
1326    name: TokenReference,
1327
1328    #[cfg(feature = "luau")]
1329    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1330    type_instantiation: Option<TypeInstantiation>,
1331
1332    args: FunctionArgs,
1333}
1334
1335impl MethodCall {
1336    /// Returns a new MethodCall from the given name and args
1337    pub fn new(name: TokenReference, args: FunctionArgs) -> Self {
1338        Self {
1339            colon_token: TokenReference::basic_symbol(":"),
1340            name,
1341            args,
1342            #[cfg(feature = "luau")]
1343            type_instantiation: None,
1344        }
1345    }
1346
1347    /// The `:` in `x:y()`
1348    pub fn colon_token(&self) -> &TokenReference {
1349        &self.colon_token
1350    }
1351
1352    /// The arguments of a method call, the `x, y, z` part of `method:call(x, y, z)`
1353    pub fn args(&self) -> &FunctionArgs {
1354        &self.args
1355    }
1356
1357    /// The method being called, the `call` part of `method:call()`
1358    pub fn name(&self) -> &TokenReference {
1359        &self.name
1360    }
1361
1362    /// The type instantiation on the method, if one is provided.
1363    /// The `<<T>>` in `f:<<T>>()`.
1364    /// Only available when the "luau" feature flag is enabled.
1365    #[cfg(feature = "luau")]
1366    pub fn type_instantiation(&self) -> Option<&TypeInstantiation> {
1367        self.type_instantiation.as_ref()
1368    }
1369
1370    /// Returns a new MethodCall with the given `:` token
1371    pub fn with_colon_token(self, colon_token: TokenReference) -> Self {
1372        Self {
1373            colon_token,
1374            ..self
1375        }
1376    }
1377
1378    /// Returns a new MethodCall with the given name
1379    pub fn with_name(self, name: TokenReference) -> Self {
1380        Self { name, ..self }
1381    }
1382
1383    /// Returns a new MethodCall with the given args
1384    pub fn with_args(self, args: FunctionArgs) -> Self {
1385        Self { args, ..self }
1386    }
1387
1388    /// Returns a new MethodCall with the given type instantiation.
1389    #[cfg(feature = "luau")]
1390    pub fn with_type_instanation(self, type_instantiation: Option<TypeInstantiation>) -> Self {
1391        Self {
1392            type_instantiation,
1393            ..self
1394        }
1395    }
1396}
1397
1398impl fmt::Display for MethodCall {
1399    fn fmt(&self, formatter: &mut Formatter<'_>) -> fmt::Result {
1400        write!(formatter, "{}{}", self.colon_token, self.name)?;
1401
1402        #[cfg(feature = "luau")]
1403        if let Some(type_instantiation) = self.type_instantiation.as_ref() {
1404            write!(formatter, "{type_instantiation}")?;
1405        }
1406
1407        write!(formatter, "{}", self.args)?;
1408
1409        Ok(())
1410    }
1411}
1412
1413/// Something being called
1414#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1415#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1416#[non_exhaustive]
1417pub enum Call {
1418    #[display("{_0}")]
1419    /// A function being called directly, such as `x(1)`
1420    AnonymousCall(FunctionArgs),
1421    #[display("{_0}")]
1422    /// A method call, such as `x:y()`
1423    MethodCall(MethodCall),
1424}
1425
1426/// A function body, everything except `function x` in `function x(a, b, c) call() end`
1427#[derive(Clone, Debug, PartialEq, Node)]
1428#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1429pub struct FunctionBody {
1430    #[cfg(feature = "luau")]
1431    generics: Option<GenericDeclaration>,
1432
1433    parameters_parentheses: ContainedSpan,
1434    parameters: Punctuated<Parameter>,
1435
1436    #[cfg(feature = "luau")]
1437    type_specifiers: Vec<Option<TypeSpecifier>>,
1438
1439    #[cfg(feature = "luau")]
1440    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
1441    return_type: Option<TypeSpecifier>,
1442
1443    block: Block,
1444    end_token: TokenReference,
1445}
1446
1447impl FunctionBody {
1448    /// Returns a new empty FunctionBody
1449    pub fn new() -> Self {
1450        Self {
1451            #[cfg(feature = "luau")]
1452            generics: None,
1453
1454            parameters_parentheses: ContainedSpan::new(
1455                TokenReference::basic_symbol("("),
1456                TokenReference::basic_symbol(")"),
1457            ),
1458            parameters: Punctuated::new(),
1459
1460            #[cfg(feature = "luau")]
1461            type_specifiers: Vec::new(),
1462
1463            #[cfg(feature = "luau")]
1464            return_type: None,
1465
1466            block: Block::new(),
1467            end_token: TokenReference::basic_symbol("\nend"),
1468        }
1469    }
1470
1471    /// The parentheses of the parameters
1472    pub fn parameters_parentheses(&self) -> &ContainedSpan {
1473        &self.parameters_parentheses
1474    }
1475
1476    /// Returns the [`Punctuated`] sequence of the parameters for the function declaration
1477    pub fn parameters(&self) -> &Punctuated<Parameter> {
1478        &self.parameters
1479    }
1480
1481    /// The code of a function body
1482    pub fn block(&self) -> &Block {
1483        &self.block
1484    }
1485
1486    /// The `end` token
1487    pub fn end_token(&self) -> &TokenReference {
1488        &self.end_token
1489    }
1490
1491    /// The generics declared for the function body.
1492    /// The `<T, U>` part of `function x<T, U>() end`
1493    /// Only available when the "luau" feature flag is enabled.
1494    #[cfg(feature = "luau")]
1495    pub fn generics(&self) -> Option<&GenericDeclaration> {
1496        self.generics.as_ref()
1497    }
1498
1499    /// The type specifiers of the variables, in the order that they were assigned.
1500    /// `(foo: number, bar, baz: boolean)` returns an iterator containing:
1501    /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1502    /// Only available when the "luau" feature flag is enabled.
1503    #[cfg(feature = "luau")]
1504    pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1505        self.type_specifiers.iter().map(Option::as_ref)
1506    }
1507
1508    /// The return type of the function, if one exists.
1509    /// Only available when the "luau" feature flag is enabled.
1510    #[cfg(feature = "luau")]
1511    pub fn return_type(&self) -> Option<&TypeSpecifier> {
1512        self.return_type.as_ref()
1513    }
1514
1515    /// Returns a new FunctionBody with the given parentheses for the parameters
1516    pub fn with_parameters_parentheses(self, parameters_parentheses: ContainedSpan) -> Self {
1517        Self {
1518            parameters_parentheses,
1519            ..self
1520        }
1521    }
1522
1523    /// Returns a new FunctionBody with the given parameters
1524    pub fn with_parameters(self, parameters: Punctuated<Parameter>) -> Self {
1525        Self { parameters, ..self }
1526    }
1527
1528    /// Returns a new FunctionBody with the given generics declaration
1529    #[cfg(feature = "luau")]
1530    pub fn with_generics(self, generics: Option<GenericDeclaration>) -> Self {
1531        Self { generics, ..self }
1532    }
1533
1534    /// Returns a new FunctionBody with the given type specifiers
1535    #[cfg(feature = "luau")]
1536    pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1537        Self {
1538            type_specifiers,
1539            ..self
1540        }
1541    }
1542
1543    /// Returns a new FunctionBody with the given return type
1544    #[cfg(feature = "luau")]
1545    pub fn with_return_type(self, return_type: Option<TypeSpecifier>) -> Self {
1546        Self {
1547            return_type,
1548            ..self
1549        }
1550    }
1551
1552    /// Returns a new FunctionBody with the given block
1553    pub fn with_block(self, block: Block) -> Self {
1554        Self { block, ..self }
1555    }
1556
1557    /// Returns a new FunctionBody with the given `end` token
1558    pub fn with_end_token(self, end_token: TokenReference) -> Self {
1559        Self { end_token, ..self }
1560    }
1561}
1562
1563impl Default for FunctionBody {
1564    fn default() -> Self {
1565        Self::new()
1566    }
1567}
1568
1569impl fmt::Display for FunctionBody {
1570    #[cfg(feature = "luau")]
1571    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1572        write!(
1573            formatter,
1574            "{}{}{}{}{}{}{}",
1575            display_option(self.generics.as_ref()),
1576            self.parameters_parentheses.tokens().0,
1577            join_type_specifiers(&self.parameters, self.type_specifiers()),
1578            self.parameters_parentheses.tokens().1,
1579            display_option(self.return_type.as_ref()),
1580            self.block,
1581            self.end_token
1582        )
1583    }
1584
1585    #[cfg(not(feature = "luau"))]
1586    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1587        write!(
1588            formatter,
1589            "{}{}{}{}{}",
1590            self.parameters_parentheses.tokens().0,
1591            self.parameters,
1592            self.parameters_parentheses.tokens().1,
1593            self.block,
1594            self.end_token
1595        )
1596    }
1597}
1598
1599/// A parameter in a function declaration
1600#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
1601#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1602#[non_exhaustive]
1603pub enum Parameter {
1604    /// The `...` vararg syntax, such as `function x(...)`
1605    Ellipsis(TokenReference),
1606    /// A name parameter, such as `function x(a, b, c)`
1607    Name(TokenReference),
1608}
1609
1610/// A suffix in certain cases, such as `:y()` in `x:y()`
1611/// Can be stacked on top of each other, such as in `x()()()`
1612#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1613#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1614#[non_exhaustive]
1615pub enum Suffix {
1616    #[display("{_0}")]
1617    /// A call, including method calls and direct calls
1618    Call(Call),
1619
1620    #[display("{_0}")]
1621    /// An index, such as `x.y`
1622    Index(Index),
1623
1624    #[display("{_0}")]
1625    #[cfg(feature = "luau")]
1626    /// A type instantiation, such as `a<<T>>`
1627    TypeInstantiation(TypeInstantiation),
1628}
1629
1630/// A complex expression used by [`Var`], consisting of both a prefix and suffixes
1631#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1632#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1633#[display("{}{}", prefix, join_vec(suffixes))]
1634pub struct VarExpression {
1635    prefix: Prefix,
1636    suffixes: Vec<Suffix>,
1637}
1638
1639impl VarExpression {
1640    /// Returns a new VarExpression from the given prefix
1641    pub fn new(prefix: Prefix) -> Self {
1642        Self {
1643            prefix,
1644            suffixes: Vec::new(),
1645        }
1646    }
1647
1648    /// The prefix of the expression, such as a name
1649    pub fn prefix(&self) -> &Prefix {
1650        &self.prefix
1651    }
1652
1653    /// An iter over the suffixes, such as indexing or calling
1654    pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
1655        self.suffixes.iter()
1656    }
1657
1658    /// Returns a new VarExpression with the given prefix
1659    pub fn with_prefix(self, prefix: Prefix) -> Self {
1660        Self { prefix, ..self }
1661    }
1662
1663    /// Returns a new VarExpression with the given suffixes
1664    pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
1665        Self { suffixes, ..self }
1666    }
1667}
1668
1669/// Used in [`Assignment`s](Assignment) and [`Value`s](Value)
1670#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1671#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1672#[non_exhaustive]
1673pub enum Var {
1674    /// An expression, such as `x.y.z` or `x()`
1675    #[display("{_0}")]
1676    Expression(Box<VarExpression>),
1677    /// A literal identifier, such as `x`
1678    #[display("{_0}")]
1679    Name(TokenReference),
1680}
1681
1682/// An assignment, such as `x = y`. Not used for [`LocalAssignment`s](LocalAssignment)
1683#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1684#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1685#[display("{var_list}{equal_token}{expr_list}")]
1686pub struct Assignment {
1687    var_list: Punctuated<Var>,
1688    equal_token: TokenReference,
1689    expr_list: Punctuated<Expression>,
1690}
1691
1692impl Assignment {
1693    /// Returns a new Assignment from the given variable and expression list
1694    pub fn new(var_list: Punctuated<Var>, expr_list: Punctuated<Expression>) -> Self {
1695        Self {
1696            var_list,
1697            equal_token: TokenReference::basic_symbol(" = "),
1698            expr_list,
1699        }
1700    }
1701
1702    /// Returns the punctuated sequence over the expressions being assigned.
1703    /// This is the the `1, 2` part of `x, y["a"] = 1, 2`
1704    pub fn expressions(&self) -> &Punctuated<Expression> {
1705        &self.expr_list
1706    }
1707
1708    /// The `=` token in between `x = y`
1709    pub fn equal_token(&self) -> &TokenReference {
1710        &self.equal_token
1711    }
1712
1713    /// Returns the punctuated sequence over the variables being assigned to.
1714    /// This is the `x, y["a"]` part of `x, y["a"] = 1, 2`
1715    pub fn variables(&self) -> &Punctuated<Var> {
1716        &self.var_list
1717    }
1718
1719    /// Returns a new Assignment with the given variables
1720    pub fn with_variables(self, var_list: Punctuated<Var>) -> Self {
1721        Self { var_list, ..self }
1722    }
1723
1724    /// Returns a new Assignment with the given `=` token
1725    pub fn with_equal_token(self, equal_token: TokenReference) -> Self {
1726        Self {
1727            equal_token,
1728            ..self
1729        }
1730    }
1731
1732    /// Returns a new Assignment with the given expressions
1733    pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1734        Self { expr_list, ..self }
1735    }
1736}
1737
1738/// A declaration of a local function, such as `local function x() end`
1739#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1740#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1741#[cfg_attr(
1742    not(feature = "luau"),
1743    display("{local_token}{function_token}{name}{body}")
1744)]
1745#[cfg_attr(
1746    feature = "luau",
1747    display(
1748        "{}{}{}{}{}",
1749        join_vec(attributes),
1750        local_token,
1751        function_token,
1752        name,
1753        body
1754    )
1755)]
1756pub struct LocalFunction {
1757    #[cfg(feature = "luau")]
1758    attributes: Vec<LuauAttribute>,
1759    local_token: TokenReference,
1760    function_token: TokenReference,
1761    name: TokenReference,
1762    body: FunctionBody,
1763}
1764
1765impl LocalFunction {
1766    /// Returns a new LocalFunction from the given name
1767    pub fn new(name: TokenReference) -> Self {
1768        LocalFunction {
1769            #[cfg(feature = "luau")]
1770            attributes: Vec::new(),
1771            local_token: TokenReference::basic_symbol("local "),
1772            function_token: TokenReference::basic_symbol("function "),
1773            name,
1774            body: FunctionBody::new(),
1775        }
1776    }
1777
1778    /// The attributes in the function, e.g. `@native`
1779    #[cfg(feature = "luau")]
1780    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
1781        self.attributes.iter()
1782    }
1783
1784    /// The `local` token
1785    pub fn local_token(&self) -> &TokenReference {
1786        &self.local_token
1787    }
1788
1789    /// The `function` token
1790    pub fn function_token(&self) -> &TokenReference {
1791        &self.function_token
1792    }
1793
1794    /// The function body, everything except `local function x` in `local function x(a, b, c) call() end`
1795    pub fn body(&self) -> &FunctionBody {
1796        &self.body
1797    }
1798
1799    /// The name of the function, the `x` part of `local function x() end`
1800    pub fn name(&self) -> &TokenReference {
1801        &self.name
1802    }
1803
1804    /// Returns a new LocalFunction with the given attributes (e.g. `@native`)
1805    #[cfg(feature = "luau")]
1806    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
1807        Self { attributes, ..self }
1808    }
1809
1810    /// Returns a new LocalFunction with the given `local` token
1811    pub fn with_local_token(self, local_token: TokenReference) -> Self {
1812        Self {
1813            local_token,
1814            ..self
1815        }
1816    }
1817
1818    /// Returns a new LocalFunction with the given `function` token
1819    pub fn with_function_token(self, function_token: TokenReference) -> Self {
1820        Self {
1821            function_token,
1822            ..self
1823        }
1824    }
1825
1826    /// Returns a new LocalFunction with the given name
1827    pub fn with_name(self, name: TokenReference) -> Self {
1828        Self { name, ..self }
1829    }
1830
1831    /// Returns a new LocalFunction with the given function body
1832    pub fn with_body(self, body: FunctionBody) -> Self {
1833        Self { body, ..self }
1834    }
1835}
1836
1837/// An assignment to a local variable, such as `local x = 1`
1838#[derive(Clone, Debug, PartialEq, Node)]
1839#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1840pub struct LocalAssignment {
1841    local_token: TokenReference,
1842    #[cfg(feature = "luau")]
1843    #[cfg_attr(
1844        feature = "serde",
1845        serde(skip_serializing_if = "empty_optional_vector")
1846    )]
1847    type_specifiers: Vec<Option<TypeSpecifier>>,
1848    name_list: Punctuated<TokenReference>,
1849    #[cfg(feature = "lua54")]
1850    #[cfg_attr(
1851        feature = "serde",
1852        serde(skip_serializing_if = "empty_optional_vector")
1853    )]
1854    attributes: Vec<Option<Attribute>>,
1855    equal_token: Option<TokenReference>,
1856    expr_list: Punctuated<Expression>,
1857}
1858
1859impl LocalAssignment {
1860    /// Returns a new LocalAssignment from the given name list
1861    pub fn new(name_list: Punctuated<TokenReference>) -> Self {
1862        Self {
1863            local_token: TokenReference::basic_symbol("local "),
1864            #[cfg(feature = "luau")]
1865            type_specifiers: Vec::new(),
1866            name_list,
1867            #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1868            attributes: Vec::new(),
1869            equal_token: None,
1870            expr_list: Punctuated::new(),
1871        }
1872    }
1873
1874    /// The `local` token
1875    pub fn local_token(&self) -> &TokenReference {
1876        &self.local_token
1877    }
1878
1879    /// The `=` token in between `local x = y`, if one exists
1880    pub fn equal_token(&self) -> Option<&TokenReference> {
1881        self.equal_token.as_ref()
1882    }
1883
1884    /// Returns the punctuated sequence of the expressions being assigned.
1885    /// This is the `1, 2` part of `local x, y = 1, 2`
1886    pub fn expressions(&self) -> &Punctuated<Expression> {
1887        &self.expr_list
1888    }
1889
1890    /// Returns the punctuated sequence of names being assigned to.
1891    /// This is the `x, y` part of `local x, y = 1, 2`
1892    pub fn names(&self) -> &Punctuated<TokenReference> {
1893        &self.name_list
1894    }
1895
1896    /// The type specifiers of the variables, in the order that they were assigned.
1897    /// `local foo: number, bar, baz: boolean` returns an iterator containing:
1898    /// `Some(TypeSpecifier(number)), None, Some(TypeSpecifier(boolean))`
1899    /// Only available when the "luau" feature flag is enabled.
1900    #[cfg(feature = "luau")]
1901    pub fn type_specifiers(&self) -> impl Iterator<Item = Option<&TypeSpecifier>> {
1902        self.type_specifiers.iter().map(Option::as_ref)
1903    }
1904
1905    /// The attributes specified for the variables, in the order that they were assigned.
1906    /// `local foo <const>, bar, baz <close>` returns an iterator containing:
1907    /// `Some(Attribute("const")), None, Some(Attribute("close"))`
1908    /// Only available when the "lua54" feature flag is enabled.
1909    #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1910    pub fn attributes(&self) -> impl Iterator<Item = Option<&Attribute>> {
1911        self.attributes.iter().map(Option::as_ref)
1912    }
1913
1914    /// Returns a new LocalAssignment with the given `local` token
1915    pub fn with_local_token(self, local_token: TokenReference) -> Self {
1916        Self {
1917            local_token,
1918            ..self
1919        }
1920    }
1921
1922    /// Returns a new LocalAssignment with the given type specifiers
1923    #[cfg(feature = "luau")]
1924    pub fn with_type_specifiers(self, type_specifiers: Vec<Option<TypeSpecifier>>) -> Self {
1925        Self {
1926            type_specifiers,
1927            ..self
1928        }
1929    }
1930
1931    /// Returns a new LocalAssignment with the given attributes
1932    #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1933    pub fn with_attributes(self, attributes: Vec<Option<Attribute>>) -> Self {
1934        Self { attributes, ..self }
1935    }
1936
1937    /// Returns a new LocalAssignment with the given name list
1938    pub fn with_names(self, name_list: Punctuated<TokenReference>) -> Self {
1939        Self { name_list, ..self }
1940    }
1941
1942    /// Returns a new LocalAssignment with the given `=` token
1943    pub fn with_equal_token(self, equal_token: Option<TokenReference>) -> Self {
1944        Self {
1945            equal_token,
1946            ..self
1947        }
1948    }
1949
1950    /// Returns a new LocalAssignment with the given expression list
1951    pub fn with_expressions(self, expr_list: Punctuated<Expression>) -> Self {
1952        Self { expr_list, ..self }
1953    }
1954}
1955
1956impl fmt::Display for LocalAssignment {
1957    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
1958        #[cfg(any(feature = "lua54", feature = "cfxlua"))]
1959        let attributes = self.attributes().chain(std::iter::repeat(None));
1960        #[cfg(not(feature = "lua54"))]
1961        let attributes = std::iter::repeat_with(|| None::<TokenReference>);
1962        #[cfg(feature = "luau")]
1963        let type_specifiers = self.type_specifiers().chain(std::iter::repeat(None));
1964        #[cfg(not(feature = "luau"))]
1965        let type_specifiers = std::iter::repeat_with(|| None::<TokenReference>);
1966
1967        write!(
1968            formatter,
1969            "{}{}{}{}",
1970            self.local_token,
1971            join_iterators(&self.name_list, attributes, type_specifiers),
1972            display_option(&self.equal_token),
1973            self.expr_list
1974        )
1975    }
1976}
1977
1978/// A `do` block, such as `do ... end`
1979/// This is not used for things like `while true do end`, only those on their own
1980#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
1981#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
1982#[display("{do_token}{block}{end_token}")]
1983pub struct Do {
1984    do_token: TokenReference,
1985    block: Block,
1986    end_token: TokenReference,
1987}
1988
1989impl Do {
1990    /// Creates an empty Do
1991    pub fn new() -> Self {
1992        Self {
1993            do_token: TokenReference::basic_symbol("do\n"),
1994            block: Block::new(),
1995            end_token: TokenReference::basic_symbol("\nend"),
1996        }
1997    }
1998
1999    /// The `do` token
2000    pub fn do_token(&self) -> &TokenReference {
2001        &self.do_token
2002    }
2003
2004    /// The code inside the `do ... end`
2005    pub fn block(&self) -> &Block {
2006        &self.block
2007    }
2008
2009    /// The `end` token
2010    pub fn end_token(&self) -> &TokenReference {
2011        &self.end_token
2012    }
2013
2014    /// Returns a new Do with the given `do` token
2015    pub fn with_do_token(self, do_token: TokenReference) -> Self {
2016        Self { do_token, ..self }
2017    }
2018
2019    /// Returns a new Do with the given block
2020    pub fn with_block(self, block: Block) -> Self {
2021        Self { block, ..self }
2022    }
2023
2024    /// Returns a new Do with the given `end` token
2025    pub fn with_end_token(self, end_token: TokenReference) -> Self {
2026        Self { end_token, ..self }
2027    }
2028}
2029
2030impl Default for Do {
2031    fn default() -> Self {
2032        Self::new()
2033    }
2034}
2035
2036/// A function being called, such as `call()`
2037#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
2038#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2039#[display("{}{}", prefix, join_vec(suffixes))]
2040pub struct FunctionCall {
2041    prefix: Prefix,
2042    suffixes: Vec<Suffix>,
2043}
2044
2045impl FunctionCall {
2046    /// Creates a new FunctionCall from the given prefix
2047    /// Sets the suffixes such that the return is `prefixes()`
2048    pub fn new(prefix: Prefix) -> Self {
2049        FunctionCall {
2050            prefix,
2051            suffixes: vec![Suffix::Call(Call::AnonymousCall(
2052                FunctionArgs::Parentheses {
2053                    arguments: Punctuated::new(),
2054                    parentheses: ContainedSpan::new(
2055                        TokenReference::basic_symbol("("),
2056                        TokenReference::basic_symbol(")"),
2057                    ),
2058                },
2059            ))],
2060        }
2061    }
2062
2063    /// The prefix of a function call, the `call` part of `call()`
2064    pub fn prefix(&self) -> &Prefix {
2065        &self.prefix
2066    }
2067
2068    /// The suffix of a function call, the `()` part of `call()`
2069    pub fn suffixes(&self) -> impl Iterator<Item = &Suffix> {
2070        self.suffixes.iter()
2071    }
2072
2073    /// Returns a new FunctionCall with the given prefix
2074    pub fn with_prefix(self, prefix: Prefix) -> Self {
2075        Self { prefix, ..self }
2076    }
2077
2078    /// Returns a new FunctionCall with the given suffixes
2079    pub fn with_suffixes(self, suffixes: Vec<Suffix>) -> Self {
2080        Self { suffixes, ..self }
2081    }
2082}
2083
2084/// A function name when being declared as [`FunctionDeclaration`]
2085#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2086#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2087#[display(
2088    "{}{}{}",
2089    names,
2090    display_option(self.method_colon()),
2091    display_option(self.method_name())
2092)]
2093pub struct FunctionName {
2094    names: Punctuated<TokenReference>,
2095    colon_name: Option<(TokenReference, TokenReference)>,
2096}
2097
2098impl FunctionName {
2099    /// Creates a new FunctionName from the given list of names
2100    pub fn new(names: Punctuated<TokenReference>) -> Self {
2101        Self {
2102            names,
2103            colon_name: None,
2104        }
2105    }
2106
2107    /// The colon between the name and the method, the `:` part of `function x:y() end`
2108    pub fn method_colon(&self) -> Option<&TokenReference> {
2109        Some(&self.colon_name.as_ref()?.0)
2110    }
2111
2112    /// A method name if one exists, the `y` part of `function x:y() end`
2113    pub fn method_name(&self) -> Option<&TokenReference> {
2114        Some(&self.colon_name.as_ref()?.1)
2115    }
2116
2117    /// Returns the punctuated sequence over the names used when defining the function.
2118    /// This is the `x.y.z` part of `function x.y.z() end`
2119    pub fn names(&self) -> &Punctuated<TokenReference> {
2120        &self.names
2121    }
2122
2123    /// Returns a new FunctionName with the given names
2124    pub fn with_names(self, names: Punctuated<TokenReference>) -> Self {
2125        Self { names, ..self }
2126    }
2127
2128    /// Returns a new FunctionName with the given method name
2129    /// The first token is the colon, and the second token is the method name itself
2130    pub fn with_method(self, method: Option<(TokenReference, TokenReference)>) -> Self {
2131        Self {
2132            colon_name: method,
2133            ..self
2134        }
2135    }
2136}
2137
2138/// A normal function declaration, supports simple declarations like `function x() end`
2139/// as well as complicated declarations such as `function x.y.z:a() end`
2140#[derive(Clone, Debug, Display, PartialEq, Node, Visit)]
2141#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2142#[cfg_attr(not(feature = "luau"), display("{function_token}{name}{body}"))]
2143#[cfg_attr(
2144    feature = "luau",
2145    display("{}{}{}{}", join_vec(attributes), function_token, name, body)
2146)]
2147pub struct FunctionDeclaration {
2148    #[cfg(feature = "luau")]
2149    attributes: Vec<LuauAttribute>,
2150    function_token: TokenReference,
2151    name: FunctionName,
2152    body: FunctionBody,
2153}
2154
2155impl FunctionDeclaration {
2156    /// Creates a new FunctionDeclaration from the given name
2157    pub fn new(name: FunctionName) -> Self {
2158        Self {
2159            #[cfg(feature = "luau")]
2160            attributes: Vec::new(),
2161            function_token: TokenReference::basic_symbol("function "),
2162            name,
2163            body: FunctionBody::new(),
2164        }
2165    }
2166
2167    /// The attributes in the function, e.g. `@native`
2168    #[cfg(feature = "luau")]
2169    pub fn attributes(&self) -> impl Iterator<Item = &LuauAttribute> {
2170        self.attributes.iter()
2171    }
2172
2173    /// The `function` token
2174    pub fn function_token(&self) -> &TokenReference {
2175        &self.function_token
2176    }
2177
2178    /// The body of the function
2179    pub fn body(&self) -> &FunctionBody {
2180        &self.body
2181    }
2182
2183    /// The name of the function
2184    pub fn name(&self) -> &FunctionName {
2185        &self.name
2186    }
2187
2188    /// Returns a new FunctionDeclaration with the given attributes (e.g. `@native`)
2189    #[cfg(feature = "luau")]
2190    pub fn with_attributes(self, attributes: Vec<LuauAttribute>) -> Self {
2191        Self { attributes, ..self }
2192    }
2193
2194    /// Returns a new FunctionDeclaration with the given `function` token
2195    pub fn with_function_token(self, function_token: TokenReference) -> Self {
2196        Self {
2197            function_token,
2198            ..self
2199        }
2200    }
2201
2202    /// Returns a new FunctionDeclaration with the given function name
2203    pub fn with_name(self, name: FunctionName) -> Self {
2204        Self { name, ..self }
2205    }
2206
2207    /// Returns a new FunctionDeclaration with the given function body
2208    pub fn with_body(self, body: FunctionBody) -> Self {
2209        Self { body, ..self }
2210    }
2211}
2212
2213#[doc(hidden)]
2214#[macro_export]
2215macro_rules! make_bin_op {
2216    ($(#[$outer:meta])* { $(
2217        $([$($version:ident)|+])? $operator:ident = $precedence:expr,
2218    )+ }) => {
2219        paste::paste! {
2220            #[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2221            #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2222            #[non_exhaustive]
2223            $(#[$outer])*
2224            #[display("{_0}")]
2225            pub enum BinOp {
2226                $(
2227                    #[allow(missing_docs)]
2228                    $(
2229                        #[cfg(any(
2230                            $(feature = "" $version),+
2231                        ))]
2232                    )*
2233                    $operator(TokenReference),
2234                )+
2235            }
2236
2237            impl BinOp {
2238                /// The precedence of non-unary operator. The larger the number, the higher the precedence.
2239                /// Shares the same precedence table as unary operators.
2240                pub fn precedence_of_token(token: &TokenReference) -> Option<u8> {
2241                    match token.token_type() {
2242                        TokenType::Symbol { symbol } => match symbol {
2243                            $(
2244                                $(
2245                                    #[cfg(any(
2246                                        $(feature = "" $version),+
2247                                    ))]
2248                                )*
2249                                Symbol::$operator => Some($precedence),
2250                            )+
2251                            _ => None,
2252                        },
2253
2254                        _ => None
2255                    }
2256                }
2257
2258                /// The token associated with this operator
2259                pub fn token(&self) -> &TokenReference {
2260                    match self {
2261                        $(
2262                            $(
2263                                #[cfg(any(
2264                                    $(feature = "" $version),+
2265                                ))]
2266                            )*
2267                            BinOp::$operator(token) => token,
2268                        )+
2269                    }
2270                }
2271
2272                pub(crate) fn consume(state: &mut parser_structs::ParserState) -> Option<Self> {
2273                    match state.current().unwrap().token_type() {
2274                        TokenType::Symbol { symbol } => match symbol {
2275                            $(
2276                                $(
2277                                    #[cfg(any(
2278                                        $(feature = "" $version),+
2279                                    ))]
2280                                )*
2281                                Symbol::$operator => {
2282                                    if !$crate::has_version!(state.lua_version(), $($($version,)+)?) {
2283                                        return None;
2284                                    }
2285
2286                                    Some(BinOp::$operator(state.consume().unwrap()))
2287                                },
2288                            )+
2289
2290                            _ => None,
2291                        },
2292
2293                        _ => None,
2294                    }
2295                }
2296            }
2297        }
2298    };
2299}
2300
2301make_bin_op!(
2302    #[doc = "Operators that require two operands, such as X + Y or X - Y"]
2303    #[visit(skip_visit_self)]
2304    {
2305        Caret = 12,
2306
2307        Percent = 10,
2308        Slash = 10,
2309        Star = 10,
2310        [luau | lua53] DoubleSlash = 10,
2311
2312        Minus = 9,
2313        Plus = 9,
2314
2315        TwoDots = 8,
2316        [lua53] DoubleLessThan = 7,
2317        [lua53] DoubleGreaterThan = 7,
2318
2319        [lua53] Ampersand = 6,
2320
2321        [lua53] Tilde = 5,
2322
2323        [lua53] Pipe = 4,
2324
2325        GreaterThan = 3,
2326        GreaterThanEqual = 3,
2327        LessThan = 3,
2328        LessThanEqual = 3,
2329        TildeEqual = 3,
2330        TwoEqual = 3,
2331
2332        And = 2,
2333
2334        Or = 1,
2335    }
2336);
2337
2338impl BinOp {
2339    /// The precedence of the operator. The larger the number, the higher the precedence.
2340    /// See more at <http://www.lua.org/manual/5.1/manual.html#2.5.6>
2341    pub fn precedence(&self) -> u8 {
2342        BinOp::precedence_of_token(self.token()).expect("invalid token")
2343    }
2344
2345    /// Whether the operator is right associative. If not, it is left associative.
2346    /// See more at <https://www.lua.org/pil/3.5.html>
2347    pub fn is_right_associative(&self) -> bool {
2348        matches!(*self, BinOp::Caret(_) | BinOp::TwoDots(_))
2349    }
2350
2351    /// Given a token, returns whether it is a right associative binary operator.
2352    pub fn is_right_associative_token(token: &TokenReference) -> bool {
2353        matches!(
2354            token.token_type(),
2355            TokenType::Symbol {
2356                symbol: Symbol::Caret
2357            } | TokenType::Symbol {
2358                symbol: Symbol::TwoDots
2359            }
2360        )
2361    }
2362}
2363
2364/// Operators that require just one operand, such as #X
2365#[derive(Clone, Debug, Display, PartialEq, Eq, Node, Visit)]
2366#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2367#[allow(missing_docs)]
2368#[non_exhaustive]
2369#[display("{_0}")]
2370pub enum UnOp {
2371    Minus(TokenReference),
2372    Not(TokenReference),
2373    Hash(TokenReference),
2374    #[cfg(feature = "lua53")]
2375    Tilde(TokenReference),
2376}
2377
2378impl UnOp {
2379    /// The token associated with the operator
2380    pub fn token(&self) -> &TokenReference {
2381        match self {
2382            UnOp::Minus(token) | UnOp::Not(token) | UnOp::Hash(token) => token,
2383            #[cfg(feature = "lua53")]
2384            UnOp::Tilde(token) => token,
2385        }
2386    }
2387
2388    /// The precedence of unary operator. The larger the number, the higher the precedence.
2389    /// Shares the same precedence table as binary operators.
2390    pub fn precedence() -> u8 {
2391        11
2392    }
2393}
2394
2395/// An error that occurs when creating the AST.
2396#[derive(Clone, Debug, PartialEq, Eq)]
2397#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2398pub struct AstError {
2399    /// The token that caused the error
2400    token: Token,
2401
2402    /// Any additional information that could be provided for debugging
2403    additional: Cow<'static, str>,
2404
2405    /// If set, this is the complete range of the error
2406    #[cfg_attr(feature = "serde", serde(skip_serializing_if = "Option::is_none"))]
2407    range: Option<(Position, Position)>,
2408}
2409
2410impl AstError {
2411    /// Returns the token that caused the error
2412    pub fn token(&self) -> &Token {
2413        &self.token
2414    }
2415
2416    /// Returns a human readable error message
2417    pub fn error_message(&self) -> &str {
2418        self.additional.as_ref()
2419    }
2420
2421    /// Returns the range of the error
2422    pub fn range(&self) -> (Position, Position) {
2423        self.range
2424            .or_else(|| Some((self.token.start_position(), self.token.end_position())))
2425            .unwrap()
2426    }
2427}
2428
2429impl fmt::Display for AstError {
2430    fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
2431        let range = self.range();
2432
2433        write!(
2434            formatter,
2435            "unexpected token `{}`. (starting from line {}, character {} and ending on line {}, character {})\nadditional information: {}",
2436            self.token,
2437            range.0.line(),
2438            range.0.character(),
2439            range.1.line(),
2440            range.1.character(),
2441            self.additional,
2442        )
2443    }
2444}
2445
2446impl std::error::Error for AstError {}
2447
2448/// An abstract syntax tree, contains all the nodes used in the code
2449#[derive(Clone, Debug)]
2450#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
2451pub struct Ast {
2452    pub(crate) nodes: Block,
2453    pub(crate) eof: TokenReference,
2454}
2455
2456impl Ast {
2457    /// Returns a new Ast with the given nodes
2458    pub fn with_nodes(self, nodes: Block) -> Self {
2459        Self { nodes, ..self }
2460    }
2461
2462    /// Returns a new Ast with the given EOF token
2463    pub fn with_eof(self, eof: TokenReference) -> Self {
2464        Self { eof, ..self }
2465    }
2466
2467    /// The entire code of the function
2468    ///
2469    /// ```rust
2470    /// # fn main() -> Result<(), Vec<full_moon::Error>> {
2471    /// assert_eq!(full_moon::parse("local x = 1; local y = 2")?.nodes().stmts().count(), 2);
2472    /// # Ok(())
2473    /// # }
2474    /// ```
2475    pub fn nodes(&self) -> &Block {
2476        &self.nodes
2477    }
2478
2479    /// The entire code of the function, but mutable
2480    pub fn nodes_mut(&mut self) -> &mut Block {
2481        &mut self.nodes
2482    }
2483
2484    /// The EOF token at the end of every Ast
2485    pub fn eof(&self) -> &TokenReference {
2486        &self.eof
2487    }
2488}
2489
2490impl fmt::Display for Ast {
2491    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
2492        write!(f, "{}", self.nodes())?;
2493        write!(f, "{}", self.eof())
2494    }
2495}
2496
2497#[cfg(test)]
2498mod tests {
2499    use crate::{parse, visitors::VisitorMut};
2500
2501    use super::*;
2502
2503    #[test]
2504    fn test_with_eof_safety() {
2505        let new_ast = {
2506            let ast = parse("local foo = 1").unwrap();
2507            let eof = ast.eof().clone();
2508            ast.with_eof(eof)
2509        };
2510
2511        assert_eq!("local foo = 1", new_ast.to_string());
2512    }
2513
2514    #[test]
2515    fn test_with_nodes_safety() {
2516        let new_ast = {
2517            let ast = parse("local foo = 1").unwrap();
2518            let nodes = ast.nodes().clone();
2519            ast.with_nodes(nodes)
2520        };
2521
2522        assert_eq!(new_ast.to_string(), "local foo = 1");
2523    }
2524
2525    #[test]
2526    fn test_with_visitor_safety() {
2527        let new_ast = {
2528            let ast = parse("local foo = 1").unwrap();
2529
2530            struct SyntaxRewriter;
2531            impl VisitorMut for SyntaxRewriter {
2532                fn visit_token(&mut self, token: Token) -> Token {
2533                    token
2534                }
2535            }
2536
2537            SyntaxRewriter.visit_ast(ast)
2538        };
2539
2540        assert_eq!(new_ast.to_string(), "local foo = 1");
2541    }
2542
2543    // Tests AST nodes with new methods that call unwrap
2544    #[test]
2545    fn test_new_validity() {
2546        let token: TokenReference = TokenReference::new(
2547            Vec::new(),
2548            Token::new(TokenType::Identifier {
2549                identifier: "foo".into(),
2550            }),
2551            Vec::new(),
2552        );
2553
2554        let expression = Expression::Var(Var::Name(token.clone()));
2555
2556        Assignment::new(Punctuated::new(), Punctuated::new());
2557        Do::new();
2558        ElseIf::new(expression.clone());
2559        FunctionBody::new();
2560        FunctionCall::new(Prefix::Name(token.clone()));
2561        FunctionDeclaration::new(FunctionName::new(Punctuated::new()));
2562        GenericFor::new(Punctuated::new(), Punctuated::new());
2563        If::new(expression.clone());
2564        LocalAssignment::new(Punctuated::new());
2565        LocalFunction::new(token.clone());
2566        MethodCall::new(
2567            token.clone(),
2568            FunctionArgs::Parentheses {
2569                arguments: Punctuated::new(),
2570                parentheses: ContainedSpan::new(token.clone(), token.clone()),
2571            },
2572        );
2573        NumericFor::new(token, expression.clone(), expression.clone());
2574        Repeat::new(expression.clone());
2575        Return::new();
2576        TableConstructor::new();
2577        While::new(expression);
2578    }
2579
2580    #[test]
2581    fn test_local_assignment_print() {
2582        let block = Block::new().with_stmts(vec![(
2583            Stmt::LocalAssignment(
2584                LocalAssignment::new(
2585                    std::iter::once(Pair::End(TokenReference::new(
2586                        vec![],
2587                        Token::new(TokenType::Identifier {
2588                            identifier: "variable".into(),
2589                        }),
2590                        vec![],
2591                    )))
2592                    .collect(),
2593                )
2594                .with_equal_token(Some(TokenReference::symbol(" = ").unwrap()))
2595                .with_expressions(
2596                    std::iter::once(Pair::End(Expression::Number(TokenReference::new(
2597                        vec![],
2598                        Token::new(TokenType::Number { text: "1".into() }),
2599                        vec![],
2600                    ))))
2601                    .collect(),
2602                ),
2603            ),
2604            None,
2605        )]);
2606
2607        let ast = parse("").unwrap().with_nodes(block);
2608        assert_eq!(ast.to_string(), "local variable = 1");
2609    }
2610}