darklua_core/
ast_converter.rs

1use std::{fmt, str::FromStr};
2
3use full_moon::{
4    ast,
5    node::Node,
6    tokenizer::{self, InterpolatedStringKind, Symbol, TokenType},
7};
8
9use crate::nodes::*;
10
11#[derive(Debug, Default)]
12pub(crate) struct AstConverter<'a> {
13    hold_token_data: bool,
14    work_stack: Vec<ConvertWork<'a>>,
15    blocks: Vec<Block>,
16    statements: Vec<Statement>,
17    last_statements: Vec<LastStatement>,
18    expressions: Vec<Expression>,
19    prefixes: Vec<Prefix>,
20    arguments: Vec<Arguments>,
21    variables: Vec<Variable>,
22    types: Vec<Type>,
23    function_return_types: Vec<FunctionReturnType>,
24    variadic_type_packs: Vec<VariadicTypePack>,
25    generic_type_packs: Vec<GenericTypePack>,
26    type_parameters: Vec<TypeParameters>,
27    type_packs: Vec<TypePack>,
28}
29
30impl<'a> AstConverter<'a> {
31    pub(crate) fn new(hold_token_data: bool) -> Self {
32        Self {
33            hold_token_data,
34            ..Default::default()
35        }
36    }
37
38    #[inline]
39    fn push_work(&mut self, work: impl Into<ConvertWork<'a>>) {
40        self.work_stack.push(work.into());
41    }
42
43    #[inline]
44    fn pop_block(&mut self) -> Result<Block, ConvertError> {
45        self.blocks
46            .pop()
47            .ok_or(ConvertError::InternalStack { kind: "Block" })
48    }
49
50    #[inline]
51    fn pop_statement(&mut self) -> Result<Statement, ConvertError> {
52        self.statements
53            .pop()
54            .ok_or(ConvertError::InternalStack { kind: "Statement" })
55    }
56
57    #[inline]
58    fn pop_statements(&mut self, n: usize) -> Result<Vec<Statement>, ConvertError> {
59        std::iter::repeat_with(|| self.pop_statement())
60            .take(n)
61            .collect()
62    }
63
64    #[inline]
65    fn pop_last_statement(&mut self) -> Result<LastStatement, ConvertError> {
66        self.last_statements
67            .pop()
68            .ok_or(ConvertError::InternalStack {
69                kind: "LastStatement",
70            })
71    }
72
73    #[inline]
74    fn pop_expression(&mut self) -> Result<Expression, ConvertError> {
75        self.expressions
76            .pop()
77            .ok_or(ConvertError::InternalStack { kind: "Expression" })
78    }
79
80    #[inline]
81    fn pop_expressions(&mut self, n: usize) -> Result<Vec<Expression>, ConvertError> {
82        std::iter::repeat_with(|| self.pop_expression())
83            .take(n)
84            .collect()
85    }
86
87    #[inline]
88    fn pop_prefix(&mut self) -> Result<Prefix, ConvertError> {
89        self.prefixes
90            .pop()
91            .ok_or(ConvertError::InternalStack { kind: "Prefix" })
92    }
93
94    #[inline]
95    fn pop_variable(&mut self) -> Result<Variable, ConvertError> {
96        self.variables
97            .pop()
98            .ok_or(ConvertError::InternalStack { kind: "Variable" })
99    }
100
101    #[inline]
102    fn pop_variables(&mut self, n: usize) -> Result<Vec<Variable>, ConvertError> {
103        std::iter::repeat_with(|| self.pop_variable())
104            .take(n)
105            .collect()
106    }
107
108    #[inline]
109    fn pop_arguments(&mut self) -> Result<Arguments, ConvertError> {
110        self.arguments
111            .pop()
112            .ok_or(ConvertError::InternalStack { kind: "Arguments" })
113    }
114
115    #[inline]
116    fn pop_type(&mut self) -> Result<Type, ConvertError> {
117        self.types
118            .pop()
119            .ok_or(ConvertError::InternalStack { kind: "Type" })
120    }
121
122    #[inline]
123    fn pop_types(&mut self, n: usize) -> Result<Vec<Type>, ConvertError> {
124        std::iter::repeat_with(|| self.pop_type()).take(n).collect()
125    }
126
127    #[inline]
128    fn pop_variadic_type_pack(&mut self) -> Result<VariadicTypePack, ConvertError> {
129        self.variadic_type_packs
130            .pop()
131            .ok_or(ConvertError::InternalStack {
132                kind: "VariadicTypePack",
133            })
134    }
135
136    #[inline]
137    fn pop_generic_type_pack(&mut self) -> Result<GenericTypePack, ConvertError> {
138        self.generic_type_packs
139            .pop()
140            .ok_or(ConvertError::InternalStack {
141                kind: "GenericTypePack",
142            })
143    }
144
145    #[inline]
146    fn pop_function_return_type(&mut self) -> Result<FunctionReturnType, ConvertError> {
147        self.function_return_types
148            .pop()
149            .ok_or(ConvertError::InternalStack {
150                kind: "FunctionReturnType",
151            })
152    }
153
154    #[inline]
155    fn pop_type_parameters(&mut self) -> Result<TypeParameters, ConvertError> {
156        self.type_parameters
157            .pop()
158            .ok_or(ConvertError::InternalStack {
159                kind: "TypeParameters",
160            })
161    }
162
163    #[inline]
164    fn pop_type_pack(&mut self) -> Result<TypePack, ConvertError> {
165        self.type_packs
166            .pop()
167            .ok_or(ConvertError::InternalStack { kind: "TypePack" })
168    }
169
170    pub(crate) fn convert(&mut self, ast: &'a ast::Ast) -> Result<Block, ConvertError> {
171        self.push_work(ast.nodes());
172
173        while let Some(work) = self.work_stack.pop() {
174            match work {
175                ConvertWork::PushVariable(variable) => {
176                    self.variables.push(variable);
177                }
178                ConvertWork::PushExpression(expression) => {
179                    self.expressions.push(expression);
180                }
181                ConvertWork::PushType(r#type) => {
182                    self.types.push(r#type);
183                }
184                ConvertWork::Block(block) => {
185                    self.work_stack.push(ConvertWork::MakeBlock { block });
186                    for stmt in block.stmts() {
187                        self.push_work(stmt);
188                    }
189                    if let Some(last) = block.last_stmt() {
190                        self.push_work(last);
191                    }
192                }
193                ConvertWork::Statement(statement) => self.convert_statement(statement)?,
194                ConvertWork::LastStatement(last_statement) => match last_statement {
195                    ast::LastStmt::Break(token) => {
196                        self.last_statements.push(if self.hold_token_data {
197                            LastStatement::Break(Some(self.convert_token(token)?))
198                        } else {
199                            LastStatement::new_break()
200                        });
201                    }
202                    ast::LastStmt::Continue(token) => {
203                        self.last_statements.push(if self.hold_token_data {
204                            LastStatement::Continue(Some(self.convert_token(token)?))
205                        } else {
206                            LastStatement::new_continue()
207                        });
208                    }
209                    ast::LastStmt::Return(return_statement) => {
210                        self.work_stack.push(ConvertWork::MakeReturn {
211                            statement: return_statement,
212                        });
213                        for expression in return_statement.returns().iter() {
214                            self.push_work(expression);
215                        }
216                    }
217                    _ => {
218                        return Err(ConvertError::LastStatement {
219                            statement: last_statement.to_string(),
220                        })
221                    }
222                },
223                ConvertWork::Expression(expression) => self.convert_expression(expression)?,
224                ConvertWork::Prefix(prefix) => match prefix {
225                    ast::Prefix::Expression(expression) => {
226                        self.work_stack
227                            .push(ConvertWork::MakePrefixFromExpression { prefix });
228                        self.push_work(expression.as_ref());
229                    }
230                    ast::Prefix::Name(name) => {
231                        self.prefixes
232                            .push(self.convert_token_to_identifier(name)?.into());
233                    }
234                    _ => {
235                        return Err(ConvertError::Prefix {
236                            prefix: prefix.to_string(),
237                        })
238                    }
239                },
240                ConvertWork::Arguments(arguments) => match arguments {
241                    ast::FunctionArgs::Parentheses {
242                        parentheses,
243                        arguments,
244                    } => {
245                        self.work_stack
246                            .push(ConvertWork::MakeArgumentsFromExpressions {
247                                parentheses,
248                                arguments,
249                            });
250                        for value in arguments.iter() {
251                            self.push_work(value);
252                        }
253                    }
254                    ast::FunctionArgs::String(string) => {
255                        self.arguments
256                            .push(self.convert_string_expression(string)?.into());
257                    }
258                    ast::FunctionArgs::TableConstructor(table) => {
259                        self.work_stack
260                            .push(ConvertWork::MakeArgumentsFromTableEntries { table });
261
262                        self.convert_table(table)?;
263                    }
264                    _ => {
265                        return Err(ConvertError::FunctionArguments {
266                            arguments: arguments.to_string(),
267                        })
268                    }
269                },
270                ConvertWork::TypeInfo(type_info) => self.convert_type_info(type_info)?,
271                ConvertWork::MakeBlock { block } => {
272                    let mut new_block = Block::new(
273                        self.pop_statements(block.stmts().count())?,
274                        block
275                            .last_stmt()
276                            .map(|_| self.pop_last_statement())
277                            .transpose()?,
278                    );
279
280                    if self.hold_token_data {
281                        let semicolons = block
282                            .stmts_with_semicolon()
283                            .map(|(_, token)| {
284                                token
285                                    .as_ref()
286                                    .map(|token| self.convert_token(token))
287                                    .transpose()
288                            })
289                            .collect::<Result<Vec<_>, _>>()?;
290                        let last_semicolon =
291                            block.last_stmt_with_semicolon().and_then(|(_, semicolon)| {
292                                semicolon.as_ref().map(|token| self.convert_token(token))
293                            });
294
295                        new_block.set_tokens(BlockTokens {
296                            semicolons,
297                            last_semicolon: last_semicolon.transpose()?,
298                            final_token: None,
299                        });
300                    };
301
302                    self.blocks.push(new_block);
303                }
304                ConvertWork::MakeDoStatement { statement } => {
305                    let block = self.pop_block()?;
306                    let mut do_statement = DoStatement::new(block);
307                    if self.hold_token_data {
308                        do_statement.set_tokens(DoTokens {
309                            r#do: self.convert_token(statement.do_token())?,
310                            end: self.convert_token(statement.end_token())?,
311                        })
312                    }
313                    self.statements.push(do_statement.into());
314                }
315                ConvertWork::MakeReturn { statement } => {
316                    let mut return_statement =
317                        ReturnStatement::new(self.pop_expressions(statement.returns().len())?);
318                    if self.hold_token_data {
319                        let commas = self.extract_tokens_from_punctuation(statement.returns())?;
320                        return_statement.set_tokens(ReturnTokens {
321                            r#return: self.convert_token(statement.token())?,
322                            commas,
323                        });
324                    }
325                    self.last_statements.push(return_statement.into());
326                }
327                ConvertWork::MakeBinaryExpression { operator } => {
328                    let left = self.pop_expression()?;
329                    let right = self.pop_expression()?;
330                    let mut binary =
331                        BinaryExpression::new(self.convert_binop(operator)?, left, right);
332                    if self.hold_token_data {
333                        binary.set_token(self.convert_token(get_binary_operator_token(operator)?)?);
334                    }
335                    self.expressions.push(binary.into());
336                }
337                ConvertWork::MakeUnaryExpression { operator } => {
338                    let mut unary =
339                        UnaryExpression::new(self.convert_unop(operator)?, self.pop_expression()?);
340                    if self.hold_token_data {
341                        unary.set_token(self.convert_token(get_unary_operator_token(operator)?)?);
342                    }
343                    self.expressions.push(unary.into());
344                }
345                ConvertWork::MakeParentheseExpression { contained_span } => {
346                    let mut parenthese = ParentheseExpression::new(self.pop_expression()?);
347                    if self.hold_token_data {
348                        let (left_parenthese, right_parenthese) =
349                            self.extract_contained_span_tokens(contained_span)?;
350                        parenthese.set_tokens(ParentheseTokens {
351                            left_parenthese,
352                            right_parenthese,
353                        });
354                    }
355                    self.expressions.push(parenthese.into());
356                }
357                ConvertWork::MakeIfExpression { if_expression } => {
358                    let condition = self.pop_expression()?;
359                    let result = self.pop_expression()?;
360                    let else_expression = self.pop_expression()?;
361
362                    let mut value = IfExpression::new(condition, result, else_expression);
363
364                    if let Some(elseifs) = if_expression.else_if_expressions() {
365                        for elseif in elseifs.iter() {
366                            let elseif_condition = self.pop_expression()?;
367                            let elseif_expression = self.pop_expression()?;
368                            let mut branch =
369                                ElseIfExpressionBranch::new(elseif_condition, elseif_expression);
370                            if self.hold_token_data {
371                                branch.set_tokens(ElseIfExpressionBranchTokens {
372                                    elseif: self.convert_token(elseif.else_if_token())?,
373                                    then: self.convert_token(elseif.then_token())?,
374                                });
375                            }
376                            value.push_branch(branch);
377                        }
378                    }
379
380                    if self.hold_token_data {
381                        value.set_tokens(IfExpressionTokens {
382                            r#if: self.convert_token(if_expression.if_token())?,
383                            then: self.convert_token(if_expression.then_token())?,
384                            r#else: self.convert_token(if_expression.else_token())?,
385                        });
386                    }
387
388                    self.expressions.push(value.into());
389                }
390                ConvertWork::MakeInterpolatedString {
391                    interpolated_string,
392                } => {
393                    let mut segments = Vec::new();
394                    let mut segments_iter = interpolated_string.segments().peekable();
395
396                    while let Some(segment) = segments_iter.next() {
397                        let literal = &segment.literal;
398                        if let Some(segment) = self.convert_string_interpolation_segment(literal)? {
399                            segments.push(segment.into());
400                        }
401
402                        let expression = self.pop_expression()?;
403                        let mut value_segment = ValueSegment::new(expression);
404
405                        if self.hold_token_data {
406                            let literal_end = self.convert_token_end_position(literal)?;
407
408                            let mut opening_brace = Token::new_with_line(
409                                literal_end.0.saturating_sub(1),
410                                literal_end.0,
411                                literal_end.1,
412                            );
413
414                            for trivia_token in literal.trailing_trivia() {
415                                opening_brace
416                                    .push_trailing_trivia(self.convert_trivia(trivia_token)?);
417                            }
418
419                            let next_literal = segments_iter
420                                .peek()
421                                .map(|next_segment| &next_segment.literal)
422                                .unwrap_or(interpolated_string.last_string());
423
424                            let next_literal_position =
425                                self.convert_token_position(next_literal)?;
426
427                            let closing_brace = Token::new_with_line(
428                                next_literal_position.0,
429                                next_literal_position.0.saturating_add(1),
430                                next_literal_position.2,
431                            );
432
433                            value_segment.set_tokens(ValueSegmentTokens {
434                                opening_brace,
435                                closing_brace,
436                            });
437                        }
438
439                        segments.push(value_segment.into());
440                    }
441
442                    if let Some(segment) = self
443                        .convert_string_interpolation_segment(interpolated_string.last_string())?
444                    {
445                        segments.push(segment.into());
446                    }
447
448                    let mut value = InterpolatedStringExpression::new(segments);
449
450                    if self.hold_token_data {
451                        let last = interpolated_string.last_string();
452                        let first = interpolated_string
453                            .segments()
454                            .next()
455                            .map(|segment| &segment.literal)
456                            .unwrap_or(last);
457
458                        let (opening_tick, closing_tick) = match first.token_type() {
459                            TokenType::InterpolatedString { literal: _, kind } => match kind {
460                                InterpolatedStringKind::Begin | InterpolatedStringKind::Simple => {
461                                    let first_position = self.convert_token_position(first)?;
462                                    let mut start_token = Token::new_with_line(
463                                        first_position.0,
464                                        first_position.0.saturating_add(1),
465                                        first_position.2,
466                                    );
467                                    let last_position = self.convert_token_end_position(last)?;
468                                    let mut end_token = Token::new_with_line(
469                                        last_position.0.saturating_sub(1),
470                                        last_position.0,
471                                        last_position.1,
472                                    );
473
474                                    for trivia_token in first.leading_trivia() {
475                                        start_token.push_leading_trivia(
476                                            self.convert_trivia(trivia_token)?,
477                                        );
478                                    }
479
480                                    for trivia_token in last.trailing_trivia() {
481                                        end_token.push_trailing_trivia(
482                                            self.convert_trivia(trivia_token)?,
483                                        );
484                                    }
485                                    (start_token, end_token)
486                                }
487                                InterpolatedStringKind::Middle | InterpolatedStringKind::End => {
488                                    return Err(ConvertError::InterpolatedString {
489                                        string: interpolated_string.to_string(),
490                                    })
491                                }
492                            },
493                            _ => {
494                                return Err(ConvertError::InterpolatedString {
495                                    string: interpolated_string.to_string(),
496                                })
497                            }
498                        };
499
500                        let tokens = InterpolatedStringTokens {
501                            opening_tick,
502                            closing_tick,
503                        };
504                        value.set_tokens(tokens);
505                    }
506
507                    self.expressions.push(value.into());
508                }
509                ConvertWork::MakeFunctionExpression { body, token } => {
510                    let builder =
511                        self.convert_function_body_attributes(body, self.convert_token(token)?)?;
512
513                    self.expressions
514                        .push(builder.into_function_expression().into());
515                }
516                ConvertWork::MakeRepeatStatement { statement } => {
517                    let mut repeat_statement =
518                        RepeatStatement::new(self.pop_block()?, self.pop_expression()?);
519                    if self.hold_token_data {
520                        repeat_statement.set_tokens(RepeatTokens {
521                            repeat: self.convert_token(statement.repeat_token())?,
522                            until: self.convert_token(statement.until_token())?,
523                        });
524                    }
525                    self.statements.push(repeat_statement.into());
526                }
527                ConvertWork::MakeWhileStatement { statement } => {
528                    let block = self.pop_block()?;
529                    let mut while_statement = WhileStatement::new(block, self.pop_expression()?);
530                    if self.hold_token_data {
531                        while_statement.set_tokens(WhileTokens {
532                            r#while: self.convert_token(statement.while_token())?,
533                            r#do: self.convert_token(statement.do_token())?,
534                            end: self.convert_token(statement.end_token())?,
535                        });
536                    }
537                    self.statements.push(while_statement.into());
538                }
539                ConvertWork::MakeNumericForStatement { statement } => {
540                    let typed_identifier = self.convert_typed_identifier(
541                        statement.index_variable(),
542                        statement.type_specifier(),
543                    )?;
544
545                    let block = self.pop_block()?;
546                    let start = self.pop_expression()?;
547                    let end = self.pop_expression()?;
548                    let step = statement
549                        .step()
550                        .map(|_| self.pop_expression())
551                        .transpose()?;
552
553                    let mut numeric_for =
554                        NumericForStatement::new(typed_identifier, start, end, step, block);
555
556                    if self.hold_token_data {
557                        numeric_for.set_tokens(NumericForTokens {
558                            r#for: self.convert_token(statement.for_token())?,
559                            equal: self.convert_token(statement.equal_token())?,
560                            r#do: self.convert_token(statement.do_token())?,
561                            end: self.convert_token(statement.end_token())?,
562                            end_comma: self.convert_token(statement.start_end_comma())?,
563                            step_comma: statement
564                                .end_step_comma()
565                                .map(|token| self.convert_token(token))
566                                .transpose()?,
567                        });
568                    }
569                    self.statements.push(numeric_for.into());
570                }
571                ConvertWork::MakeGenericForStatement { statement } => {
572                    let block = self.pop_block()?;
573                    let identifiers = statement
574                        .names()
575                        .iter()
576                        .zip(statement.type_specifiers())
577                        .map(|(name, type_specifier)| {
578                            self.convert_typed_identifier(name, type_specifier)
579                        })
580                        .collect::<Result<Vec<_>, _>>()?;
581                    let mut generic_for = GenericForStatement::new(
582                        identifiers,
583                        self.pop_expressions(statement.expressions().len())?,
584                        block,
585                    );
586                    if self.hold_token_data {
587                        generic_for.set_tokens(GenericForTokens {
588                            r#for: self.convert_token(statement.for_token())?,
589                            r#in: self.convert_token(statement.in_token())?,
590                            r#do: self.convert_token(statement.do_token())?,
591                            end: self.convert_token(statement.end_token())?,
592                            identifier_commas: self
593                                .extract_tokens_from_punctuation(statement.names())?,
594                            value_commas: self
595                                .extract_tokens_from_punctuation(statement.expressions())?,
596                        });
597                    }
598                    self.statements.push(generic_for.into());
599                }
600                ConvertWork::MakeFunctionDeclaration { statement } => {
601                    let builder = self.convert_function_body_attributes(
602                        statement.body(),
603                        self.convert_token(statement.function_token())?,
604                    )?;
605                    let name = self.convert_function_name(statement.name())?;
606
607                    self.statements
608                        .push(builder.into_function_statement(name).into());
609                }
610                ConvertWork::MakeFunctionCallStatement { call } => {
611                    let call = self.make_function_call(call)?;
612                    self.statements.push(call.into());
613                }
614                ConvertWork::MakePrefixFromExpression { prefix } => match self.pop_expression()? {
615                    Expression::Parenthese(parenthese) => {
616                        self.prefixes.push(Prefix::Parenthese(*parenthese));
617                    }
618                    _ => {
619                        return Err(ConvertError::Prefix {
620                            prefix: prefix.to_string(),
621                        })
622                    }
623                },
624                ConvertWork::MakeTypeDeclarationStatement {
625                    type_declaration,
626                    export_token,
627                } => {
628                    let mut declaration = TypeDeclarationStatement::new(
629                        self.convert_token_to_identifier(type_declaration.type_name())?,
630                        self.pop_type()?,
631                    );
632
633                    if export_token.is_some() {
634                        declaration.set_exported();
635                    }
636
637                    if let Some(generics) = type_declaration.generics() {
638                        let mut type_variables = Vec::new();
639                        let mut generic_type_packs = Vec::new();
640                        let mut type_variables_with_default = Vec::new();
641                        let mut generic_type_packs_with_default = Vec::new();
642
643                        for parameter in generics.generics() {
644                            match parameter.parameter() {
645                                ast::luau::GenericParameterInfo::Name(token) => {
646                                    let name = self.convert_token_to_identifier(token)?;
647
648                                    if let Some(default_type) = parameter
649                                        .default_type()
650                                        .map(|_| self.pop_type())
651                                        .transpose()?
652                                    {
653                                        type_variables_with_default.push(if self.hold_token_data {
654                                            let equal_token =
655                                                parameter.equals().ok_or_else(|| {
656                                                    ConvertError::GenericDeclaration {
657                                                        generics: generics.to_string(),
658                                                    }
659                                                })?;
660                                            (
661                                                name,
662                                                default_type,
663                                                Some(self.convert_token(equal_token)?),
664                                            )
665                                        } else {
666                                            (name, default_type, None)
667                                        });
668                                    } else {
669                                        type_variables
670                                            .push(self.convert_token_to_identifier(token)?);
671                                    }
672                                }
673                                ast::luau::GenericParameterInfo::Variadic { name, ellipsis } => {
674                                    let mut generic_pack = GenericTypePack::new(
675                                        self.convert_token_to_identifier(name)?,
676                                    );
677
678                                    if self.hold_token_data {
679                                        generic_pack.set_token(self.convert_token(ellipsis)?);
680                                    }
681
682                                    use ast::luau::TypeInfo;
683
684                                    if let Some(default_type) = parameter
685                                        .default_type()
686                                        .map(|default_type| {
687                                            if is_variadic_type(default_type).is_some() {
688                                                self.pop_variadic_type_pack()
689                                                    .map(GenericTypePackDefault::from)
690                                            } else {
691                                                match default_type {
692                                                    TypeInfo::GenericPack { .. } => self
693                                                        .pop_generic_type_pack()
694                                                        .map(GenericTypePackDefault::from),
695                                                    TypeInfo::VariadicPack { .. } => self
696                                                        .pop_variadic_type_pack()
697                                                        .map(GenericTypePackDefault::from),
698                                                    TypeInfo::Tuple { .. } => self
699                                                        .pop_type_pack()
700                                                        .map(GenericTypePackDefault::from),
701                                                    _ => Err(ConvertError::GenericDeclaration {
702                                                        generics: generics.to_string(),
703                                                    }),
704                                                }
705                                            }
706                                        })
707                                        .transpose()?
708                                    {
709                                        let mut generic_pack_with_default =
710                                            GenericTypePackWithDefault::new(
711                                                generic_pack,
712                                                default_type,
713                                            );
714
715                                        if self.hold_token_data {
716                                            let equal_token =
717                                                parameter.equals().ok_or_else(|| {
718                                                    ConvertError::GenericDeclaration {
719                                                        generics: generics.to_string(),
720                                                    }
721                                                })?;
722                                            generic_pack_with_default
723                                                .set_token(self.convert_token(equal_token)?);
724                                        }
725
726                                        generic_type_packs_with_default
727                                            .push(generic_pack_with_default);
728                                    } else {
729                                        generic_type_packs.push(generic_pack)
730                                    }
731                                }
732                                _ => {
733                                    return Err(ConvertError::GenericDeclaration {
734                                        generics: generics.to_string(),
735                                    })
736                                }
737                            }
738                        }
739
740                        let mut type_variable_iter = type_variables.into_iter();
741                        let mut type_variable_with_default_iter = type_variables_with_default
742                            .into_iter()
743                            .map(|(variable, default, token)| {
744                                let mut type_variable =
745                                    TypeVariableWithDefault::new(variable, default);
746
747                                if let Some(token) = token {
748                                    type_variable.set_token(token);
749                                }
750
751                                type_variable
752                            });
753                        let mut generic_type_packs_iter = generic_type_packs.into_iter();
754                        let mut generic_type_packs_with_default_iter =
755                            generic_type_packs_with_default.into_iter();
756
757                        let mut generic_parameters = type_variable_iter
758                            .next()
759                            .map(GenericParametersWithDefaults::from_type_variable)
760                            .or_else(|| {
761                                type_variable_with_default_iter.next().map(
762                                    GenericParametersWithDefaults::from_type_variable_with_default,
763                                )
764                            })
765                            .or_else(|| {
766                                generic_type_packs_iter
767                                    .next()
768                                    .map(GenericParametersWithDefaults::from_generic_type_pack)
769                            })
770                            .or_else(|| {
771                                generic_type_packs_with_default_iter
772                                    .next()
773                                    .map(GenericParametersWithDefaults::from_generic_type_pack_with_default)
774                            })
775                            .ok_or_else(|| ConvertError::GenericDeclaration {
776                                generics: generics.to_string(),
777                            })?;
778
779                        for type_variable in type_variable_iter {
780                            generic_parameters.push_type_variable(type_variable);
781                        }
782
783                        for type_variable_with_default in type_variable_with_default_iter {
784                            if !generic_parameters
785                                .push_type_variable_with_default(type_variable_with_default)
786                            {
787                                return Err(ConvertError::GenericDeclaration {
788                                    generics: generics.to_string(),
789                                });
790                            }
791                        }
792
793                        for generic_type_pack in generic_type_packs_iter {
794                            if !generic_parameters.push_generic_type_pack(generic_type_pack) {
795                                return Err(ConvertError::GenericDeclaration {
796                                    generics: generics.to_string(),
797                                });
798                            }
799                        }
800
801                        for generic_type_pack_with_default in generic_type_packs_with_default_iter {
802                            generic_parameters.push_generic_type_pack_with_default(
803                                generic_type_pack_with_default,
804                            );
805                        }
806
807                        if self.hold_token_data {
808                            let (opening_list, closing_list) =
809                                self.extract_contained_span_tokens(generics.arrows())?;
810                            generic_parameters.set_tokens(GenericParametersTokens {
811                                opening_list,
812                                closing_list,
813                                commas: self
814                                    .extract_tokens_from_punctuation(generics.generics())?,
815                            });
816                        }
817
818                        declaration.set_generic_parameters(generic_parameters);
819                    }
820
821                    if self.hold_token_data {
822                        declaration.set_tokens(TypeDeclarationTokens {
823                            r#type: self.convert_token(type_declaration.type_token())?,
824                            equal: self.convert_token(type_declaration.equal_token())?,
825                            export: export_token
826                                .map(|token| self.convert_token(token))
827                                .transpose()?,
828                        });
829                    }
830                    self.statements.push(declaration.into());
831                }
832                ConvertWork::MakeFunctionCallExpression { call } => {
833                    let call = self.make_function_call(call)?;
834                    self.expressions.push(call.into());
835                }
836                ConvertWork::MakeLocalFunctionStatement { statement } => {
837                    let builder = self.convert_function_body_attributes(
838                        statement.body(),
839                        self.convert_token(statement.function_token())?,
840                    )?;
841                    let mut name = Identifier::new(statement.name().token().to_string());
842                    let mut local_token = None;
843
844                    if self.hold_token_data {
845                        name.set_token(self.convert_token(statement.name())?);
846                        local_token = Some(self.convert_token(statement.local_token())?);
847                    }
848
849                    self.statements.push(
850                        builder
851                            .into_local_function_statement(name, local_token)
852                            .into(),
853                    );
854                }
855                ConvertWork::MakeLocalAssignStatement { statement } => {
856                    let variables = statement
857                        .names()
858                        .iter()
859                        .zip(statement.type_specifiers())
860                        .map(|(token_ref, type_specifier)| {
861                            self.convert_typed_identifier(token_ref, type_specifier)
862                        })
863                        .collect::<Result<Vec<_>, _>>()?;
864
865                    let mut local_assign = LocalAssignStatement::new(
866                        variables,
867                        self.pop_expressions(statement.expressions().len())?,
868                    );
869
870                    if self.hold_token_data {
871                        local_assign.set_tokens(LocalAssignTokens {
872                            local: self.convert_token(statement.local_token())?,
873                            equal: statement
874                                .equal_token()
875                                .map(|token| self.convert_token(token))
876                                .transpose()?,
877                            variable_commas: self
878                                .extract_tokens_from_punctuation(statement.names())?,
879                            value_commas: self
880                                .extract_tokens_from_punctuation(statement.expressions())?,
881                        })
882                    }
883                    self.statements.push(local_assign.into());
884                }
885                ConvertWork::MakeArgumentsFromExpressions {
886                    arguments,
887                    parentheses,
888                } => {
889                    let mut tuple = TupleArguments::new(self.pop_expressions(arguments.len())?);
890                    if self.hold_token_data {
891                        let (opening_parenthese, closing_parenthese) =
892                            self.extract_contained_span_tokens(parentheses)?;
893                        tuple.set_tokens(TupleArgumentsTokens {
894                            opening_parenthese,
895                            closing_parenthese,
896                            commas: self.extract_tokens_from_punctuation(arguments)?,
897                        })
898                    }
899                    self.arguments.push(tuple.into());
900                }
901                ConvertWork::MakeArgumentsFromTableEntries { table } => {
902                    let expression = self.make_table_expression(table)?;
903                    self.arguments.push(expression.into());
904                }
905                ConvertWork::MakeTableExpression { table } => {
906                    let expression = self.make_table_expression(table)?;
907                    self.expressions.push(expression.into());
908                }
909                ConvertWork::MakeAssignStatement { statement } => {
910                    let variables = self.pop_variables(statement.variables().len())?;
911                    let values = self.pop_expressions(statement.expressions().len())?;
912                    let mut assignment = AssignStatement::new(variables, values);
913                    if self.hold_token_data {
914                        assignment.set_tokens(AssignTokens {
915                            equal: self.convert_token(statement.equal_token())?,
916                            variable_commas: self
917                                .extract_tokens_from_punctuation(statement.variables())?,
918                            value_commas: self
919                                .extract_tokens_from_punctuation(statement.expressions())?,
920                        });
921                    }
922                    self.statements.push(assignment.into());
923                }
924                ConvertWork::MakeVariable { variable } => {
925                    let prefix = self.make_prefix_with_suffixes(variable.suffixes())?;
926                    let variable = match prefix {
927                        Prefix::Identifier(name) => Variable::Identifier(name),
928                        Prefix::Field(field) => Variable::Field(field),
929                        Prefix::Index(index) => Variable::Index(index),
930                        Prefix::Call(_) | Prefix::Parenthese(_) => {
931                            return Err(ConvertError::Variable {
932                                variable: variable.to_string(),
933                            })
934                        }
935                    };
936                    self.variables.push(variable);
937                }
938                ConvertWork::MakePrefixExpression { variable } => {
939                    let prefix = self.make_prefix_with_suffixes(variable.suffixes())?;
940                    self.expressions.push(prefix.into());
941                }
942                ConvertWork::MakeCompoundAssignStatement { statement } => {
943                    let variable = self.pop_variable()?;
944                    let value = self.pop_expression()?;
945                    let mut assignment = CompoundAssignStatement::new(
946                        self.convert_compound_op(statement.compound_operator())?,
947                        variable,
948                        value,
949                    );
950                    if self.hold_token_data {
951                        assignment.set_tokens(CompoundAssignTokens {
952                            operator: self.convert_token(get_compound_operator_token(
953                                statement.compound_operator(),
954                            )?)?,
955                        });
956                    }
957                    self.statements.push(assignment.into());
958                }
959                ConvertWork::MakeIfStatement { statement } => {
960                    let condition = self.pop_expression()?;
961                    let block = self.pop_block()?;
962                    let mut if_statement = IfStatement::create(condition, block);
963                    if let Some(elseifs) = statement.else_if() {
964                        for else_if in elseifs {
965                            let elseif_condition = self.pop_expression()?;
966                            let elseif_block = self.pop_block()?;
967                            let mut branch = IfBranch::new(elseif_condition, elseif_block);
968                            if self.hold_token_data {
969                                branch.set_tokens(IfBranchTokens {
970                                    elseif: self.convert_token(else_if.else_if_token())?,
971                                    then: self.convert_token(else_if.then_token())?,
972                                });
973                            }
974                            if_statement.push_branch(branch);
975                        }
976                    }
977                    if statement.else_block().is_some() {
978                        if_statement.set_else_block(self.pop_block()?);
979                    }
980                    if self.hold_token_data {
981                        if_statement.set_tokens(IfStatementTokens {
982                            r#if: self.convert_token(statement.if_token())?,
983                            then: self.convert_token(statement.then_token())?,
984                            end: self.convert_token(statement.end_token())?,
985                            r#else: statement
986                                .else_token()
987                                .map(|token| self.convert_token(token))
988                                .transpose()?,
989                        })
990                    }
991                    self.statements.push(if_statement.into());
992                }
993                ConvertWork::MakeFunctionReturnType { type_info } => {
994                    use ast::luau::TypeInfo;
995
996                    let return_type = if is_variadic_type(type_info).is_some() {
997                        self.pop_variadic_type_pack()?.into()
998                    } else {
999                        match type_info {
1000                            TypeInfo::Tuple { .. } => self.pop_type_pack()?.into(),
1001                            TypeInfo::GenericPack { .. } => self.pop_generic_type_pack()?.into(),
1002                            _ => self.pop_type()?.into(),
1003                        }
1004                    };
1005
1006                    self.function_return_types.push(return_type);
1007                }
1008                ConvertWork::MakeVariadicTypePack { ellipsis } => {
1009                    let mut variadic_type_pack = VariadicTypePack::new(self.pop_type()?);
1010
1011                    if self.hold_token_data {
1012                        variadic_type_pack.set_token(self.convert_token(ellipsis)?);
1013                    }
1014
1015                    self.variadic_type_packs.push(variadic_type_pack);
1016                }
1017                ConvertWork::MakeArrayType { braces } => {
1018                    let mut array_type = ArrayType::new(self.pop_type()?);
1019
1020                    if self.hold_token_data {
1021                        let (opening_brace, closing_brace) =
1022                            self.extract_contained_span_tokens(braces)?;
1023
1024                        array_type.set_tokens(ArrayTypeTokens {
1025                            opening_brace,
1026                            closing_brace,
1027                        })
1028                    }
1029
1030                    self.types.push(array_type.into());
1031                }
1032                ConvertWork::MakeOptionalType { question_mark } => {
1033                    let mut optional_type = OptionalType::new(self.pop_type()?);
1034
1035                    if self.hold_token_data {
1036                        optional_type.set_token(self.convert_token(question_mark)?);
1037                    }
1038
1039                    self.types.push(optional_type.into());
1040                }
1041                ConvertWork::MakeIntersectionType {
1042                    length,
1043                    leading_token,
1044                    separators,
1045                } => {
1046                    let types = self.pop_types(length)?;
1047
1048                    let mut intersection_type = IntersectionType::from(types);
1049
1050                    if self.hold_token_data {
1051                        intersection_type.set_tokens(IntersectionTypeTokens {
1052                            leading_token: leading_token
1053                                .map(|token| self.convert_token(token))
1054                                .transpose()?,
1055                            separators: self.extract_tokens_from_punctuation(separators)?,
1056                        });
1057                    } else if leading_token.is_some() {
1058                        intersection_type.put_leading_token();
1059                    }
1060
1061                    self.types.push(intersection_type.into());
1062                }
1063                ConvertWork::MakeUnionType {
1064                    length,
1065                    leading_token,
1066                    separators,
1067                } => {
1068                    let types = self.pop_types(length)?;
1069
1070                    let mut union_type = UnionType::from(types);
1071
1072                    if self.hold_token_data {
1073                        union_type.set_tokens(UnionTypeTokens {
1074                            leading_token: leading_token
1075                                .map(|token| self.convert_token(token))
1076                                .transpose()?,
1077                            separators: self.extract_tokens_from_punctuation(separators)?,
1078                        });
1079                    } else if leading_token.is_some() {
1080                        union_type.put_leading_token();
1081                    }
1082
1083                    self.types.push(union_type.into());
1084                }
1085                ConvertWork::MakeTableType { braces, fields } => {
1086                    let mut table_type = TableType::default();
1087
1088                    for field in fields {
1089                        use ast::luau::TypeFieldKey;
1090
1091                        match field.key() {
1092                            TypeFieldKey::Name(property_name) => {
1093                                let mut property_type = TablePropertyType::new(
1094                                    self.convert_token_to_identifier(property_name)?,
1095                                    self.pop_type()?,
1096                                );
1097
1098                                if self.hold_token_data {
1099                                    property_type
1100                                        .set_token(self.convert_token(field.colon_token())?);
1101                                }
1102
1103                                table_type.push_property(property_type);
1104                            }
1105                            TypeFieldKey::IndexSignature { brackets, .. } => {
1106                                let mut indexer_type =
1107                                    TableIndexerType::new(self.pop_type()?, self.pop_type()?);
1108
1109                                if self.hold_token_data {
1110                                    let (opening_bracket, closing_bracket) =
1111                                        self.extract_contained_span_tokens(brackets)?;
1112
1113                                    indexer_type.set_tokens(TableIndexTypeTokens {
1114                                        opening_bracket,
1115                                        closing_bracket,
1116                                        colon: self.convert_token(field.colon_token())?,
1117                                    })
1118                                }
1119
1120                                table_type.set_indexer_type(indexer_type);
1121                            }
1122                            key => {
1123                                return Err(ConvertError::TableTypeProperty {
1124                                    property: key.to_string(),
1125                                });
1126                            }
1127                        }
1128                    }
1129
1130                    if self.hold_token_data {
1131                        let (opening_brace, closing_brace) =
1132                            self.extract_contained_span_tokens(braces)?;
1133
1134                        table_type.set_tokens(TableTypeTokens {
1135                            opening_brace,
1136                            closing_brace,
1137                            separators: self.extract_tokens_from_punctuation(fields)?,
1138                        })
1139                    }
1140
1141                    self.types.push(table_type.into());
1142                }
1143                ConvertWork::MakeExpressionType {
1144                    typeof_token,
1145                    parentheses,
1146                } => {
1147                    let mut expression_type = ExpressionType::new(self.pop_expression()?);
1148
1149                    if self.hold_token_data {
1150                        let (opening_parenthese, closing_parenthese) =
1151                            self.extract_contained_span_tokens(parentheses)?;
1152
1153                        expression_type.set_tokens(ExpressionTypeTokens {
1154                            r#typeof: self.convert_token(typeof_token)?,
1155                            opening_parenthese,
1156                            closing_parenthese,
1157                        });
1158                    }
1159
1160                    self.types.push(expression_type.into());
1161                }
1162                ConvertWork::MakeFunctionType {
1163                    generics,
1164                    parentheses,
1165                    arguments,
1166                    arrow,
1167                } => {
1168                    let mut function_type = FunctionType::new(self.pop_function_return_type()?);
1169
1170                    for argument in arguments {
1171                        use ast::luau::TypeInfo;
1172
1173                        if is_variadic_type(argument.type_info()).is_some() {
1174                            function_type.set_variadic_type(self.pop_variadic_type_pack()?);
1175                        } else {
1176                            match argument.type_info() {
1177                                TypeInfo::Variadic { .. } | TypeInfo::VariadicPack { .. } => {
1178                                    function_type.set_variadic_type(self.pop_variadic_type_pack()?);
1179                                }
1180                                TypeInfo::GenericPack { .. } => {
1181                                    function_type.set_variadic_type(self.pop_generic_type_pack()?);
1182                                }
1183                                _ => {
1184                                    let mut argument_type =
1185                                        FunctionArgumentType::new(self.pop_type()?);
1186
1187                                    if let Some((name, colon)) = argument.name() {
1188                                        argument_type
1189                                            .set_name(self.convert_token_to_identifier(name)?);
1190
1191                                        if self.hold_token_data {
1192                                            argument_type.set_token(self.convert_token(colon)?);
1193                                        }
1194                                    }
1195
1196                                    function_type.push_argument(argument_type);
1197                                }
1198                            };
1199                        }
1200                    }
1201
1202                    if let Some(generics) = generics {
1203                        let generic_parameters = self.convert_generic_type_parameters(generics)?;
1204
1205                        function_type.set_generic_parameters(generic_parameters);
1206                    }
1207
1208                    if self.hold_token_data {
1209                        let (opening_parenthese, closing_parenthese) =
1210                            self.extract_contained_span_tokens(parentheses)?;
1211
1212                        function_type.set_tokens(FunctionTypeTokens {
1213                            opening_parenthese,
1214                            closing_parenthese,
1215                            arrow: self.convert_token(arrow)?,
1216                            commas: self.extract_tokens_from_punctuation(arguments)?,
1217                        });
1218                    }
1219
1220                    self.types.push(function_type.into());
1221                }
1222                ConvertWork::MakeGenericType { base, module } => {
1223                    let type_name = TypeName::new(self.convert_token_to_identifier(base)?)
1224                        .with_type_parameters(self.pop_type_parameters()?);
1225
1226                    self.types
1227                        .push(if let Some((module, punctuation)) = module {
1228                            let mut type_field = TypeField::new(
1229                                self.convert_token_to_identifier(module)?,
1230                                type_name,
1231                            );
1232
1233                            if self.hold_token_data {
1234                                type_field.set_token(self.convert_token(punctuation)?);
1235                            }
1236
1237                            type_field.into()
1238                        } else {
1239                            type_name.into()
1240                        });
1241                }
1242                ConvertWork::MakeTypeParameters { arrows, generics } => {
1243                    use ast::luau::TypeInfo;
1244
1245                    let mut parameters = generics
1246                        .iter()
1247                        .map(|type_parameter| {
1248                            if is_variadic_type(type_parameter).is_some() {
1249                                self.pop_variadic_type_pack().map(TypeParameter::from)
1250                            } else {
1251                                match type_parameter {
1252                                    TypeInfo::GenericPack { .. } => {
1253                                        self.pop_generic_type_pack().map(TypeParameter::from)
1254                                    }
1255                                    TypeInfo::VariadicPack { .. } | TypeInfo::Variadic { .. } => {
1256                                        self.pop_variadic_type_pack().map(TypeParameter::from)
1257                                    }
1258                                    TypeInfo::Tuple { .. } => {
1259                                        self.pop_type_pack().map(TypeParameter::from)
1260                                    }
1261                                    TypeInfo::Array { .. }
1262                                    | TypeInfo::Basic(_)
1263                                    | TypeInfo::String(_)
1264                                    | TypeInfo::Boolean(_)
1265                                    | TypeInfo::Callback { .. }
1266                                    | TypeInfo::Generic { .. }
1267                                    | TypeInfo::Intersection { .. }
1268                                    | TypeInfo::Module { .. }
1269                                    | TypeInfo::Optional { .. }
1270                                    | TypeInfo::Table { .. }
1271                                    | TypeInfo::Typeof { .. }
1272                                    | TypeInfo::Union { .. } => {
1273                                        self.pop_type().map(TypeParameter::from)
1274                                    }
1275                                    _ => Err(ConvertError::TypeInfo {
1276                                        type_info: type_parameter.to_string(),
1277                                    }),
1278                                }
1279                            }
1280                        })
1281                        .collect::<Result<TypeParameters, ConvertError>>()?;
1282
1283                    if self.hold_token_data {
1284                        let (opening_list, closing_list) =
1285                            self.extract_contained_span_tokens(arrows)?;
1286
1287                        let commas = self.extract_tokens_from_punctuation(generics)?;
1288
1289                        parameters.set_tokens(TypeParametersTokens {
1290                            opening_list,
1291                            closing_list,
1292                            commas,
1293                        })
1294                    }
1295
1296                    self.type_parameters.push(parameters);
1297                }
1298                ConvertWork::MakeTypeCast { type_assertion } => {
1299                    let r#type = self.pop_type()?;
1300                    let expression = self.pop_expression()?;
1301
1302                    let mut type_cast = TypeCastExpression::new(expression, r#type);
1303
1304                    if self.hold_token_data {
1305                        type_cast.set_token(self.convert_token(type_assertion.assertion_op())?);
1306                    }
1307
1308                    self.expressions.push(type_cast.into());
1309                }
1310                ConvertWork::MakeParentheseType { parentheses } => {
1311                    let r#type = self.pop_type()?;
1312
1313                    let mut parenthese_type = ParentheseType::new(r#type);
1314
1315                    if self.hold_token_data {
1316                        let (left_parenthese, right_parenthese) =
1317                            self.extract_contained_span_tokens(parentheses)?;
1318                        parenthese_type.set_tokens(ParentheseTypeTokens {
1319                            left_parenthese,
1320                            right_parenthese,
1321                        });
1322                    }
1323
1324                    self.types.push(parenthese_type.into());
1325                }
1326                ConvertWork::MakeTypePack { types, parentheses } => {
1327                    use ast::luau::TypeInfo;
1328
1329                    let mut type_pack = TypePack::default();
1330
1331                    let last_index = types.len().saturating_sub(1);
1332                    for (i, r#type) in types.iter().enumerate() {
1333                        if i == last_index && is_variadic_type(r#type).is_some() {
1334                            type_pack.set_variadic_type(self.pop_variadic_type_pack()?);
1335                        } else {
1336                            match r#type {
1337                                TypeInfo::GenericPack { .. } => {
1338                                    type_pack.set_variadic_type(self.pop_generic_type_pack()?);
1339                                }
1340                                _ => {
1341                                    type_pack.push_type(self.pop_type()?);
1342                                }
1343                            }
1344                        }
1345                    }
1346
1347                    if self.hold_token_data {
1348                        let (left_parenthese, right_parenthese) =
1349                            self.extract_contained_span_tokens(parentheses)?;
1350                        let commas = self.extract_tokens_from_punctuation(types)?;
1351                        type_pack.set_tokens(TypePackTokens {
1352                            left_parenthese,
1353                            right_parenthese,
1354                            commas,
1355                        });
1356                    }
1357
1358                    self.type_packs.push(type_pack);
1359                }
1360            }
1361        }
1362
1363        let mut block = self.blocks.pop().expect("root block should be converted");
1364
1365        if self.hold_token_data {
1366            if let Some(tokens) = block.mutate_tokens() {
1367                let token = self.convert_token(ast.eof())?;
1368                if token.has_trivia() {
1369                    tokens.final_token = Some(token);
1370                }
1371            }
1372        }
1373
1374        Ok(block)
1375    }
1376
1377    fn convert_generic_type_parameters(
1378        &mut self,
1379        generics: &ast::luau::GenericDeclaration,
1380    ) -> Result<GenericParameters, ConvertError> {
1381        let mut type_variables = Vec::new();
1382        let mut generic_type_packs = Vec::new();
1383        for parameter in generics.generics() {
1384            match parameter.parameter() {
1385                ast::luau::GenericParameterInfo::Name(name) => {
1386                    if !generic_type_packs.is_empty() {
1387                        return Err(ConvertError::GenericDeclaration {
1388                            generics: generics.to_string(),
1389                        });
1390                    }
1391                    type_variables.push(self.convert_token_to_identifier(name)?);
1392                }
1393                ast::luau::GenericParameterInfo::Variadic { name, ellipsis } => {
1394                    let mut generic_pack =
1395                        GenericTypePack::new(self.convert_token_to_identifier(name)?);
1396
1397                    if self.hold_token_data {
1398                        generic_pack.set_token(self.convert_token(ellipsis)?);
1399                    }
1400
1401                    generic_type_packs.push(generic_pack);
1402                }
1403                _ => {
1404                    return Err(ConvertError::GenericDeclaration {
1405                        generics: generics.to_string(),
1406                    })
1407                }
1408            }
1409        }
1410        let mut type_variables_iter = type_variables.into_iter();
1411        let mut generic_type_packs_iter = generic_type_packs.into_iter();
1412        let mut generic_parameters = type_variables_iter
1413            .next()
1414            .map(GenericParameters::from_type_variable)
1415            .or_else(|| {
1416                generic_type_packs_iter
1417                    .next()
1418                    .map(GenericParameters::from_generic_type_pack)
1419            })
1420            .ok_or_else(|| ConvertError::GenericDeclaration {
1421                generics: generics.to_string(),
1422            })?;
1423
1424        for type_variable in type_variables_iter {
1425            generic_parameters.push_type_variable(type_variable);
1426        }
1427
1428        for generic_pack in generic_type_packs_iter {
1429            generic_parameters.push_generic_type_pack(generic_pack);
1430        }
1431
1432        if self.hold_token_data {
1433            let (opening_list, closing_list) =
1434                self.extract_contained_span_tokens(generics.arrows())?;
1435            let commas = self.extract_tokens_from_punctuation(generics.generics())?;
1436            generic_parameters.set_tokens(GenericParametersTokens {
1437                opening_list,
1438                closing_list,
1439                commas,
1440            });
1441        }
1442
1443        Ok(generic_parameters)
1444    }
1445
1446    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1447    fn convert_statement(&mut self, statement: &'a ast::Stmt) -> Result<(), ConvertError> {
1448        match statement {
1449            ast::Stmt::Assignment(assignment) => {
1450                self.work_stack.push(ConvertWork::MakeAssignStatement {
1451                    statement: assignment,
1452                });
1453                for variable in assignment.variables() {
1454                    self.convert_variable(variable)?;
1455                }
1456                for expression in assignment.expressions() {
1457                    self.push_work(expression);
1458                }
1459            }
1460            ast::Stmt::Do(do_statement) => {
1461                self.work_stack.push(ConvertWork::MakeDoStatement {
1462                    statement: do_statement,
1463                });
1464                self.push_work(do_statement.block());
1465            }
1466            ast::Stmt::FunctionCall(call) => {
1467                self.work_stack
1468                    .push(ConvertWork::MakeFunctionCallStatement { call });
1469                self.convert_function_call(call)?;
1470            }
1471            ast::Stmt::FunctionDeclaration(function) => {
1472                self.work_stack.push(ConvertWork::MakeFunctionDeclaration {
1473                    statement: function,
1474                });
1475                self.push_function_body_work(function.body());
1476            }
1477            ast::Stmt::GenericFor(generic_for) => {
1478                self.work_stack.push(ConvertWork::MakeGenericForStatement {
1479                    statement: generic_for,
1480                });
1481                self.push_work(generic_for.block());
1482                for type_specifier in generic_for.type_specifiers().flatten() {
1483                    self.push_work(type_specifier.type_info());
1484                }
1485                for expression in generic_for.expressions().iter() {
1486                    self.push_work(expression);
1487                }
1488            }
1489            ast::Stmt::If(if_statement) => {
1490                self.work_stack.push(ConvertWork::MakeIfStatement {
1491                    statement: if_statement,
1492                });
1493                self.push_work(if_statement.condition());
1494                self.push_work(if_statement.block());
1495                if let Some(elseifs) = if_statement.else_if() {
1496                    for branch in elseifs {
1497                        self.push_work(branch.condition());
1498                        self.push_work(branch.block());
1499                    }
1500                }
1501                if let Some(block) = if_statement.else_block() {
1502                    self.push_work(block);
1503                }
1504            }
1505            ast::Stmt::LocalAssignment(local_assign) => {
1506                self.work_stack.push(ConvertWork::MakeLocalAssignStatement {
1507                    statement: local_assign,
1508                });
1509                for type_specifier in local_assign.type_specifiers().flatten() {
1510                    self.push_work(type_specifier.type_info());
1511                }
1512                for expression in local_assign.expressions().iter() {
1513                    self.push_work(expression);
1514                }
1515            }
1516            ast::Stmt::LocalFunction(local_function) => {
1517                self.work_stack
1518                    .push(ConvertWork::MakeLocalFunctionStatement {
1519                        statement: local_function,
1520                    });
1521                self.push_function_body_work(local_function.body());
1522            }
1523            ast::Stmt::NumericFor(numeric_for) => {
1524                self.work_stack.push(ConvertWork::MakeNumericForStatement {
1525                    statement: numeric_for,
1526                });
1527                if let Some(type_info) = numeric_for.type_specifier() {
1528                    self.push_work(type_info.type_info());
1529                }
1530                self.push_work(numeric_for.block());
1531                self.work_stack
1532                    .push(ConvertWork::Expression(numeric_for.start()));
1533                self.work_stack
1534                    .push(ConvertWork::Expression(numeric_for.end()));
1535                if let Some(step) = numeric_for.step() {
1536                    self.push_work(step);
1537                }
1538            }
1539            ast::Stmt::Repeat(repeat) => {
1540                self.work_stack
1541                    .push(ConvertWork::MakeRepeatStatement { statement: repeat });
1542                self.push_work(repeat.block());
1543                self.push_work(repeat.until());
1544            }
1545            ast::Stmt::While(while_statement) => {
1546                self.work_stack.push(ConvertWork::MakeWhileStatement {
1547                    statement: while_statement,
1548                });
1549                self.push_work(while_statement.block());
1550                self.push_work(while_statement.condition());
1551            }
1552            ast::Stmt::CompoundAssignment(assignment) => {
1553                self.work_stack
1554                    .push(ConvertWork::MakeCompoundAssignStatement {
1555                        statement: assignment,
1556                    });
1557                self.convert_variable(assignment.lhs())?;
1558                self.push_work(assignment.rhs());
1559            }
1560            ast::Stmt::ExportedTypeDeclaration(exported_type_declaration) => {
1561                let type_declaration = exported_type_declaration.type_declaration();
1562
1563                self.convert_type_declaration(
1564                    type_declaration,
1565                    Some(exported_type_declaration.export_token()),
1566                );
1567            }
1568            ast::Stmt::TypeDeclaration(type_declaration) => {
1569                self.convert_type_declaration(type_declaration, None);
1570            }
1571            _ => {
1572                return Err(ConvertError::Statement {
1573                    statement: statement.to_string(),
1574                })
1575            }
1576        }
1577        Ok(())
1578    }
1579
1580    fn convert_type_declaration(
1581        &mut self,
1582        type_declaration: &'a ast::luau::TypeDeclaration,
1583        export_token: Option<&'a tokenizer::TokenReference>,
1584    ) {
1585        self.work_stack
1586            .push(ConvertWork::MakeTypeDeclarationStatement {
1587                type_declaration,
1588                export_token,
1589            });
1590        self.push_work(type_declaration.type_definition());
1591
1592        if let Some(generics) = type_declaration.generics() {
1593            for parameter in generics.generics() {
1594                if let Some(default_type) = parameter.default_type() {
1595                    match (parameter.parameter(), default_type) {
1596                        (
1597                            ast::luau::GenericParameterInfo::Variadic { .. },
1598                            ast::luau::TypeInfo::Tuple { parentheses, types },
1599                        ) => {
1600                            self.push_type_pack_work(types, parentheses);
1601                        }
1602                        _ => {
1603                            self.push_maybe_variadic_type(default_type);
1604                        }
1605                    }
1606                }
1607            }
1608        }
1609    }
1610
1611    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1612    fn convert_table(&mut self, table: &'a ast::TableConstructor) -> Result<(), ConvertError> {
1613        for field in table.fields() {
1614            match field {
1615                ast::Field::ExpressionKey {
1616                    brackets: _,
1617                    key,
1618                    equal: _,
1619                    value,
1620                } => {
1621                    self.push_work(key);
1622                    self.push_work(value);
1623                }
1624                ast::Field::NameKey {
1625                    key: _,
1626                    equal: _,
1627                    value,
1628                } => {
1629                    self.push_work(value);
1630                }
1631                ast::Field::NoKey(value) => {
1632                    self.push_work(value);
1633                }
1634                _ => {
1635                    return Err(ConvertError::TableEntry {
1636                        entry: field.to_string(),
1637                    })
1638                }
1639            }
1640        }
1641        Ok(())
1642    }
1643
1644    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1645    fn make_table_expression(
1646        &mut self,
1647        table: &ast::TableConstructor,
1648    ) -> Result<TableExpression, ConvertError> {
1649        let entries: Result<_, _> = table
1650            .fields()
1651            .iter()
1652            .map(|field| match field {
1653                ast::Field::ExpressionKey {
1654                    brackets,
1655                    key: _,
1656                    equal,
1657                    value: _,
1658                } => {
1659                    let key = self.pop_expression()?;
1660                    let value = self.pop_expression()?;
1661                    let mut entry = TableIndexEntry::new(key, value);
1662                    if self.hold_token_data {
1663                        let (opening_bracket, closing_bracket) =
1664                            self.extract_contained_span_tokens(brackets)?;
1665                        entry.set_tokens(TableIndexEntryTokens {
1666                            opening_bracket,
1667                            closing_bracket,
1668                            equal: self.convert_token(equal)?,
1669                        })
1670                    }
1671                    Ok(entry.into())
1672                }
1673                ast::Field::NameKey {
1674                    key,
1675                    equal,
1676                    value: _,
1677                } => {
1678                    let mut entry = TableFieldEntry::new(
1679                        self.convert_token_to_identifier(key)?,
1680                        self.pop_expression()?,
1681                    );
1682                    if self.hold_token_data {
1683                        entry.set_token(self.convert_token(equal)?);
1684                    }
1685                    Ok(entry.into())
1686                }
1687                ast::Field::NoKey(_) => Ok(TableEntry::Value(self.pop_expression()?)),
1688                _ => Err(ConvertError::TableEntry {
1689                    entry: field.to_string(),
1690                }),
1691            })
1692            .collect();
1693        let mut expression = TableExpression::new(entries?);
1694        if self.hold_token_data {
1695            let (opening_brace, closing_brace) =
1696                self.extract_contained_span_tokens(table.braces())?;
1697            expression.set_tokens(TableTokens {
1698                opening_brace,
1699                closing_brace,
1700                separators: self.extract_tokens_from_punctuation(table.fields())?,
1701            });
1702        }
1703        Ok(expression)
1704    }
1705
1706    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1707    fn make_function_call(
1708        &mut self,
1709        call: &'a ast::FunctionCall,
1710    ) -> Result<FunctionCall, ConvertError> {
1711        let prefix = self.make_prefix_with_suffixes(call.suffixes())?;
1712        match prefix {
1713            Prefix::Call(call) => Ok(call),
1714            _ => panic!(
1715                "FunctionCall should convert to a call statement, but got {:#?}",
1716                prefix,
1717            ),
1718        }
1719    }
1720
1721    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1722    fn make_prefix_with_suffixes(
1723        &mut self,
1724        suffixes: impl Iterator<Item = &'a ast::Suffix>,
1725    ) -> Result<Prefix, ConvertError> {
1726        let mut prefix = self.pop_prefix()?;
1727
1728        for suffix in suffixes {
1729            match suffix {
1730                ast::Suffix::Call(call_suffix) => match call_suffix {
1731                    ast::Call::AnonymousCall(_) => {
1732                        let mut call = FunctionCall::new(prefix, self.pop_arguments()?, None);
1733                        if self.hold_token_data {
1734                            call.set_tokens(FunctionCallTokens { colon: None })
1735                        }
1736                        prefix = call.into();
1737                    }
1738                    ast::Call::MethodCall(method_call) => {
1739                        let mut call = FunctionCall::new(
1740                            prefix,
1741                            self.pop_arguments()?,
1742                            Some(self.convert_token_to_identifier(method_call.name())?),
1743                        );
1744                        if self.hold_token_data {
1745                            call.set_tokens(FunctionCallTokens {
1746                                colon: Some(self.convert_token(method_call.colon_token())?),
1747                            });
1748                        }
1749                        prefix = call.into();
1750                    }
1751                    _ => {
1752                        return Err(ConvertError::Call {
1753                            call: call_suffix.to_string(),
1754                        });
1755                    }
1756                },
1757                ast::Suffix::Index(index) => match index {
1758                    ast::Index::Brackets {
1759                        brackets,
1760                        expression: _,
1761                    } => {
1762                        let mut index = IndexExpression::new(prefix, self.pop_expression()?);
1763                        if self.hold_token_data {
1764                            let (opening_bracket, closing_bracket) =
1765                                self.extract_contained_span_tokens(brackets)?;
1766                            index.set_tokens(IndexExpressionTokens {
1767                                opening_bracket,
1768                                closing_bracket,
1769                            });
1770                        }
1771                        prefix = index.into();
1772                    }
1773                    ast::Index::Dot { name, dot } => {
1774                        let mut field =
1775                            FieldExpression::new(prefix, self.convert_token_to_identifier(name)?);
1776                        if self.hold_token_data {
1777                            field.set_token(self.convert_token(dot)?);
1778                        }
1779                        prefix = field.into();
1780                    }
1781                    _ => {
1782                        return Err(ConvertError::Index {
1783                            index: index.to_string(),
1784                        });
1785                    }
1786                },
1787                _ => {
1788                    return Err(ConvertError::Suffix {
1789                        suffix: suffix.to_string(),
1790                    });
1791                }
1792            }
1793        }
1794
1795        Ok(prefix)
1796    }
1797
1798    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1799    fn convert_expression(&mut self, expression: &'a ast::Expression) -> Result<(), ConvertError> {
1800        match expression {
1801            ast::Expression::BinaryOperator { lhs, binop, rhs } => {
1802                self.work_stack
1803                    .push(ConvertWork::MakeBinaryExpression { operator: binop });
1804                self.work_stack.push(ConvertWork::Expression(lhs));
1805                self.work_stack.push(ConvertWork::Expression(rhs));
1806            }
1807            ast::Expression::Parentheses {
1808                contained,
1809                expression: inner_expression,
1810            } => {
1811                self.work_stack.push(ConvertWork::MakeParentheseExpression {
1812                    contained_span: contained,
1813                });
1814                self.work_stack
1815                    .push(ConvertWork::Expression(inner_expression));
1816            }
1817            ast::Expression::UnaryOperator { unop, expression } => {
1818                self.work_stack
1819                    .push(ConvertWork::MakeUnaryExpression { operator: unop });
1820                self.work_stack.push(ConvertWork::Expression(expression));
1821            }
1822            ast::Expression::TypeAssertion {
1823                expression,
1824                type_assertion,
1825            } => {
1826                self.work_stack
1827                    .push(ConvertWork::MakeTypeCast { type_assertion });
1828                self.push_work(type_assertion.cast_to());
1829                self.push_work(expression.as_ref());
1830            }
1831            ast::Expression::Function(function) => {
1832                let (token, body) = function.as_ref();
1833                self.work_stack
1834                    .push(ConvertWork::MakeFunctionExpression { body, token });
1835
1836                self.push_function_body_work(body);
1837            }
1838            ast::Expression::FunctionCall(call) => {
1839                self.work_stack
1840                    .push(ConvertWork::MakeFunctionCallExpression { call });
1841                self.convert_function_call(call)?;
1842            }
1843            ast::Expression::TableConstructor(table) => {
1844                self.work_stack
1845                    .push(ConvertWork::MakeTableExpression { table });
1846                self.convert_table(table)?;
1847            }
1848            ast::Expression::Number(number) => {
1849                let mut expression = NumberExpression::from_str(&number.token().to_string())
1850                    .map_err(|err| ConvertError::Number {
1851                        number: number.to_string(),
1852                        parsing_error: err.to_string(),
1853                    })?;
1854                if self.hold_token_data {
1855                    expression.set_token(self.convert_token(number)?);
1856                }
1857                self.work_stack
1858                    .push(ConvertWork::PushExpression(expression.into()));
1859            }
1860            ast::Expression::String(token_ref) => {
1861                self.work_stack.push(ConvertWork::PushExpression(
1862                    self.convert_string_expression(token_ref)?.into(),
1863                ));
1864            }
1865            ast::Expression::Symbol(symbol_token) => match symbol_token.token().token_type() {
1866                TokenType::Symbol { symbol } => {
1867                    let token = if self.hold_token_data {
1868                        Some(self.convert_token(symbol_token)?)
1869                    } else {
1870                        None
1871                    };
1872                    let expression = match symbol {
1873                        Symbol::True => Expression::True(token),
1874                        Symbol::False => Expression::False(token),
1875                        Symbol::Nil => Expression::Nil(token),
1876                        Symbol::Ellipsis => Expression::VariableArguments(token),
1877                        _ => {
1878                            return Err(ConvertError::Expression {
1879                                expression: expression.to_string(),
1880                            })
1881                        }
1882                    };
1883                    self.work_stack
1884                        .push(ConvertWork::PushExpression(expression));
1885                }
1886                _ => {
1887                    return Err(ConvertError::Expression {
1888                        expression: expression.to_string(),
1889                    })
1890                }
1891            },
1892            ast::Expression::Var(var) => match var {
1893                ast::Var::Expression(var_expression) => {
1894                    self.work_stack.push(ConvertWork::MakePrefixExpression {
1895                        variable: var_expression,
1896                    });
1897                    self.push_work(var_expression.prefix());
1898                    self.convert_suffixes(var_expression.suffixes())?;
1899                }
1900                ast::Var::Name(token_ref) => {
1901                    self.work_stack
1902                        .push(ConvertWork::PushExpression(Expression::Identifier(
1903                            self.convert_token_to_identifier(token_ref)?,
1904                        )));
1905                }
1906                _ => {
1907                    return Err(ConvertError::Expression {
1908                        expression: expression.to_string(),
1909                    })
1910                }
1911            },
1912            ast::Expression::IfExpression(if_expression) => {
1913                self.push_work(ConvertWork::MakeIfExpression { if_expression });
1914                self.push_work(if_expression.condition());
1915                self.push_work(if_expression.if_expression());
1916                self.push_work(if_expression.else_expression());
1917                if let Some(elseif_expressions) = if_expression.else_if_expressions() {
1918                    for elseif in elseif_expressions {
1919                        self.push_work(elseif.condition());
1920                        self.push_work(elseif.expression());
1921                    }
1922                }
1923            }
1924            ast::Expression::InterpolatedString(interpolated_string) => {
1925                self.push_work(ConvertWork::MakeInterpolatedString {
1926                    interpolated_string,
1927                });
1928                for segment in interpolated_string.segments() {
1929                    self.push_work(&segment.expression);
1930                }
1931            }
1932            _ => {
1933                return Err(ConvertError::Expression {
1934                    expression: expression.to_string(),
1935                })
1936            }
1937        }
1938        Ok(())
1939    }
1940
1941    fn push_function_body_work(&mut self, body: &'a ast::FunctionBody) {
1942        self.push_work(body.block());
1943        if let Some(return_type) = body.return_type() {
1944            self.push_function_return_type(return_type.type_info());
1945        }
1946        for type_specifier in body.type_specifiers().flatten() {
1947            self.push_work(type_specifier.type_info());
1948        }
1949    }
1950
1951    fn push_function_return_type(&mut self, return_type: &'a ast::luau::TypeInfo) {
1952        self.push_work(ConvertWork::MakeFunctionReturnType {
1953            type_info: return_type,
1954        });
1955        match return_type {
1956            ast::luau::TypeInfo::Tuple { types, parentheses } => {
1957                self.push_type_pack_work(types, parentheses);
1958            }
1959            _ => {
1960                self.push_maybe_variadic_type(return_type);
1961            }
1962        };
1963    }
1964
1965    fn push_type_pack_work(
1966        &mut self,
1967        types: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
1968        parentheses: &'a ast::span::ContainedSpan,
1969    ) {
1970        self.work_stack
1971            .push(ConvertWork::MakeTypePack { types, parentheses });
1972
1973        let last_index = types.len().saturating_sub(1);
1974        for (i, r#type) in types.iter().enumerate() {
1975            if i == last_index {
1976                self.push_maybe_variadic_type(r#type);
1977            } else {
1978                self.push_work(r#type)
1979            }
1980        }
1981    }
1982
1983    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
1984    fn convert_type_info(
1985        &mut self,
1986        type_info: &'a ast::luau::TypeInfo,
1987    ) -> Result<(), ConvertError> {
1988        use ast::luau::TypeInfo;
1989
1990        match type_info {
1991            TypeInfo::Array {
1992                braces,
1993                type_info,
1994                access: _,
1995            } => {
1996                self.work_stack.push(ConvertWork::MakeArrayType { braces });
1997
1998                self.push_work(type_info.as_ref());
1999            }
2000            TypeInfo::Basic(token_ref) => {
2001                if let TokenType::Symbol { symbol } = token_ref.token_type() {
2002                    let token = if self.hold_token_data {
2003                        Some(self.convert_token(token_ref)?)
2004                    } else {
2005                        None
2006                    };
2007                    let new_type = match symbol {
2008                        Symbol::Nil => Type::Nil(token),
2009                        _ => {
2010                            return Err(ConvertError::TypeInfo {
2011                                type_info: type_info.to_string(),
2012                            })
2013                        }
2014                    };
2015                    self.work_stack.push(ConvertWork::PushType(new_type));
2016                } else {
2017                    self.work_stack.push(ConvertWork::PushType(
2018                        TypeName::new(self.convert_token_to_identifier(token_ref)?).into(),
2019                    ));
2020                }
2021            }
2022            TypeInfo::String(token) => {
2023                self.work_stack.push(ConvertWork::PushType(
2024                    self.convert_string_type(token)?.into(),
2025                ));
2026            }
2027            TypeInfo::Boolean(token_ref) => {
2028                if let TokenType::Symbol { symbol } = token_ref.token_type() {
2029                    let token = if self.hold_token_data {
2030                        Some(self.convert_token(token_ref)?)
2031                    } else {
2032                        None
2033                    };
2034                    let new_type = match symbol {
2035                        Symbol::True => Type::True(token),
2036                        Symbol::False => Type::False(token),
2037                        _ => {
2038                            return Err(ConvertError::TypeInfo {
2039                                type_info: type_info.to_string(),
2040                            })
2041                        }
2042                    };
2043                    self.work_stack.push(ConvertWork::PushType(new_type));
2044                } else {
2045                    return Err(ConvertError::TypeInfo {
2046                        type_info: type_info.to_string(),
2047                    });
2048                }
2049            }
2050            TypeInfo::Callback {
2051                generics,
2052                parentheses,
2053                arguments,
2054                arrow,
2055                return_type,
2056            } => {
2057                self.work_stack.push(ConvertWork::MakeFunctionType {
2058                    generics,
2059                    parentheses,
2060                    arguments,
2061                    arrow,
2062                });
2063
2064                self.push_function_return_type(return_type);
2065
2066                let mut has_variadic_type = false;
2067
2068                for argument in arguments {
2069                    let argument_type = argument.type_info();
2070                    if is_argument_variadic(argument_type) {
2071                        if has_variadic_type {
2072                            return Err(ConvertError::TypeInfo {
2073                                type_info: type_info.to_string(),
2074                            });
2075                        }
2076                        has_variadic_type = true;
2077                    }
2078                    self.push_maybe_variadic_type(argument_type);
2079                }
2080            }
2081            TypeInfo::Generic {
2082                base,
2083                arrows,
2084                generics,
2085            } => {
2086                self.push_generic_type_work(base, arrows, generics, None);
2087            }
2088            TypeInfo::GenericPack { name, ellipsis } => {
2089                let mut generic_pack =
2090                    GenericTypePack::new(self.convert_token_to_identifier(name)?);
2091
2092                if self.hold_token_data {
2093                    generic_pack.set_token(self.convert_token(ellipsis)?);
2094                }
2095
2096                self.generic_type_packs.push(generic_pack);
2097            }
2098            TypeInfo::Intersection(intersection) => {
2099                self.work_stack.push(ConvertWork::MakeIntersectionType {
2100                    leading_token: intersection.leading(),
2101                    separators: intersection.types(),
2102                    length: intersection.types().len(),
2103                });
2104
2105                for type_info in intersection.types() {
2106                    self.push_work(type_info);
2107                }
2108            }
2109            TypeInfo::Union(union) => {
2110                self.work_stack.push(ConvertWork::MakeUnionType {
2111                    leading_token: union.leading(),
2112                    separators: union.types(),
2113                    length: union.types().len(),
2114                });
2115
2116                for type_info in union.types() {
2117                    self.push_work(type_info);
2118                }
2119            }
2120            TypeInfo::Module {
2121                module,
2122                punctuation,
2123                type_info,
2124            } => match type_info.as_ref() {
2125                ast::luau::IndexedTypeInfo::Basic(name) => {
2126                    let mut type_field = TypeField::new(
2127                        self.convert_token_to_identifier(module)?,
2128                        TypeName::new(self.convert_token_to_identifier(name)?),
2129                    );
2130
2131                    if self.hold_token_data {
2132                        type_field.set_token(self.convert_token(punctuation)?);
2133                    }
2134
2135                    self.work_stack
2136                        .push(ConvertWork::PushType(type_field.into()));
2137                }
2138                ast::luau::IndexedTypeInfo::Generic {
2139                    base,
2140                    arrows,
2141                    generics,
2142                } => {
2143                    self.push_generic_type_work(
2144                        base,
2145                        arrows,
2146                        generics,
2147                        Some((module, punctuation)),
2148                    );
2149                }
2150                _ => {
2151                    return Err(ConvertError::TypeInfo {
2152                        type_info: type_info.to_string(),
2153                    });
2154                }
2155            },
2156            TypeInfo::Optional {
2157                base,
2158                question_mark,
2159            } => {
2160                self.work_stack
2161                    .push(ConvertWork::MakeOptionalType { question_mark });
2162
2163                self.push_work(base.as_ref());
2164            }
2165            TypeInfo::Table { braces, fields } => {
2166                self.work_stack
2167                    .push(ConvertWork::MakeTableType { braces, fields });
2168
2169                for field in fields {
2170                    use ast::luau::TypeFieldKey;
2171
2172                    match field.key() {
2173                        TypeFieldKey::Name(_) => {}
2174                        TypeFieldKey::IndexSignature { inner, .. } => {
2175                            self.push_work(inner);
2176                        }
2177                        key => {
2178                            return Err(ConvertError::TableTypeProperty {
2179                                property: key.to_string(),
2180                            });
2181                        }
2182                    }
2183
2184                    self.push_work(field.value());
2185                }
2186            }
2187            TypeInfo::Typeof {
2188                typeof_token,
2189                parentheses,
2190                inner,
2191            } => {
2192                self.work_stack.push(ConvertWork::MakeExpressionType {
2193                    typeof_token,
2194                    parentheses,
2195                });
2196
2197                self.push_work(inner.as_ref());
2198            }
2199            TypeInfo::Tuple { types, parentheses } => {
2200                if types.len() == 1 {
2201                    self.work_stack
2202                        .push(ConvertWork::MakeParentheseType { parentheses });
2203                    self.push_work(
2204                        types
2205                            .iter()
2206                            .next()
2207                            .expect("types should contain exactly one type at this point"),
2208                    );
2209                } else {
2210                    return Err(ConvertError::TypeInfo {
2211                        type_info: type_info.to_string(),
2212                    });
2213                }
2214            }
2215            TypeInfo::Variadic { type_info, .. } => {
2216                self.push_work(type_info.as_ref());
2217            }
2218            TypeInfo::VariadicPack { name, .. } => {
2219                self.types
2220                    .push(TypeName::new(self.convert_token_to_identifier(name)?).into());
2221            }
2222            _ => {
2223                return Err(ConvertError::TypeInfo {
2224                    type_info: type_info.to_string(),
2225                });
2226            }
2227        }
2228
2229        Ok(())
2230    }
2231
2232    fn push_maybe_variadic_type(&mut self, type_info: &'a ast::luau::TypeInfo) {
2233        if let Some(ellipsis) = is_variadic_type(type_info) {
2234            self.work_stack
2235                .push(ConvertWork::MakeVariadicTypePack { ellipsis });
2236        }
2237        self.push_work(type_info);
2238    }
2239
2240    fn push_generic_type_work(
2241        &mut self,
2242        base: &'a tokenizer::TokenReference,
2243        arrows: &'a ast::span::ContainedSpan,
2244        generics: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
2245        module: Option<(&'a tokenizer::TokenReference, &'a tokenizer::TokenReference)>,
2246    ) {
2247        self.work_stack
2248            .push(ConvertWork::MakeGenericType { base, module });
2249
2250        self.work_stack
2251            .push(ConvertWork::MakeTypeParameters { arrows, generics });
2252
2253        for parameter_type in generics {
2254            match parameter_type {
2255                ast::luau::TypeInfo::Tuple { parentheses, types } => {
2256                    self.push_type_pack_work(types, parentheses);
2257                }
2258                _ => {
2259                    self.push_maybe_variadic_type(parameter_type);
2260                }
2261            }
2262        }
2263    }
2264
2265    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2266    fn convert_function_call(&mut self, call: &'a ast::FunctionCall) -> Result<(), ConvertError> {
2267        self.push_work(call.prefix());
2268        self.convert_suffixes(call.suffixes())?;
2269        Ok(())
2270    }
2271
2272    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2273    fn convert_suffixes(
2274        &mut self,
2275        suffixes: impl Iterator<Item = &'a ast::Suffix>,
2276    ) -> Result<(), ConvertError> {
2277        for suffix in suffixes {
2278            match suffix {
2279                ast::Suffix::Call(call_suffix) => match call_suffix {
2280                    ast::Call::AnonymousCall(arguments) => {
2281                        self.push_work(arguments);
2282                    }
2283                    ast::Call::MethodCall(method_call) => {
2284                        self.push_work(method_call.args());
2285                    }
2286                    _ => {
2287                        return Err(ConvertError::Call {
2288                            call: call_suffix.to_string(),
2289                        });
2290                    }
2291                },
2292                ast::Suffix::Index(index) => match index {
2293                    ast::Index::Brackets {
2294                        brackets: _,
2295                        expression,
2296                    } => {
2297                        self.push_work(expression);
2298                    }
2299                    ast::Index::Dot { name: _, dot: _ } => {}
2300                    _ => {
2301                        return Err(ConvertError::Index {
2302                            index: index.to_string(),
2303                        });
2304                    }
2305                },
2306                _ => {
2307                    return Err(ConvertError::Suffix {
2308                        suffix: suffix.to_string(),
2309                    });
2310                }
2311            }
2312        }
2313        Ok(())
2314    }
2315
2316    fn convert_token_position(
2317        &self,
2318        token: &tokenizer::TokenReference,
2319    ) -> Result<(usize, usize, usize), ConvertError> {
2320        let start = token
2321            .start_position()
2322            .ok_or_else(|| ConvertError::TokenPositionNotFound {
2323                token: token.to_string(),
2324            })?;
2325        Ok((
2326            start.bytes(),
2327            token
2328                .end_position()
2329                .ok_or_else(|| ConvertError::TokenPositionNotFound {
2330                    token: token.to_string(),
2331                })?
2332                .bytes(),
2333            start.line(),
2334        ))
2335    }
2336
2337    fn convert_token_end_position(
2338        &self,
2339        token: &tokenizer::TokenReference,
2340    ) -> Result<(usize, usize), ConvertError> {
2341        let end_position =
2342            token
2343                .end_position()
2344                .ok_or_else(|| ConvertError::TokenPositionNotFound {
2345                    token: token.to_string(),
2346                })?;
2347        Ok((end_position.bytes(), end_position.line()))
2348    }
2349
2350    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2351    fn convert_token(&self, token: &tokenizer::TokenReference) -> Result<Token, ConvertError> {
2352        let position = self.convert_token_position(token)?;
2353        let mut new_token = Token::new_with_line(position.0, position.1, position.2);
2354
2355        for trivia_token in token.leading_trivia() {
2356            new_token.push_leading_trivia(self.convert_trivia(trivia_token)?);
2357        }
2358
2359        for trivia_token in token.trailing_trivia() {
2360            new_token.push_trailing_trivia(self.convert_trivia(trivia_token)?);
2361        }
2362
2363        Ok(new_token)
2364    }
2365
2366    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2367    fn convert_trivia(&self, token: &tokenizer::Token) -> Result<Trivia, ConvertError> {
2368        use tokenizer::TokenKind;
2369
2370        let trivia = match token.token_kind() {
2371            TokenKind::MultiLineComment => TriviaKind::Comment,
2372            TokenKind::SingleLineComment => TriviaKind::Comment,
2373            TokenKind::Whitespace => TriviaKind::Whitespace,
2374            _ => return Err(ConvertError::UnexpectedTrivia(token.token_kind())),
2375        }
2376        .at(
2377            token.start_position().bytes(),
2378            token.end_position().bytes(),
2379            token.start_position().line(),
2380        );
2381        Ok(trivia)
2382    }
2383
2384    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2385    fn convert_token_to_identifier(
2386        &self,
2387        token: &tokenizer::TokenReference,
2388    ) -> Result<Identifier, ConvertError> {
2389        let mut identifier = Identifier::new(token.token().to_string());
2390        if self.hold_token_data {
2391            identifier.set_token(self.convert_token(token)?);
2392        }
2393        Ok(identifier)
2394    }
2395
2396    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2397    fn convert_typed_identifier(
2398        &mut self,
2399        identifier: &tokenizer::TokenReference,
2400        type_specifier: Option<&ast::luau::TypeSpecifier>,
2401    ) -> Result<TypedIdentifier, ConvertError> {
2402        let identifier = self.convert_token_to_identifier(identifier)?;
2403
2404        Ok(if let Some(type_specifier) = type_specifier {
2405            let mut typed_identifier = identifier.with_type(self.pop_type()?);
2406            if self.hold_token_data {
2407                typed_identifier.set_colon_token(self.convert_token(type_specifier.punctuation())?);
2408            }
2409            typed_identifier
2410        } else {
2411            identifier.into()
2412        })
2413    }
2414
2415    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2416    fn extract_tokens_from_punctuation<T>(
2417        &self,
2418        punctuated: &ast::punctuated::Punctuated<T>,
2419    ) -> Result<Vec<Token>, ConvertError> {
2420        punctuated
2421            .pairs()
2422            .filter_map(|pair| match pair {
2423                ast::punctuated::Pair::End(_) => None,
2424                ast::punctuated::Pair::Punctuated(_, token) => Some(self.convert_token(token)),
2425            })
2426            .collect()
2427    }
2428
2429    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2430    fn extract_contained_span_tokens(
2431        &self,
2432        contained_span: &ast::span::ContainedSpan,
2433    ) -> Result<(Token, Token), ConvertError> {
2434        let (left, right) = contained_span.tokens();
2435        Ok((self.convert_token(left)?, self.convert_token(right)?))
2436    }
2437
2438    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2439    fn convert_function_body_attributes(
2440        &mut self,
2441        body: &ast::FunctionBody,
2442        function_token: Token,
2443    ) -> Result<FunctionBuilder, ConvertError> {
2444        let mut builder = FunctionBuilder::from_block(self.pop_block()?);
2445
2446        if let Some(return_type) = body.return_type() {
2447            if self.hold_token_data {
2448                builder.set_return_type_colon(self.convert_token(return_type.punctuation())?);
2449            }
2450            builder.set_return_type(self.pop_function_return_type()?);
2451        };
2452
2453        for (param, type_specifier) in body.parameters().iter().zip(body.type_specifiers()) {
2454            match param {
2455                ast::Parameter::Ellipsis(token) => {
2456                    if builder.is_variadic() {
2457                        return Err(ConvertError::FunctionParameters {
2458                            parameters: body.parameters().to_string(),
2459                        });
2460                    } else {
2461                        if let Some(type_specifier) = type_specifier {
2462                            builder.set_variadic_type(
2463                                if let ast::luau::TypeInfo::GenericPack { .. } =
2464                                    type_specifier.type_info()
2465                                {
2466                                    self.pop_generic_type_pack()?.into()
2467                                } else {
2468                                    self.pop_type()?.into()
2469                                },
2470                            );
2471
2472                            if self.hold_token_data {
2473                                builder.set_variable_arguments_colon(
2474                                    self.convert_token(type_specifier.punctuation())?,
2475                                );
2476                            }
2477                        } else {
2478                            builder.set_variadic();
2479                        }
2480                        if self.hold_token_data {
2481                            builder.set_variable_arguments_token(self.convert_token(token)?);
2482                        }
2483                    }
2484                }
2485                ast::Parameter::Name(name) => {
2486                    if builder.is_variadic() {
2487                        return Err(ConvertError::FunctionParameters {
2488                            parameters: body.parameters().to_string(),
2489                        });
2490                    }
2491                    let mut identifier = Identifier::new(name.token().to_string());
2492                    if self.hold_token_data {
2493                        identifier.set_token(self.convert_token(name)?);
2494                    }
2495
2496                    if let Some(type_specifier) = type_specifier {
2497                        let type_value = self.pop_type()?;
2498                        let mut typed_identifier =
2499                            TypedIdentifier::from(identifier).with_type(type_value);
2500                        if self.hold_token_data {
2501                            typed_identifier
2502                                .set_colon_token(self.convert_token(type_specifier.punctuation())?);
2503                        }
2504                        builder.push_parameter(typed_identifier);
2505                    } else {
2506                        builder.push_parameter(identifier.into());
2507                    }
2508                }
2509                _ => {
2510                    return Err(ConvertError::FunctionParameter {
2511                        parameter: param.to_string(),
2512                    })
2513                }
2514            }
2515        }
2516
2517        if let Some(generics) = body.generics() {
2518            let generic_parameters = self.convert_generic_type_parameters(generics)?;
2519            builder.set_generic_parameters(generic_parameters);
2520        }
2521
2522        if self.hold_token_data {
2523            let (open, close) =
2524                self.extract_contained_span_tokens(body.parameters_parentheses())?;
2525
2526            builder.set_parentheses_tokens(open, close);
2527            builder.set_parameter_commas(self.extract_tokens_from_punctuation(body.parameters())?);
2528            builder.set_function_token(function_token);
2529            builder.set_end_token(self.convert_token(body.end_token())?);
2530        }
2531
2532        Ok(builder)
2533    }
2534
2535    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2536    fn convert_string_expression(
2537        &self,
2538        string: &tokenizer::TokenReference,
2539    ) -> Result<StringExpression, ConvertError> {
2540        let mut expression =
2541            StringExpression::new(&string.token().to_string()).map_err(|_err| {
2542                ConvertError::String {
2543                    string: string.to_string(),
2544                }
2545            })?;
2546
2547        if self.hold_token_data {
2548            expression.set_token(self.convert_token(string)?);
2549        }
2550        Ok(expression)
2551    }
2552
2553    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2554    fn convert_string_type(
2555        &self,
2556        string: &tokenizer::TokenReference,
2557    ) -> Result<StringType, ConvertError> {
2558        let mut expression =
2559            StringType::new(&string.token().to_string()).map_err(|_err| ConvertError::String {
2560                string: string.to_string(),
2561            })?;
2562        if self.hold_token_data {
2563            expression.set_token(self.convert_token(string)?);
2564        }
2565        Ok(expression)
2566    }
2567
2568    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2569    fn convert_binop(&self, operator: &ast::BinOp) -> Result<BinaryOperator, ConvertError> {
2570        Ok(match operator {
2571            ast::BinOp::And(_) => BinaryOperator::And,
2572            ast::BinOp::Caret(_) => BinaryOperator::Caret,
2573            ast::BinOp::GreaterThan(_) => BinaryOperator::GreaterThan,
2574            ast::BinOp::GreaterThanEqual(_) => BinaryOperator::GreaterOrEqualThan,
2575            ast::BinOp::LessThan(_) => BinaryOperator::LowerThan,
2576            ast::BinOp::LessThanEqual(_) => BinaryOperator::LowerOrEqualThan,
2577            ast::BinOp::Minus(_) => BinaryOperator::Minus,
2578            ast::BinOp::Or(_) => BinaryOperator::Or,
2579            ast::BinOp::Percent(_) => BinaryOperator::Percent,
2580            ast::BinOp::Plus(_) => BinaryOperator::Plus,
2581            ast::BinOp::Slash(_) => BinaryOperator::Slash,
2582            ast::BinOp::DoubleSlash(_) => BinaryOperator::DoubleSlash,
2583            ast::BinOp::Star(_) => BinaryOperator::Asterisk,
2584            ast::BinOp::TildeEqual(_) => BinaryOperator::NotEqual,
2585            ast::BinOp::TwoDots(_) => BinaryOperator::Concat,
2586            ast::BinOp::TwoEqual(_) => BinaryOperator::Equal,
2587            _ => {
2588                return Err(ConvertError::BinaryOperator {
2589                    operator: operator.to_string(),
2590                })
2591            }
2592        })
2593    }
2594
2595    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2596    fn convert_unop(&self, operator: &ast::UnOp) -> Result<UnaryOperator, ConvertError> {
2597        Ok(match operator {
2598            ast::UnOp::Minus(_) => UnaryOperator::Minus,
2599            ast::UnOp::Not(_) => UnaryOperator::Not,
2600            ast::UnOp::Hash(_) => UnaryOperator::Length,
2601            _ => {
2602                return Err(ConvertError::UnaryOperator {
2603                    operator: operator.to_string(),
2604                })
2605            }
2606        })
2607    }
2608
2609    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2610    fn convert_compound_op(
2611        &self,
2612        operator: &ast::luau::CompoundOp,
2613    ) -> Result<CompoundOperator, ConvertError> {
2614        Ok(match operator {
2615            ast::luau::CompoundOp::PlusEqual(_) => CompoundOperator::Plus,
2616            ast::luau::CompoundOp::MinusEqual(_) => CompoundOperator::Minus,
2617            ast::luau::CompoundOp::StarEqual(_) => CompoundOperator::Asterisk,
2618            ast::luau::CompoundOp::SlashEqual(_) => CompoundOperator::Slash,
2619            ast::luau::CompoundOp::DoubleSlashEqual(_) => CompoundOperator::DoubleSlash,
2620            ast::luau::CompoundOp::PercentEqual(_) => CompoundOperator::Percent,
2621            ast::luau::CompoundOp::CaretEqual(_) => CompoundOperator::Caret,
2622            ast::luau::CompoundOp::TwoDotsEqual(_) => CompoundOperator::Concat,
2623            _ => {
2624                return Err(ConvertError::CompoundOperator {
2625                    operator: operator.to_string(),
2626                })
2627            }
2628        })
2629    }
2630
2631    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2632    fn convert_function_name(
2633        &self,
2634        name: &ast::FunctionName,
2635    ) -> Result<FunctionName, ConvertError> {
2636        let mut name_iter = name
2637            .names()
2638            .iter()
2639            .map(|token_ref| self.convert_token_to_identifier(token_ref));
2640
2641        let mut function_name = FunctionName::new(
2642            name_iter
2643                .next()
2644                .transpose()?
2645                .ok_or(ConvertError::ExpectedFunctionName)?,
2646            name_iter.collect::<Result<Vec<_>, _>>()?,
2647            name.method_name()
2648                .map(|token_ref| self.convert_token_to_identifier(token_ref))
2649                .transpose()?,
2650        );
2651
2652        if self.hold_token_data {
2653            function_name.set_tokens(FunctionNameTokens {
2654                periods: self.extract_tokens_from_punctuation(name.names())?,
2655                colon: name
2656                    .method_colon()
2657                    .map(|colon| self.convert_token(colon))
2658                    .transpose()?,
2659            });
2660        }
2661
2662        Ok(function_name)
2663    }
2664
2665    #[cfg_attr(feature = "tracing", tracing::instrument(level = "trace", skip_all))]
2666    fn convert_variable(&mut self, variable: &'a ast::Var) -> Result<(), ConvertError> {
2667        match variable {
2668            ast::Var::Expression(var_expression) => {
2669                self.work_stack.push(ConvertWork::MakeVariable {
2670                    variable: var_expression,
2671                });
2672                self.push_work(var_expression.prefix());
2673                self.convert_suffixes(var_expression.suffixes())?;
2674            }
2675            ast::Var::Name(name) => {
2676                self.work_stack.push(ConvertWork::PushVariable(
2677                    self.convert_token_to_identifier(name)?.into(),
2678                ));
2679            }
2680            _ => {
2681                return Err(ConvertError::Variable {
2682                    variable: variable.to_string(),
2683                })
2684            }
2685        }
2686        Ok(())
2687    }
2688
2689    fn convert_string_interpolation_segment(
2690        &self,
2691        token: &tokenizer::TokenReference,
2692    ) -> Result<Option<StringSegment>, ConvertError> {
2693        match token.token_type() {
2694            TokenType::InterpolatedString { literal, kind: _ } => {
2695                if !literal.is_empty() {
2696                    let mut segment = StringSegment::new(literal.as_str())
2697                        .expect("unable to convert interpolated string segment");
2698
2699                    if self.hold_token_data {
2700                        let position = self.convert_token_position(token)?;
2701                        let segment_token = Token::new_with_line(
2702                            position.0.saturating_add(1),
2703                            position.1.saturating_sub(1),
2704                            position.2,
2705                        );
2706                        // no trivia since it is grabbing a substring of the token
2707                        segment.set_token(segment_token);
2708                    }
2709
2710                    Ok(Some(segment))
2711                } else {
2712                    Ok(None)
2713                }
2714            }
2715            _ => unreachable!(),
2716        }
2717    }
2718}
2719
2720fn is_argument_variadic(mut r#type: &ast::luau::TypeInfo) -> bool {
2721    use ast::luau::TypeInfo;
2722    loop {
2723        match r#type {
2724            TypeInfo::GenericPack { .. }
2725            | TypeInfo::Variadic { .. }
2726            | TypeInfo::VariadicPack { .. } => break true,
2727            TypeInfo::Optional { base, .. } => {
2728                r#type = base;
2729            }
2730            TypeInfo::Intersection(intersection) => {
2731                r#type = intersection
2732                    .types()
2733                    .first()
2734                    .expect("intersection should have at least one type")
2735                    .value();
2736            }
2737            TypeInfo::Union(union_type) => {
2738                r#type = union_type
2739                    .types()
2740                    .first()
2741                    .expect("union should have at least one type")
2742                    .value();
2743            }
2744            _ => break false,
2745        }
2746    }
2747}
2748
2749fn is_variadic_type(mut r#type: &ast::luau::TypeInfo) -> Option<&tokenizer::TokenReference> {
2750    use ast::luau::TypeInfo;
2751    loop {
2752        match r#type {
2753            TypeInfo::Variadic { ellipsis, .. } | TypeInfo::VariadicPack { ellipsis, .. } => {
2754                break Some(ellipsis)
2755            }
2756            TypeInfo::Optional { base: left, .. } => {
2757                r#type = left;
2758            }
2759            TypeInfo::Intersection(intersection) => {
2760                r#type = intersection
2761                    .types()
2762                    .first()
2763                    .expect("at least one type")
2764                    .value();
2765            }
2766            TypeInfo::Union(union_type) => {
2767                r#type = union_type
2768                    .types()
2769                    .first()
2770                    .expect("at least one type")
2771                    .value();
2772            }
2773            _ => break None,
2774        }
2775    }
2776}
2777
2778#[derive(Debug)]
2779enum ConvertWork<'a> {
2780    Block(&'a ast::Block),
2781    Statement(&'a ast::Stmt),
2782    LastStatement(&'a ast::LastStmt),
2783    Expression(&'a ast::Expression),
2784    Prefix(&'a ast::Prefix),
2785    Arguments(&'a ast::FunctionArgs),
2786    TypeInfo(&'a ast::luau::TypeInfo),
2787    PushExpression(Expression),
2788    PushVariable(Variable),
2789    PushType(Type),
2790    MakeBlock {
2791        block: &'a ast::Block,
2792    },
2793    MakeDoStatement {
2794        statement: &'a ast::Do,
2795    },
2796    MakeReturn {
2797        statement: &'a ast::Return,
2798    },
2799    MakeBinaryExpression {
2800        operator: &'a ast::BinOp,
2801    },
2802    MakeUnaryExpression {
2803        operator: &'a ast::UnOp,
2804    },
2805    MakeParentheseExpression {
2806        contained_span: &'a ast::span::ContainedSpan,
2807    },
2808    MakeIfExpression {
2809        if_expression: &'a ast::luau::IfExpression,
2810    },
2811    MakeFunctionExpression {
2812        body: &'a ast::FunctionBody,
2813        token: &'a tokenizer::TokenReference,
2814    },
2815    MakeRepeatStatement {
2816        statement: &'a ast::Repeat,
2817    },
2818    MakeWhileStatement {
2819        statement: &'a ast::While,
2820    },
2821    MakeNumericForStatement {
2822        statement: &'a ast::NumericFor,
2823    },
2824    MakeGenericForStatement {
2825        statement: &'a ast::GenericFor,
2826    },
2827    MakeFunctionDeclaration {
2828        statement: &'a ast::FunctionDeclaration,
2829    },
2830    MakeFunctionCallExpression {
2831        call: &'a ast::FunctionCall,
2832    },
2833    MakeFunctionCallStatement {
2834        call: &'a ast::FunctionCall,
2835    },
2836    MakeTypeDeclarationStatement {
2837        type_declaration: &'a ast::luau::TypeDeclaration,
2838        export_token: Option<&'a tokenizer::TokenReference>,
2839    },
2840    MakePrefixFromExpression {
2841        prefix: &'a ast::Prefix,
2842    },
2843    MakeLocalFunctionStatement {
2844        statement: &'a ast::LocalFunction,
2845    },
2846    MakeLocalAssignStatement {
2847        statement: &'a ast::LocalAssignment,
2848    },
2849    MakeAssignStatement {
2850        statement: &'a ast::Assignment,
2851    },
2852    MakeCompoundAssignStatement {
2853        statement: &'a ast::luau::CompoundAssignment,
2854    },
2855    MakeIfStatement {
2856        statement: &'a ast::If,
2857    },
2858    MakeArgumentsFromExpressions {
2859        arguments: &'a ast::punctuated::Punctuated<ast::Expression>,
2860        parentheses: &'a ast::span::ContainedSpan,
2861    },
2862    MakeArgumentsFromTableEntries {
2863        table: &'a ast::TableConstructor,
2864    },
2865    MakeTableExpression {
2866        table: &'a ast::TableConstructor,
2867    },
2868    MakeVariable {
2869        variable: &'a ast::VarExpression,
2870    },
2871    MakePrefixExpression {
2872        variable: &'a ast::VarExpression,
2873    },
2874    MakeInterpolatedString {
2875        interpolated_string: &'a ast::luau::InterpolatedString,
2876    },
2877    MakeFunctionReturnType {
2878        type_info: &'a ast::luau::TypeInfo,
2879    },
2880    MakeVariadicTypePack {
2881        ellipsis: &'a tokenizer::TokenReference,
2882    },
2883    MakeArrayType {
2884        braces: &'a ast::span::ContainedSpan,
2885    },
2886    MakeOptionalType {
2887        question_mark: &'a tokenizer::TokenReference,
2888    },
2889    MakeUnionType {
2890        length: usize,
2891        leading_token: Option<&'a tokenizer::TokenReference>,
2892        separators: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
2893    },
2894    MakeIntersectionType {
2895        length: usize,
2896        leading_token: Option<&'a tokenizer::TokenReference>,
2897        separators: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
2898    },
2899    MakeTableType {
2900        braces: &'a ast::span::ContainedSpan,
2901        fields: &'a ast::punctuated::Punctuated<ast::luau::TypeField>,
2902    },
2903    MakeExpressionType {
2904        typeof_token: &'a tokenizer::TokenReference,
2905        parentheses: &'a ast::span::ContainedSpan,
2906    },
2907    MakeFunctionType {
2908        generics: &'a Option<ast::luau::GenericDeclaration>,
2909        parentheses: &'a ast::span::ContainedSpan,
2910        arguments: &'a ast::punctuated::Punctuated<ast::luau::TypeArgument>,
2911        arrow: &'a tokenizer::TokenReference,
2912    },
2913    MakeGenericType {
2914        base: &'a tokenizer::TokenReference,
2915        module: Option<(&'a tokenizer::TokenReference, &'a tokenizer::TokenReference)>,
2916    },
2917    MakeTypeParameters {
2918        arrows: &'a ast::span::ContainedSpan,
2919        generics: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
2920    },
2921    MakeTypeCast {
2922        type_assertion: &'a ast::luau::TypeAssertion,
2923    },
2924    MakeParentheseType {
2925        parentheses: &'a ast::span::ContainedSpan,
2926    },
2927    MakeTypePack {
2928        parentheses: &'a ast::span::ContainedSpan,
2929        types: &'a ast::punctuated::Punctuated<ast::luau::TypeInfo>,
2930    },
2931}
2932
2933impl<'a> From<&'a ast::Block> for ConvertWork<'a> {
2934    fn from(block: &'a ast::Block) -> Self {
2935        ConvertWork::Block(block)
2936    }
2937}
2938
2939impl<'a> From<&'a ast::Stmt> for ConvertWork<'a> {
2940    fn from(statement: &'a ast::Stmt) -> Self {
2941        ConvertWork::Statement(statement)
2942    }
2943}
2944
2945impl<'a> From<&'a ast::LastStmt> for ConvertWork<'a> {
2946    fn from(statement: &'a ast::LastStmt) -> Self {
2947        ConvertWork::LastStatement(statement)
2948    }
2949}
2950
2951impl<'a> From<&'a ast::Expression> for ConvertWork<'a> {
2952    fn from(expression: &'a ast::Expression) -> Self {
2953        ConvertWork::Expression(expression)
2954    }
2955}
2956
2957impl<'a> From<&'a ast::Prefix> for ConvertWork<'a> {
2958    fn from(prefix: &'a ast::Prefix) -> Self {
2959        ConvertWork::Prefix(prefix)
2960    }
2961}
2962
2963impl<'a> From<&'a ast::FunctionArgs> for ConvertWork<'a> {
2964    fn from(arguments: &'a ast::FunctionArgs) -> Self {
2965        ConvertWork::Arguments(arguments)
2966    }
2967}
2968
2969impl<'a> From<&'a ast::luau::TypeInfo> for ConvertWork<'a> {
2970    fn from(type_info: &'a ast::luau::TypeInfo) -> Self {
2971        ConvertWork::TypeInfo(type_info)
2972    }
2973}
2974
2975#[derive(Clone, Debug)]
2976pub(crate) enum ConvertError {
2977    Statement {
2978        statement: String,
2979    },
2980    LastStatement {
2981        statement: String,
2982    },
2983    Variable {
2984        variable: String,
2985    },
2986    FunctionArguments {
2987        arguments: String,
2988    },
2989    Call {
2990        call: String,
2991    },
2992    Index {
2993        index: String,
2994    },
2995    Suffix {
2996        suffix: String,
2997    },
2998    Prefix {
2999        prefix: String,
3000    },
3001    Number {
3002        number: String,
3003        parsing_error: String,
3004    },
3005    Expression {
3006        expression: String,
3007    },
3008    FunctionParameter {
3009        parameter: String,
3010    },
3011    FunctionParameters {
3012        parameters: String,
3013    },
3014    TableEntry {
3015        entry: String,
3016    },
3017    BinaryOperator {
3018        operator: String,
3019    },
3020    CompoundOperator {
3021        operator: String,
3022    },
3023    UnaryOperator {
3024        operator: String,
3025    },
3026    InterpolatedString {
3027        string: String,
3028    },
3029    String {
3030        string: String,
3031    },
3032    TypeInfo {
3033        type_info: String,
3034    },
3035    TableTypeProperty {
3036        property: String,
3037    },
3038    GenericDeclaration {
3039        generics: String,
3040    },
3041    UnexpectedTrivia(tokenizer::TokenKind),
3042    ExpectedFunctionName,
3043    TokenPositionNotFound {
3044        token: String,
3045    },
3046    InternalStack {
3047        kind: &'static str,
3048    },
3049}
3050
3051impl fmt::Display for ConvertError {
3052    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
3053        let (kind, code) = match self {
3054            ConvertError::Statement { statement } => ("statement", statement),
3055            ConvertError::LastStatement { statement } => ("last statement", statement),
3056            ConvertError::Variable { variable } => ("variable", variable),
3057            ConvertError::FunctionArguments { arguments } => ("function arguments", arguments),
3058            ConvertError::Call { call } => ("function call", call),
3059            ConvertError::Index { index } => ("index expression", index),
3060            ConvertError::Suffix { suffix } => ("suffix", suffix),
3061            ConvertError::Prefix { prefix } => ("prefix", prefix),
3062            ConvertError::Number {
3063                number,
3064                parsing_error,
3065            } => {
3066                return write!(
3067                    f,
3068                    "unable to convert number from `{}` ({})",
3069                    number, parsing_error
3070                )
3071            }
3072            ConvertError::InterpolatedString { string } => ("interpolated string", string),
3073            ConvertError::Expression { expression } => ("expression", expression),
3074            ConvertError::FunctionParameter { parameter } => ("parameter", parameter),
3075            ConvertError::FunctionParameters { parameters } => ("parameters", parameters),
3076            ConvertError::TableEntry { entry } => ("table entry", entry),
3077            ConvertError::BinaryOperator { operator } => ("binary operator", operator),
3078            ConvertError::CompoundOperator { operator } => ("compound operator", operator),
3079            ConvertError::UnaryOperator { operator } => ("unary operator", operator),
3080            ConvertError::String { string } => ("string", string),
3081            ConvertError::TypeInfo { type_info } => ("type", type_info),
3082            ConvertError::TableTypeProperty { property } => ("table type property", property),
3083            ConvertError::GenericDeclaration { generics } => ("generics", generics),
3084            ConvertError::UnexpectedTrivia(token_kind) => {
3085                return write!(
3086                    f,
3087                    "unable to convert trivia from token kind `{:?}`",
3088                    token_kind
3089                );
3090            }
3091            ConvertError::ExpectedFunctionName => {
3092                return write!(f, "unable to convert empty function name");
3093            }
3094            ConvertError::TokenPositionNotFound { token } => {
3095                return write!(
3096                    f,
3097                    "unable to convert token '{}' because its position is missing",
3098                    token
3099                );
3100            }
3101            ConvertError::InternalStack { kind } => {
3102                return write!(
3103                    f,
3104                    "internal conversion stack expected to find an item of `{}`",
3105                    kind
3106                )
3107            }
3108        };
3109        write!(f, "unable to convert {} from `{}`", kind, code)
3110    }
3111}
3112
3113fn get_binary_operator_token(
3114    operator: &ast::BinOp,
3115) -> Result<&tokenizer::TokenReference, ConvertError> {
3116    use ast::BinOp;
3117
3118    match operator {
3119        BinOp::And(token)
3120        | BinOp::Caret(token)
3121        | BinOp::GreaterThan(token)
3122        | BinOp::GreaterThanEqual(token)
3123        | BinOp::LessThan(token)
3124        | BinOp::LessThanEqual(token)
3125        | BinOp::Minus(token)
3126        | BinOp::Or(token)
3127        | BinOp::Percent(token)
3128        | BinOp::Plus(token)
3129        | BinOp::Slash(token)
3130        | BinOp::DoubleSlash(token)
3131        | BinOp::Star(token)
3132        | BinOp::TildeEqual(token)
3133        | BinOp::TwoDots(token)
3134        | BinOp::TwoEqual(token) => Ok(token),
3135        _ => Err(ConvertError::BinaryOperator {
3136            operator: operator.to_string(),
3137        }),
3138    }
3139}
3140
3141fn get_unary_operator_token(
3142    operator: &ast::UnOp,
3143) -> Result<&tokenizer::TokenReference, ConvertError> {
3144    use ast::UnOp;
3145
3146    match operator {
3147        UnOp::Minus(token) | UnOp::Not(token) | UnOp::Hash(token) => Ok(token),
3148        _ => Err(ConvertError::UnaryOperator {
3149            operator: operator.to_string(),
3150        }),
3151    }
3152}
3153
3154fn get_compound_operator_token(
3155    operator: &ast::luau::CompoundOp,
3156) -> Result<&tokenizer::TokenReference, ConvertError> {
3157    use ast::luau::CompoundOp;
3158
3159    match operator {
3160        CompoundOp::PlusEqual(token)
3161        | CompoundOp::MinusEqual(token)
3162        | CompoundOp::StarEqual(token)
3163        | CompoundOp::SlashEqual(token)
3164        | CompoundOp::DoubleSlashEqual(token)
3165        | CompoundOp::PercentEqual(token)
3166        | CompoundOp::CaretEqual(token)
3167        | CompoundOp::TwoDotsEqual(token) => Ok(token),
3168        _ => Err(ConvertError::CompoundOperator {
3169            operator: operator.to_string(),
3170        }),
3171    }
3172}
3173
3174#[cfg(test)]
3175mod test {
3176    use super::*;
3177
3178    mod convert_error {
3179        use super::*;
3180
3181        #[test]
3182        fn display_unexpected_trivia_symbol() {
3183            assert_eq!(
3184                ConvertError::UnexpectedTrivia(tokenizer::TokenKind::Symbol).to_string(),
3185                "unable to convert trivia from token kind `Symbol`"
3186            )
3187        }
3188
3189        #[test]
3190        fn display_unexpected_trivia_eof() {
3191            assert_eq!(
3192                ConvertError::UnexpectedTrivia(tokenizer::TokenKind::Eof).to_string(),
3193                "unable to convert trivia from token kind `Eof`"
3194            )
3195        }
3196    }
3197}